[
  {
    "path": ".gitattributes",
    "content": "*.a filter=lfs diff=lfs merge=lfs -text\n*.bc filter=lfs diff=lfs merge=lfs -text\n*.ttc filter=lfs diff=lfs merge=lfs -text\n*.ttf filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".gitignore",
    "content": "skia_bindings.bc\n.idea/\n/cmake-build-debug/\n/CMakeLists.txt\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 Erik De Rijcke\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "This project has been superseded by Google's [CanvasKit](https://skia.org/user/modules/canvaskit)\n\n# skia-wasm-port\nPort of the Skia drawing library to wasm, for use in node &amp; browser.\n\n[Skia](https://skia.org/) is the drawing library used by Chrome and Firefox to provide the actual rendering of web pages.\n\n# Goal\nThe goal of this project is to make skia available to Javascript without the need to rely on native code.\nThe end result would be a library able to do fast complex 2d drawings in both node & the browser.\n\n# State\nCurrently a limited set of skia functions are defined (wip), so the library is not very usable yet. You do get a\nstatic archive that contains all llvm bitcode needed to generate the final wasm, as well as a script to generate this\nllvm bitcode from Skia sources. This library will become usable as soon as enough bindings are defined.\n\nAn example is currently available under `example_star.js` that can be run with node. Running in the\nbrowser is also possible if the png file saving is adjusted accordingly. The example exactly matches the one found\non the Skia [website](https://skia.org/user/api/skcanvas_creation).\n\n`example_star.js` demonstrates path rendering:\n\n![alt text](https://raw.githubusercontent.com/Zubnix/skia-wasm-port/master/out_star.png)\n\n`example_gradient.js` demonstrates gradient shader:\n\n![alt text](https://raw.githubusercontent.com/Zubnix/skia-wasm-port/master/out_gradient.png)\n\n`example_text.js` demonstrates font rendering:\n\n![alt text](https://raw.githubusercontent.com/Zubnix/skia-wasm-port/master/out_text.png)\n\n# WebGL\n\nSkia WASM  can also run in the browser while utilizing a WebGL accelerated back-end. This however requires\nsome modifications to the existing Skia code, which is expected to be implemented upstream in the future.\nThe provided Skia bitcode in this repository includes the needed WebGL changes. More information can be found\n[here](https://bugs.chromium.org/p/skia/issues/detail?id=8041)\n\nA WebGL port of the Skia SDL [example](https://github.com/google/skia/blob/master/example/SkiaSDLExample.cpp) can be found in `docs/webgl.js`. You can try it out [here](https://zubnix.github.io/skia-wasm-port/). If the page fails to load, try disabling any adblocker.\n\n# Defining bindings\nBindings are defined using [Embind](https://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/embind.html).\nCurrently defined bindings live in `skia_bindings.cpp`.\n\n# Building Bindings\nThis library requires [git lfs](https://git-lfs.github.com/)\n\nMake sure you have the emscripten sdk installed. Current code has been tested on the linux-incoming-64bit version.\n\nMake sure you define the correct paths in `build_bindings.sh` and run `build_bindings.sh`. You should get a `skia.js` \nand a `skia.wasm` file. To test the build, simply run `example_star.js`.\n\n\n# Building Skia bitcode\nClone the official Skia git repository and copy over the `build_skia_wasm_bitcode.sh` script together with the `wasm_compatible_build.patch`,\nthen simply execute `bash build_skia_wasm_bitcode.sh`. Make sure you define the correct paths in the build script!\n"
  },
  {
    "path": "build_bindings.sh",
    "content": "#!/usr/bin/env bash\n\n#eg /home/john/emsdk-portable\n#EMSDK=\"path/to/em/sdk\"\nEMSDK=\"/home/zubzub/emsdk-portable\"\n#eg 1.37.27\n#EM_VERSION=\"0.0.0\"\nEM_VERSION=\"incoming\"\n\n#export EMCC_DEBUG=1\n\nprintf \"Compiling bindings to bitcode\\n\"\n${EMSDK}/emscripten/${EM_VERSION}/emcc -O3 -std=c++11 \\\n-Iinclude/android \\\n-Iinclude/atlastext \\\n-Iinclude/c \\\n-Iinclude/codec \\\n-Iinclude/config \\\n-Iinclude/core \\\n-Iinclude/effects \\\n-Iinclude/encode \\\n-Iinclude/gpu \\\n-Iinclude/gpu/gl \\\n-Iinclude/pathops \\\n-Iinclude/ports \\\n-Iinclude/svg \\\n-Iinclude/utils \\\n-Iinclude/views \\\n-Iinclude/utils/mac \\\nskia_bindings.cpp -o skia_bindings.bc\n\nprintf \"Generating final wasm\\n\"\n${EMSDK}/emscripten/${EM_VERSION}/emcc -O3 -std=c++11 --bind skia_bindings.bc libskia.a -s ALLOW_MEMORY_GROWTH=1 -s USE_WEBGL2=1 -s NO_EXIT_RUNTIME=1 -s USE_FREETYPE=1 -s USE_LIBPNG=1 -s WASM=1 -s MODULARIZE=1 -s FORCE_FILESYSTEM=0 -o skia.js"
  },
  {
    "path": "build_skia_wasm_bitcode.sh",
    "content": "#!/bin/bash\n\npatch -p0 < wasm_compatible_build.patch\n\n#eg /home/john/emsdk-portable\nEMSDK=\"/home/zubzub/emsdk-portable\"\n#eg 1.37.27\nEM_VERSION=\"incoming\"\n\nsource ${EMSDK}/emsdk_env.sh\n\n./bin/gn gen ./out/Build-wasm-Release/Release --args=\"cc=\\\"${EMSDK}/emscripten/${EM_VERSION}/emcc\\\" extra_cflags_cc=[\\\"-frtti\\\",\\\"-s\\\",\\\"USE_FREETYPE=1\\\"] cxx=\\\"${EMSDK}/emscripten/${EM_VERSION}/em++\\\" extra_cflags=[\\\"-Wno-unknown-warning-option\\\",\\\"-s\\\",\\\"USE_FREETYPE=1\\\",\\\"-s\\\",\\\"USE_LIBPNG=1\\\"] \\\nis_debug=false \\\nis_official_build=true \\\nis_component_build=false \\\ntarget_cpu=\\\"wasm\\\" \\\n\\\nskia_use_egl=true \\\nskia_use_vulkan=false \\\nskia_use_libwebp=false \\\nskia_use_libpng=true \\\nskia_use_lua=false \\\nskia_use_dng_sdk=false \\\nskia_use_fontconfig=false \\\nskia_use_libjpeg_turbo=false \\\nskia_use_libheif=false \\\nskia_use_expat=false \\\nskia_use_vulkan=false \\\nskia_use_freetype=true \\\nskia_use_icu=false \\\nskia_use_expat=false \\\nskia_use_piex=false \\\nskia_use_zlib=true \\\n\\\nskia_enable_gpu=true \\\nskia_enable_pdf=false\"\n\nninja -k 0 -C out/Build-wasm-Release/Release\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n    <title>WebAssembly WebGL Skia</title>\n    <script src=\"./skia.js\"></script>\n    <script src=\"webgl.js\"></script>\n</head>\n<body style=\"margin: 0; overflow: hidden;\">\n</body>\n</html>"
  },
  {
    "path": "docs/skia.js",
    "content": "var Module = function(Module) {\n  Module = Module || {};\n\nvar Module=typeof Module!==\"undefined\"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}Module[\"arguments\"]=[];Module[\"thisProgram\"]=\"./this.program\";Module[\"quit\"]=(function(status,toThrow){throw toThrow});Module[\"preRun\"]=[];Module[\"postRun\"]=[];var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module[\"ENVIRONMENT\"]){if(Module[\"ENVIRONMENT\"]===\"WEB\"){ENVIRONMENT_IS_WEB=true}else if(Module[\"ENVIRONMENT\"]===\"WORKER\"){ENVIRONMENT_IS_WORKER=true}else if(Module[\"ENVIRONMENT\"]===\"NODE\"){ENVIRONMENT_IS_NODE=true}else if(Module[\"ENVIRONMENT\"]===\"SHELL\"){ENVIRONMENT_IS_SHELL=true}else{throw new Error(\"Module['ENVIRONMENT'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.\")}}else{ENVIRONMENT_IS_WEB=typeof window===\"object\";ENVIRONMENT_IS_WORKER=typeof importScripts===\"function\";ENVIRONMENT_IS_NODE=typeof process===\"object\"&&typeof require===\"function\"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){var nodeFS;var nodePath;Module[\"read\"]=function shell_read(filename,binary){var ret;if(!nodeFS)nodeFS=require(\"fs\");if(!nodePath)nodePath=require(\"path\");filename=nodePath[\"normalize\"](filename);ret=nodeFS[\"readFileSync\"](filename);return binary?ret:ret.toString()};Module[\"readBinary\"]=function readBinary(filename){var ret=Module[\"read\"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process[\"argv\"].length>1){Module[\"thisProgram\"]=process[\"argv\"][1].replace(/\\\\/g,\"/\")}Module[\"arguments\"]=process[\"argv\"].slice(2);process[\"on\"](\"uncaughtException\",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));process[\"on\"](\"unhandledRejection\",(function(reason,p){process[\"exit\"](1)}));Module[\"inspect\"]=(function(){return\"[Emscripten Module object]\"})}else if(ENVIRONMENT_IS_SHELL){if(typeof read!=\"undefined\"){Module[\"read\"]=function shell_read(f){return read(f)}}Module[\"readBinary\"]=function readBinary(f){var data;if(typeof readbuffer===\"function\"){return new Uint8Array(readbuffer(f))}data=read(f,\"binary\");assert(typeof data===\"object\");return data};if(typeof scriptArgs!=\"undefined\"){Module[\"arguments\"]=scriptArgs}else if(typeof arguments!=\"undefined\"){Module[\"arguments\"]=arguments}if(typeof quit===\"function\"){Module[\"quit\"]=(function(status,toThrow){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module[\"read\"]=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){Module[\"readBinary\"]=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.responseType=\"arraybuffer\";xhr.send(null);return new Uint8Array(xhr.response)}}Module[\"readAsync\"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,true);xhr.responseType=\"arraybuffer\";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)};Module[\"setWindowTitle\"]=(function(title){document.title=title})}else{throw new Error(\"not compiled for this environment\")}Module[\"print\"]=typeof console!==\"undefined\"?console.log.bind(console):typeof print!==\"undefined\"?print:null;Module[\"printErr\"]=typeof printErr!==\"undefined\"?printErr:typeof console!==\"undefined\"&&console.warn.bind(console)||Module[\"print\"];Module.print=Module[\"print\"];Module.printErr=Module[\"printErr\"];for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var STACK_ALIGN=16;function staticAlloc(size){assert(!staticSealed);var ret=STATICTOP;STATICTOP=STATICTOP+size+15&-16;return ret}function dynamicAlloc(size){assert(DYNAMICTOP_PTR);var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;var ret=size=Math.ceil(size/factor)*factor;return ret}function getNativeTypeSize(type){switch(type){case\"i1\":case\"i8\":return 1;case\"i16\":return 2;case\"i32\":return 4;case\"i64\":return 8;case\"float\":return 4;case\"double\":return 8;default:{if(type[type.length-1]===\"*\"){return 4}else if(type[0]===\"i\"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;Module.printErr(text)}}var jsCallStartIndex=1;var functionPointers=new Array(0);function addFunction(func,sig){var base=0;for(var i=base;i<base+0;i++){if(!functionPointers[i]){functionPointers[i]=func;return jsCallStartIndex+i}}throw\"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.\"}var GLOBAL_BASE=1024;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort(\"Assertion failed: \"+text)}}function setValue(ptr,value,type,noSafe){type=type||\"i8\";if(type.charAt(type.length-1)===\"*\")type=\"i32\";switch(type){case\"i1\":HEAP8[ptr>>0]=value;break;case\"i8\":HEAP8[ptr>>0]=value;break;case\"i16\":HEAP16[ptr>>1]=value;break;case\"i32\":HEAP32[ptr>>2]=value;break;case\"i64\":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case\"float\":HEAPF32[ptr>>2]=value;break;case\"double\":HEAPF64[ptr>>3]=value;break;default:abort(\"invalid type for setValue: \"+type)}}var ALLOC_NORMAL=0;var ALLOC_STATIC=2;var ALLOC_NONE=4;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab===\"number\"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types===\"string\"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc===\"function\"?_malloc:staticAlloc,stackAlloc,staticAlloc,dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var stop;ptr=ret;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType===\"i8\"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];type=singleType||types[i];if(type===0){i++;continue}if(type==\"i64\")type=\"i32\";setValue(ret+i,curr,type);if(previousType!==type){typeSize=getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}function Pointer_stringify(ptr,length){if(length===0||!ptr)return\"\";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret=\"\";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return UTF8ToString(ptr)}var UTF8Decoder=typeof TextDecoder!==\"undefined\"?new TextDecoder(\"utf8\"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str=\"\";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}var UTF16Decoder=typeof TextDecoder!==\"undefined\"?new TextDecoder(\"utf-16le\"):undefined;function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function demangle(func){return func}function demangleAll(text){var regex=/__Z[\\w\\d_]+/g;return text.replace(regex,(function(x){var y=demangle(x);return x===y?x:x+\" [\"+y+\"]\"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return\"(no stack trace available)\"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module[\"extraStackTrace\"])js+=\"\\n\"+Module[\"extraStackTrace\"]();return demangleAll(js)}var PAGE_SIZE=16384;var WASM_PAGE_SIZE=65536;var ASMJS_PAGE_SIZE=16777216;var MIN_TOTAL_MEMORY=16777216;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBuffer(buf){Module[\"buffer\"]=buffer=buf}function updateGlobalBufferViews(){Module[\"HEAP8\"]=HEAP8=new Int8Array(buffer);Module[\"HEAP16\"]=HEAP16=new Int16Array(buffer);Module[\"HEAP32\"]=HEAP32=new Int32Array(buffer);Module[\"HEAPU8\"]=HEAPU8=new Uint8Array(buffer);Module[\"HEAPU16\"]=HEAPU16=new Uint16Array(buffer);Module[\"HEAPU32\"]=HEAPU32=new Uint32Array(buffer);Module[\"HEAPF32\"]=HEAPF32=new Float32Array(buffer);Module[\"HEAPF64\"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort(\"Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value \"+TOTAL_MEMORY+\", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 \")}if(!Module[\"reallocBuffer\"])Module[\"reallocBuffer\"]=(function(size){var ret;try{if(ArrayBuffer.transfer){ret=ArrayBuffer.transfer(buffer,size)}else{var oldHEAP8=HEAP8;ret=new ArrayBuffer(size);var temp=new Int8Array(ret);temp.set(oldHEAP8)}}catch(e){return false}var success=_emscripten_replace_memory(ret);if(!success)return false;return ret});function enlargeMemory(){var PAGE_MULTIPLE=Module[\"usingWasm\"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;var LIMIT=2147483648-PAGE_MULTIPLE;if(HEAP32[DYNAMICTOP_PTR>>2]>LIMIT){return false}var OLD_TOTAL_MEMORY=TOTAL_MEMORY;TOTAL_MEMORY=Math.max(TOTAL_MEMORY,MIN_TOTAL_MEMORY);while(TOTAL_MEMORY<HEAP32[DYNAMICTOP_PTR>>2]){if(TOTAL_MEMORY<=536870912){TOTAL_MEMORY=alignUp(2*TOTAL_MEMORY,PAGE_MULTIPLE)}else{TOTAL_MEMORY=Math.min(alignUp((3*TOTAL_MEMORY+2147483648)/4,PAGE_MULTIPLE),LIMIT)}}var replacement=Module[\"reallocBuffer\"](TOTAL_MEMORY);if(!replacement||replacement.byteLength!=TOTAL_MEMORY){TOTAL_MEMORY=OLD_TOTAL_MEMORY;return false}updateGlobalBuffer(replacement);updateGlobalBufferViews();return true}var byteLength;try{byteLength=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,\"byteLength\").get);byteLength(new ArrayBuffer(4))}catch(e){byteLength=(function(buffer){return buffer.byteLength})}var TOTAL_STACK=Module[\"TOTAL_STACK\"]||5242880;var TOTAL_MEMORY=Module[\"TOTAL_MEMORY\"]||16777216;if(TOTAL_MEMORY<TOTAL_STACK)Module.printErr(\"TOTAL_MEMORY should be larger than TOTAL_STACK, was \"+TOTAL_MEMORY+\"! (TOTAL_STACK=\"+TOTAL_STACK+\")\");if(Module[\"buffer\"]){buffer=Module[\"buffer\"]}else{if(typeof WebAssembly===\"object\"&&typeof WebAssembly.Memory===\"function\"){Module[\"wasmMemory\"]=new WebAssembly.Memory({\"initial\":TOTAL_MEMORY/WASM_PAGE_SIZE});buffer=Module[\"wasmMemory\"].buffer}else{buffer=new ArrayBuffer(TOTAL_MEMORY)}Module[\"buffer\"]=buffer}updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}HEAP32[0]=1668509029;HEAP16[1]=25459;if(HEAPU8[2]!==115||HEAPU8[3]!==99)throw\"Runtime error: expected the system to be little-endian!\";function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback==\"function\"){callback();continue}var func=callback.func;if(typeof func===\"number\"){if(callback.arg===undefined){Module[\"dynCall_v\"](func)}else{Module[\"dynCall_vi\"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module[\"preRun\"]){if(typeof Module[\"preRun\"]==\"function\")Module[\"preRun\"]=[Module[\"preRun\"]];while(Module[\"preRun\"].length){addOnPreRun(Module[\"preRun\"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module[\"postRun\"]){if(typeof Module[\"postRun\"]==\"function\")Module[\"postRun\"]=[Module[\"postRun\"]];while(Module[\"postRun\"].length){addOnPostRun(Module[\"postRun\"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_max=Math.max;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module[\"preloadedImages\"]={};Module[\"preloadedAudios\"]={};var dataURIPrefix=\"data:application/octet-stream;base64,\";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}function integrateWasmJS(){var wasmTextFile=\"skia.wast\";var wasmBinaryFile=\"skia.wasm\";var asmjsCodeFile=\"skia.temp.asm.js\";if(typeof Module[\"locateFile\"]===\"function\"){if(!isDataURI(wasmTextFile)){wasmTextFile=Module[\"locateFile\"](wasmTextFile)}if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=Module[\"locateFile\"](wasmBinaryFile)}if(!isDataURI(asmjsCodeFile)){asmjsCodeFile=Module[\"locateFile\"](asmjsCodeFile)}}var wasmPageSize=64*1024;var info={\"global\":null,\"env\":null,\"asm2wasm\":{\"f64-rem\":(function(x,y){return x%y}),\"debugger\":(function(){debugger})},\"parent\":Module};var exports=null;function mergeMemory(newBuffer){var oldBuffer=Module[\"buffer\"];if(newBuffer.byteLength<oldBuffer.byteLength){Module[\"printErr\"](\"the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here\")}var oldView=new Int8Array(oldBuffer);var newView=new Int8Array(newBuffer);newView.set(oldView);updateGlobalBuffer(newBuffer);updateGlobalBufferViews()}function fixImports(imports){return imports}function getBinary(){try{if(Module[\"wasmBinary\"]){return new Uint8Array(Module[\"wasmBinary\"])}if(Module[\"readBinary\"]){return Module[\"readBinary\"](wasmBinaryFile)}else{throw\"on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)\"}}catch(err){abort(err)}}function getBinaryPromise(){if(!Module[\"wasmBinary\"]&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch===\"function\"){return fetch(wasmBinaryFile,{credentials:\"same-origin\"}).then((function(response){if(!response[\"ok\"]){throw\"failed to load wasm binary file at '\"+wasmBinaryFile+\"'\"}return response[\"arrayBuffer\"]()})).catch((function(){return getBinary()}))}return new Promise((function(resolve,reject){resolve(getBinary())}))}function doNativeWasm(global,env,providedBuffer){if(typeof WebAssembly!==\"object\"){Module[\"printErr\"](\"no native wasm support detected\");return false}if(!(Module[\"wasmMemory\"]instanceof WebAssembly.Memory)){Module[\"printErr\"](\"no native wasm Memory in use\");return false}env[\"memory\"]=Module[\"wasmMemory\"];info[\"global\"]={\"NaN\":NaN,\"Infinity\":Infinity};info[\"global.Math\"]=Math;info[\"env\"]=env;function receiveInstance(instance,module){exports=instance.exports;if(exports.memory)mergeMemory(exports.memory);Module[\"asm\"]=exports;Module[\"usingWasm\"]=true;removeRunDependency(\"wasm-instantiate\")}addRunDependency(\"wasm-instantiate\");if(Module[\"instantiateWasm\"]){try{return Module[\"instantiateWasm\"](info,receiveInstance)}catch(e){Module[\"printErr\"](\"Module.instantiateWasm callback failed with error: \"+e);return false}}function receiveInstantiatedSource(output){receiveInstance(output[\"instance\"],output[\"module\"])}function instantiateArrayBuffer(receiver){getBinaryPromise().then((function(binary){return WebAssembly.instantiate(binary,info)})).then(receiver).catch((function(reason){Module[\"printErr\"](\"failed to asynchronously prepare wasm: \"+reason);abort(reason)}))}if(!Module[\"wasmBinary\"]&&typeof WebAssembly.instantiateStreaming===\"function\"&&!isDataURI(wasmBinaryFile)&&typeof fetch===\"function\"){WebAssembly.instantiateStreaming(fetch(wasmBinaryFile,{credentials:\"same-origin\"}),info).then(receiveInstantiatedSource).catch((function(reason){Module[\"printErr\"](\"wasm streaming compile failed: \"+reason);Module[\"printErr\"](\"falling back to ArrayBuffer instantiation\");instantiateArrayBuffer(receiveInstantiatedSource)}))}else{instantiateArrayBuffer(receiveInstantiatedSource)}return{}}Module[\"asmPreload\"]=Module[\"asm\"];var asmjsReallocBuffer=Module[\"reallocBuffer\"];var wasmReallocBuffer=(function(size){var PAGE_MULTIPLE=Module[\"usingWasm\"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;size=alignUp(size,PAGE_MULTIPLE);var old=Module[\"buffer\"];var oldSize=old.byteLength;if(Module[\"usingWasm\"]){try{var result=Module[\"wasmMemory\"].grow((size-oldSize)/wasmPageSize);if(result!==(-1|0)){return Module[\"buffer\"]=Module[\"wasmMemory\"].buffer}else{return null}}catch(e){return null}}});Module[\"reallocBuffer\"]=(function(size){if(finalMethod===\"asmjs\"){return asmjsReallocBuffer(size)}else{return wasmReallocBuffer(size)}});var finalMethod=\"\";Module[\"asm\"]=(function(global,env,providedBuffer){env=fixImports(env);if(!env[\"table\"]){var TABLE_SIZE=Module[\"wasmTableSize\"];if(TABLE_SIZE===undefined)TABLE_SIZE=1024;var MAX_TABLE_SIZE=Module[\"wasmMaxTableSize\"];if(typeof WebAssembly===\"object\"&&typeof WebAssembly.Table===\"function\"){if(MAX_TABLE_SIZE!==undefined){env[\"table\"]=new WebAssembly.Table({\"initial\":TABLE_SIZE,\"maximum\":MAX_TABLE_SIZE,\"element\":\"anyfunc\"})}else{env[\"table\"]=new WebAssembly.Table({\"initial\":TABLE_SIZE,element:\"anyfunc\"})}}else{env[\"table\"]=new Array(TABLE_SIZE)}Module[\"wasmTable\"]=env[\"table\"]}if(!env[\"memoryBase\"]){env[\"memoryBase\"]=Module[\"STATIC_BASE\"]}if(!env[\"tableBase\"]){env[\"tableBase\"]=0}var exports;exports=doNativeWasm(global,env,providedBuffer);assert(exports,\"no binaryen method succeeded.\");return exports})}integrateWasmJS();var ASM_CONSTS=[(function(){Module[\"SkSurfaceProps\"][\"Flags\"]=Module[\"SkSurfaceProps.Flags\"];delete Module[\"SkSurfaceProps.Flags\"]}),(function(){Module[\"SkPath\"][\"FillType\"]=Module[\"SkPath.FillType\"];delete Module[\"SkPath.FillType\"]}),(function(){Module[\"SkPaint\"][\"Style\"]=Module[\"SkPaint.Style\"];delete Module[\"SkPaint.Flags\"]}),(function(){Module[\"SkShader\"][\"TileMode\"]=Module[\"SkShader.TileMode\"];delete Module[\"SkShader.TileMode\"]})];function _emscripten_asm_const_i(code){return ASM_CONSTS[code]()}STATIC_BASE=GLOBAL_BASE;STATICTOP=STATIC_BASE+429888;__ATINIT__.push({func:(function(){__GLOBAL__sub_I_skia_bindings_cpp()})},{func:(function(){__GLOBAL__sub_I_bind_cpp()})});var STATIC_BUMP=429888;Module[\"STATIC_BASE\"]=STATIC_BASE;Module[\"STATIC_BUMP\"]=STATIC_BUMP;STATICTOP+=16;function ___cxa_allocate_exception(size){return _malloc(size)}var EXCEPTIONS={last:0,caught:[],infos:{},deAdjust:(function(adjusted){if(!adjusted||EXCEPTIONS.infos[adjusted])return adjusted;for(var key in EXCEPTIONS.infos){var ptr=+key;var info=EXCEPTIONS.infos[ptr];if(info.adjusted===adjusted){return ptr}}return adjusted}),addRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount++}),decRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];assert(info.refcount>0);info.refcount--;if(info.refcount===0&&!info.rethrown){if(info.destructor){Module[\"dynCall_vi\"](info.destructor,ptr)}delete EXCEPTIONS.infos[ptr];___cxa_free_exception(ptr)}}),clearRef:(function(ptr){if(!ptr)return;var info=EXCEPTIONS.infos[ptr];info.refcount=0})};function ___cxa_pure_virtual(){ABORT=true;throw\"Pure virtual function called!\"}function ___cxa_throw(ptr,type,destructor){EXCEPTIONS.infos[ptr]={ptr:ptr,adjusted:ptr,type:type,destructor:destructor,refcount:0,caught:false,rethrown:false};EXCEPTIONS.last=ptr;if(!(\"uncaught_exception\"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exception=1}else{__ZSt18uncaught_exceptionv.uncaught_exception++}throw ptr+\" - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.\"}function ___cxa_uncaught_exception(){return!!__ZSt18uncaught_exceptionv.uncaught_exception}function ___lock(){}var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};function ___setErrNo(value){if(Module[\"___errno_location\"])HEAP32[Module[\"___errno_location\"]()>>2]=value;return value}function ___map_file(pathname,size){___setErrNo(ERRNO_CODES.EPERM);return-1}var ERRNO_MESSAGES={0:\"Success\",1:\"Not super-user\",2:\"No such file or directory\",3:\"No such process\",4:\"Interrupted system call\",5:\"I/O error\",6:\"No such device or address\",7:\"Arg list too long\",8:\"Exec format error\",9:\"Bad file number\",10:\"No children\",11:\"No more processes\",12:\"Not enough core\",13:\"Permission denied\",14:\"Bad address\",15:\"Block device required\",16:\"Mount device busy\",17:\"File exists\",18:\"Cross-device link\",19:\"No such device\",20:\"Not a directory\",21:\"Is a directory\",22:\"Invalid argument\",23:\"Too many open files in system\",24:\"Too many open files\",25:\"Not a typewriter\",26:\"Text file busy\",27:\"File too large\",28:\"No space left on device\",29:\"Illegal seek\",30:\"Read only file system\",31:\"Too many links\",32:\"Broken pipe\",33:\"Math arg out of domain of func\",34:\"Math result not representable\",35:\"File locking deadlock error\",36:\"File or path name too long\",37:\"No record locks available\",38:\"Function not implemented\",39:\"Directory not empty\",40:\"Too many symbolic links\",42:\"No message of desired type\",43:\"Identifier removed\",44:\"Channel number out of range\",45:\"Level 2 not synchronized\",46:\"Level 3 halted\",47:\"Level 3 reset\",48:\"Link number out of range\",49:\"Protocol driver not attached\",50:\"No CSI structure available\",51:\"Level 2 halted\",52:\"Invalid exchange\",53:\"Invalid request descriptor\",54:\"Exchange full\",55:\"No anode\",56:\"Invalid request code\",57:\"Invalid slot\",59:\"Bad font file fmt\",60:\"Device not a stream\",61:\"No data (for no delay io)\",62:\"Timer expired\",63:\"Out of streams resources\",64:\"Machine is not on the network\",65:\"Package not installed\",66:\"The object is remote\",67:\"The link has been severed\",68:\"Advertise error\",69:\"Srmount error\",70:\"Communication error on send\",71:\"Protocol error\",72:\"Multihop attempted\",73:\"Cross mount point (not really error)\",74:\"Trying to read unreadable message\",75:\"Value too large for defined data type\",76:\"Given log. name not unique\",77:\"f.d. invalid for this operation\",78:\"Remote address changed\",79:\"Can   access a needed shared lib\",80:\"Accessing a corrupted shared lib\",81:\".lib section in a.out corrupted\",82:\"Attempting to link in too many libs\",83:\"Attempting to exec a shared library\",84:\"Illegal byte sequence\",86:\"Streams pipe error\",87:\"Too many users\",88:\"Socket operation on non-socket\",89:\"Destination address required\",90:\"Message too long\",91:\"Protocol wrong type for socket\",92:\"Protocol not available\",93:\"Unknown protocol\",94:\"Socket type not supported\",95:\"Not supported\",96:\"Protocol family not supported\",97:\"Address family not supported by protocol family\",98:\"Address already in use\",99:\"Address not available\",100:\"Network interface is not configured\",101:\"Network is unreachable\",102:\"Connection reset by network\",103:\"Connection aborted\",104:\"Connection reset by peer\",105:\"No buffer space available\",106:\"Socket is already connected\",107:\"Socket is not connected\",108:\"Can't send after socket shutdown\",109:\"Too many references\",110:\"Connection timed out\",111:\"Connection refused\",112:\"Host is down\",113:\"Host is unreachable\",114:\"Socket already connected\",115:\"Connection already in progress\",116:\"Stale file handle\",122:\"Quota exceeded\",123:\"No medium (in tape drive)\",125:\"Operation canceled\",130:\"Previous owner died\",131:\"State not recoverable\"};var PATH={splitPath:(function(filename){var splitPathRe=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;return splitPathRe.exec(filename).slice(1)}),normalizeArray:(function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last===\".\"){parts.splice(i,1)}else if(last===\"..\"){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift(\"..\")}}return parts}),normalize:(function(path){var isAbsolute=path.charAt(0)===\"/\",trailingSlash=path.substr(-1)===\"/\";path=PATH.normalizeArray(path.split(\"/\").filter((function(p){return!!p})),!isAbsolute).join(\"/\");if(!path&&!isAbsolute){path=\".\"}if(path&&trailingSlash){path+=\"/\"}return(isAbsolute?\"/\":\"\")+path}),dirname:(function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return\".\"}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir}),basename:(function(path){if(path===\"/\")return\"/\";var lastSlash=path.lastIndexOf(\"/\");if(lastSlash===-1)return path;return path.substr(lastSlash+1)}),extname:(function(path){return PATH.splitPath(path)[3]}),join:(function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join(\"/\"))}),join2:(function(l,r){return PATH.normalize(l+\"/\"+r)}),resolve:(function(){var resolvedPath=\"\",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!==\"string\"){throw new TypeError(\"Arguments to path.resolve must be strings\")}else if(!path){return\"\"}resolvedPath=path+\"/\"+resolvedPath;resolvedAbsolute=path.charAt(0)===\"/\"}resolvedPath=PATH.normalizeArray(resolvedPath.split(\"/\").filter((function(p){return!!p})),!resolvedAbsolute).join(\"/\");return(resolvedAbsolute?\"/\":\"\")+resolvedPath||\".\"}),relative:(function(from,to){from=PATH.resolve(from).substr(1);to=PATH.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!==\"\")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!==\"\")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split(\"/\"));var toParts=trim(to.split(\"/\"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push(\"..\")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join(\"/\")})};var TTY={ttys:[],init:(function(){}),shutdown:(function(){}),register:(function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)}),stream_ops:{open:(function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}stream.tty=tty;stream.seekable=false}),close:(function(stream){stream.tty.ops.flush(stream.tty)}),flush:(function(stream){stream.tty.ops.flush(stream.tty)}),read:(function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(ERRNO_CODES.ENXIO)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead}),write:(function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(ERRNO_CODES.ENXIO)}for(var i=0;i<length;i++){try{stream.tty.ops.put_char(stream.tty,buffer[offset+i])}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}}if(length){stream.node.timestamp=Date.now()}return i})},default_tty_ops:{get_char:(function(tty){if(!tty.input.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=new Buffer(BUFSIZE);var bytesRead=0;var isPosixPlatform=process.platform!=\"win32\";var fd=process.stdin.fd;if(isPosixPlatform){var usingDevice=false;try{fd=fs.openSync(\"/dev/stdin\",\"r\");usingDevice=true}catch(e){}}try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE,null)}catch(e){if(e.toString().indexOf(\"EOF\")!=-1)bytesRead=0;else throw e}if(usingDevice){fs.closeSync(fd)}if(bytesRead>0){result=buf.slice(0,bytesRead).toString(\"utf-8\")}else{result=null}}else if(typeof window!=\"undefined\"&&typeof window.prompt==\"function\"){result=window.prompt(\"Input: \");if(result!==null){result+=\"\\n\"}}else if(typeof readline==\"function\"){result=readline();if(result!==null){result+=\"\\n\"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()}),put_char:(function(tty,val){if(val===null||val===10){Module[\"print\"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module[\"print\"](UTF8ArrayToString(tty.output,0));tty.output=[]}})},default_tty1_ops:{put_char:(function(tty,val){if(val===null||val===10){Module[\"printErr\"](UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}}),flush:(function(tty){if(tty.output&&tty.output.length>0){Module[\"printErr\"](UTF8ArrayToString(tty.output,0));tty.output=[]}})}};var MEMFS={ops_table:null,mount:(function(mount){return MEMFS.createNode(null,\"/\",16384|511,0)}),createNode:(function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node}),getFileDataAsRegularArray:(function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i<node.usedBytes;++i)arr.push(node.contents[i]);return arr}return node.contents}),getFileDataAsTypedArray:(function(node){if(!node.contents)return new Uint8Array;if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)}),expandFileStorage:(function(node,newCapacity){if(node.contents&&node.contents.subarray&&newCapacity>node.contents.length){node.contents=MEMFS.getFileDataAsRegularArray(node);node.usedBytes=node.contents.length}if(!node.contents||node.contents.subarray){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)|0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return}if(!node.contents&&newCapacity>0)node.contents=[];while(node.contents.length<newCapacity)node.contents.push(0)}),resizeFileStorage:(function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(new ArrayBuffer(newSize));if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length<newSize)node.contents.push(0);node.usedBytes=newSize}),node_ops:{getattr:(function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr}),setattr:(function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}}),lookup:(function(parent,name){throw FS.genericErrors[ERRNO_CODES.ENOENT]}),mknod:(function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)}),rename:(function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}}}delete old_node.parent.contents[old_node.name];old_node.name=new_name;new_dir.contents[new_name]=old_node;old_node.parent=new_dir}),unlink:(function(parent,name){delete parent.contents[name]}),rmdir:(function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}delete parent.contents[name]}),readdir:(function(node){var entries=[\".\",\"..\"];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries}),symlink:(function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node}),readlink:(function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return node.link})},stream_ops:{read:(function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);assert(size>=0);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size}),write:(function(stream,buffer,offset,length,position,canOwn){if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=new Uint8Array(buffer.subarray(offset,offset+length));node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray)node.contents.set(buffer.subarray(offset,offset+length),position);else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position}),allocate:(function(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)}),mmap:(function(stream,buffer,offset,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&(contents.buffer===buffer||contents.buffer===buffer.buffer)){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<stream.node.usedBytes){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=_malloc(length);if(!ptr){throw new FS.ErrnoError(ERRNO_CODES.ENOMEM)}buffer.set(contents,ptr)}return{ptr:ptr,allocated:allocated}}),msync:(function(stream,buffer,offset,length,mmapFlags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}if(mmapFlags&2){return 0}var bytesWritten=MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0})}};var IDBFS={dbs:{},indexedDB:(function(){if(typeof indexedDB!==\"undefined\")return indexedDB;var ret=null;if(typeof window===\"object\")ret=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;assert(ret,\"IDBFS used, but indexedDB not supported\");return ret}),DB_VERSION:21,DB_STORE_NAME:\"FILE_DATA\",mount:(function(mount){return MEMFS.mount.apply(null,arguments)}),syncfs:(function(mount,populate,callback){IDBFS.getLocalSet(mount,(function(err,local){if(err)return callback(err);IDBFS.getRemoteSet(mount,(function(err,remote){if(err)return callback(err);var src=populate?remote:local;var dst=populate?local:remote;IDBFS.reconcile(src,dst,callback)}))}))}),getDB:(function(name,callback){var db=IDBFS.dbs[name];if(db){return callback(null,db)}var req;try{req=IDBFS.indexedDB().open(name,IDBFS.DB_VERSION)}catch(e){return callback(e)}if(!req){return callback(\"Unable to connect to IndexedDB\")}req.onupgradeneeded=(function(e){var db=e.target.result;var transaction=e.target.transaction;var fileStore;if(db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)){fileStore=transaction.objectStore(IDBFS.DB_STORE_NAME)}else{fileStore=db.createObjectStore(IDBFS.DB_STORE_NAME)}if(!fileStore.indexNames.contains(\"timestamp\")){fileStore.createIndex(\"timestamp\",\"timestamp\",{unique:false})}});req.onsuccess=(function(){db=req.result;IDBFS.dbs[name]=db;callback(null,db)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),getLocalSet:(function(mount,callback){var entries={};function isRealDir(p){return p!==\".\"&&p!==\"..\"}function toAbsolute(root){return(function(p){return PATH.join2(root,p)})}var check=FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));while(check.length){var path=check.pop();var stat;try{stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){check.push.apply(check,FS.readdir(path).filter(isRealDir).map(toAbsolute(path)))}entries[path]={timestamp:stat.mtime}}return callback(null,{type:\"local\",entries:entries})}),getRemoteSet:(function(mount,callback){var entries={};IDBFS.getDB(mount.mountpoint,(function(err,db){if(err)return callback(err);try{var transaction=db.transaction([IDBFS.DB_STORE_NAME],\"readonly\");transaction.onerror=(function(e){callback(this.error);e.preventDefault()});var store=transaction.objectStore(IDBFS.DB_STORE_NAME);var index=store.index(\"timestamp\");index.openKeyCursor().onsuccess=(function(event){var cursor=event.target.result;if(!cursor){return callback(null,{type:\"remote\",db:db,entries:entries})}entries[cursor.primaryKey]={timestamp:cursor.key};cursor.continue()})}catch(e){return callback(e)}}))}),loadLocalEntry:(function(path,callback){var stat,node;try{var lookup=FS.lookupPath(path);node=lookup.node;stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){return callback(null,{timestamp:stat.mtime,mode:stat.mode})}else if(FS.isFile(stat.mode)){node.contents=MEMFS.getFileDataAsTypedArray(node);return callback(null,{timestamp:stat.mtime,mode:stat.mode,contents:node.contents})}else{return callback(new Error(\"node type not supported\"))}}),storeLocalEntry:(function(path,entry,callback){try{if(FS.isDir(entry.mode)){FS.mkdir(path,entry.mode)}else if(FS.isFile(entry.mode)){FS.writeFile(path,entry.contents,{canOwn:true})}else{return callback(new Error(\"node type not supported\"))}FS.chmod(path,entry.mode);FS.utime(path,entry.timestamp,entry.timestamp)}catch(e){return callback(e)}callback(null)}),removeLocalEntry:(function(path,callback){try{var lookup=FS.lookupPath(path);var stat=FS.stat(path);if(FS.isDir(stat.mode)){FS.rmdir(path)}else if(FS.isFile(stat.mode)){FS.unlink(path)}}catch(e){return callback(e)}callback(null)}),loadRemoteEntry:(function(store,path,callback){var req=store.get(path);req.onsuccess=(function(event){callback(null,event.target.result)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),storeRemoteEntry:(function(store,path,entry,callback){var req=store.put(entry,path);req.onsuccess=(function(){callback(null)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),removeRemoteEntry:(function(store,path,callback){var req=store.delete(path);req.onsuccess=(function(){callback(null)});req.onerror=(function(e){callback(this.error);e.preventDefault()})}),reconcile:(function(src,dst,callback){var total=0;var create=[];Object.keys(src.entries).forEach((function(key){var e=src.entries[key];var e2=dst.entries[key];if(!e2||e.timestamp>e2.timestamp){create.push(key);total++}}));var remove=[];Object.keys(dst.entries).forEach((function(key){var e=dst.entries[key];var e2=src.entries[key];if(!e2){remove.push(key);total++}}));if(!total){return callback(null)}var completed=0;var db=src.type===\"remote\"?src.db:dst.db;var transaction=db.transaction([IDBFS.DB_STORE_NAME],\"readwrite\");var store=transaction.objectStore(IDBFS.DB_STORE_NAME);function done(err){if(err){if(!done.errored){done.errored=true;return callback(err)}return}if(++completed>=total){return callback(null)}}transaction.onerror=(function(e){done(this.error);e.preventDefault()});create.sort().forEach((function(path){if(dst.type===\"local\"){IDBFS.loadRemoteEntry(store,path,(function(err,entry){if(err)return done(err);IDBFS.storeLocalEntry(path,entry,done)}))}else{IDBFS.loadLocalEntry(path,(function(err,entry){if(err)return done(err);IDBFS.storeRemoteEntry(store,path,entry,done)}))}}));remove.sort().reverse().forEach((function(path){if(dst.type===\"local\"){IDBFS.removeLocalEntry(path,done)}else{IDBFS.removeRemoteEntry(store,path,done)}}))})};var NODEFS={isWindows:false,staticInit:(function(){NODEFS.isWindows=!!process.platform.match(/^win/);var flags=process[\"binding\"](\"constants\");if(flags[\"fs\"]){flags=flags[\"fs\"]}NODEFS.flagsForNodeMap={\"1024\":flags[\"O_APPEND\"],\"64\":flags[\"O_CREAT\"],\"128\":flags[\"O_EXCL\"],\"0\":flags[\"O_RDONLY\"],\"2\":flags[\"O_RDWR\"],\"4096\":flags[\"O_SYNC\"],\"512\":flags[\"O_TRUNC\"],\"1\":flags[\"O_WRONLY\"]}}),bufferFrom:(function(arrayBuffer){return Buffer.alloc?Buffer.from(arrayBuffer):new Buffer(arrayBuffer)}),mount:(function(mount){assert(ENVIRONMENT_IS_NODE);return NODEFS.createNode(null,\"/\",NODEFS.getMode(mount.opts.root),0)}),createNode:(function(parent,name,mode,dev){if(!FS.isDir(mode)&&!FS.isFile(mode)&&!FS.isLink(mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=FS.createNode(parent,name,mode);node.node_ops=NODEFS.node_ops;node.stream_ops=NODEFS.stream_ops;return node}),getMode:(function(path){var stat;try{stat=fs.lstatSync(path);if(NODEFS.isWindows){stat.mode=stat.mode|(stat.mode&292)>>2}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return stat.mode}),realPath:(function(node){var parts=[];while(node.parent!==node){parts.push(node.name);node=node.parent}parts.push(node.mount.opts.root);parts.reverse();return PATH.join.apply(null,parts)}),flagsForNode:(function(flags){flags&=~2097152;flags&=~2048;flags&=~32768;flags&=~524288;var newFlags=0;for(var k in NODEFS.flagsForNodeMap){if(flags&k){newFlags|=NODEFS.flagsForNodeMap[k];flags^=k}}if(!flags){return newFlags}else{throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}}),node_ops:{getattr:(function(node){var path=NODEFS.realPath(node);var stat;try{stat=fs.lstatSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}if(NODEFS.isWindows&&!stat.blksize){stat.blksize=4096}if(NODEFS.isWindows&&!stat.blocks){stat.blocks=(stat.size+stat.blksize-1)/stat.blksize|0}return{dev:stat.dev,ino:stat.ino,mode:stat.mode,nlink:stat.nlink,uid:stat.uid,gid:stat.gid,rdev:stat.rdev,size:stat.size,atime:stat.atime,mtime:stat.mtime,ctime:stat.ctime,blksize:stat.blksize,blocks:stat.blocks}}),setattr:(function(node,attr){var path=NODEFS.realPath(node);try{if(attr.mode!==undefined){fs.chmodSync(path,attr.mode);node.mode=attr.mode}if(attr.timestamp!==undefined){var date=new Date(attr.timestamp);fs.utimesSync(path,date,date)}if(attr.size!==undefined){fs.truncateSync(path,attr.size)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),lookup:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);var mode=NODEFS.getMode(path);return NODEFS.createNode(parent,name,mode)}),mknod:(function(parent,name,mode,dev){var node=NODEFS.createNode(parent,name,mode,dev);var path=NODEFS.realPath(node);try{if(FS.isDir(node.mode)){fs.mkdirSync(path,node.mode)}else{fs.writeFileSync(path,\"\",{mode:node.mode})}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}return node}),rename:(function(oldNode,newDir,newName){var oldPath=NODEFS.realPath(oldNode);var newPath=PATH.join2(NODEFS.realPath(newDir),newName);try{fs.renameSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),unlink:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.unlinkSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),rmdir:(function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.rmdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readdir:(function(node){var path=NODEFS.realPath(node);try{return fs.readdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),symlink:(function(parent,newName,oldPath){var newPath=PATH.join2(NODEFS.realPath(parent),newName);try{fs.symlinkSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),readlink:(function(node){var path=NODEFS.realPath(node);try{path=fs.readlinkSync(path);path=NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root),path);return path}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}})},stream_ops:{open:(function(stream){var path=NODEFS.realPath(stream.node);try{if(FS.isFile(stream.node.mode)){stream.nfd=fs.openSync(path,NODEFS.flagsForNode(stream.flags))}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),close:(function(stream){try{if(FS.isFile(stream.node.mode)&&stream.nfd){fs.closeSync(stream.nfd)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),read:(function(stream,buffer,offset,length,position){if(length===0)return 0;try{return fs.readSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),write:(function(stream,buffer,offset,length,position){try{return fs.writeSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){try{var stat=fs.fstatSync(stream.nfd);position+=stat.size}catch(e){throw new FS.ErrnoError(ERRNO_CODES[e.code])}}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};var WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:(function(mount){assert(ENVIRONMENT_IS_WORKER);if(!WORKERFS.reader)WORKERFS.reader=new FileReaderSync;var root=WORKERFS.createNode(null,\"/\",WORKERFS.DIR_MODE,0);var createdParents={};function ensureParent(path){var parts=path.split(\"/\");var parent=root;for(var i=0;i<parts.length-1;i++){var curr=parts.slice(0,i+1).join(\"/\");if(!createdParents[curr]){createdParents[curr]=WORKERFS.createNode(parent,parts[i],WORKERFS.DIR_MODE,0)}parent=createdParents[curr]}return parent}function base(path){var parts=path.split(\"/\");return parts[parts.length-1]}Array.prototype.forEach.call(mount.opts[\"files\"]||[],(function(file){WORKERFS.createNode(ensureParent(file.name),base(file.name),WORKERFS.FILE_MODE,0,file,file.lastModifiedDate)}));(mount.opts[\"blobs\"]||[]).forEach((function(obj){WORKERFS.createNode(ensureParent(obj[\"name\"]),base(obj[\"name\"]),WORKERFS.FILE_MODE,0,obj[\"data\"])}));(mount.opts[\"packages\"]||[]).forEach((function(pack){pack[\"metadata\"].files.forEach((function(file){var name=file.filename.substr(1);WORKERFS.createNode(ensureParent(name),base(name),WORKERFS.FILE_MODE,0,pack[\"blob\"].slice(file.start,file.end))}))}));return root}),createNode:(function(parent,name,mode,dev,contents,mtime){var node=FS.createNode(parent,name,mode);node.mode=mode;node.node_ops=WORKERFS.node_ops;node.stream_ops=WORKERFS.stream_ops;node.timestamp=(mtime||new Date).getTime();assert(WORKERFS.FILE_MODE!==WORKERFS.DIR_MODE);if(mode===WORKERFS.FILE_MODE){node.size=contents.size;node.contents=contents}else{node.size=4096;node.contents={}}if(parent){parent.contents[name]=node}return node}),node_ops:{getattr:(function(node){return{dev:1,ino:undefined,mode:node.mode,nlink:1,uid:0,gid:0,rdev:undefined,size:node.size,atime:new Date(node.timestamp),mtime:new Date(node.timestamp),ctime:new Date(node.timestamp),blksize:4096,blocks:Math.ceil(node.size/4096)}}),setattr:(function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}}),lookup:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}),mknod:(function(parent,name,mode,dev){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),rename:(function(oldNode,newDir,newName){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),unlink:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),rmdir:(function(parent,name){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),readdir:(function(node){var entries=[\".\",\"..\"];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries}),symlink:(function(parent,newName,oldPath){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}),readlink:(function(node){throw new FS.ErrnoError(ERRNO_CODES.EPERM)})},stream_ops:{read:(function(stream,buffer,offset,length,position){if(position>=stream.node.size)return 0;var chunk=stream.node.contents.slice(position,position+length);var ab=WORKERFS.reader.readAsArrayBuffer(chunk);buffer.set(new Uint8Array(ab),offset);return chunk.size}),write:(function(stream,buffer,offset,length,position){throw new FS.ErrnoError(ERRNO_CODES.EIO)}),llseek:(function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.size}}if(position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return position})}};STATICTOP+=16;STATICTOP+=16;STATICTOP+=16;var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:\"/\",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:(function(e){if(!(e instanceof FS.ErrnoError))throw e+\" : \"+stackTrace();return ___setErrNo(e.errno)}),lookupPath:(function(path,opts){path=PATH.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:\"\",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}var parts=PATH.normalizeArray(path.split(\"/\").filter((function(p){return!!p})),false);var current=FS.root;var current_path=\"/\";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count});current=lookup.node;if(count++>40){throw new FS.ErrnoError(ERRNO_CODES.ELOOP)}}}}return{path:current_path,node:current}}),getPath:(function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!==\"/\"?mount+\"/\"+path:mount+path}path=path?node.name+\"/\"+path:node.name;node=node.parent}}),hashName:(function(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length}),hashAddNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node}),hashRemoveNode:(function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}}),lookupNode:(function(parent,name){var err=FS.mayLookup(parent);if(err){throw new FS.ErrnoError(err,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)}),createNode:(function(parent,name,mode,rdev){if(!FS.FSNode){FS.FSNode=(function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev});FS.FSNode.prototype={};var readMode=292|73;var writeMode=146;Object.defineProperties(FS.FSNode.prototype,{read:{get:(function(){return(this.mode&readMode)===readMode}),set:(function(val){val?this.mode|=readMode:this.mode&=~readMode})},write:{get:(function(){return(this.mode&writeMode)===writeMode}),set:(function(val){val?this.mode|=writeMode:this.mode&=~writeMode})},isFolder:{get:(function(){return FS.isDir(this.mode)})},isDevice:{get:(function(){return FS.isChrdev(this.mode)})}})}var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node}),destroyNode:(function(node){FS.hashRemoveNode(node)}),isRoot:(function(node){return node===node.parent}),isMountpoint:(function(node){return!!node.mounted}),isFile:(function(mode){return(mode&61440)===32768}),isDir:(function(mode){return(mode&61440)===16384}),isLink:(function(mode){return(mode&61440)===40960}),isChrdev:(function(mode){return(mode&61440)===8192}),isBlkdev:(function(mode){return(mode&61440)===24576}),isFIFO:(function(mode){return(mode&61440)===4096}),isSocket:(function(mode){return(mode&49152)===49152}),flagModes:{\"r\":0,\"rs\":1052672,\"r+\":2,\"w\":577,\"wx\":705,\"xw\":705,\"w+\":578,\"wx+\":706,\"xw+\":706,\"a\":1089,\"ax\":1217,\"xa\":1217,\"a+\":1090,\"ax+\":1218,\"xa+\":1218},modeStringToFlags:(function(str){var flags=FS.flagModes[str];if(typeof flags===\"undefined\"){throw new Error(\"Unknown file open mode: \"+str)}return flags}),flagsToPermissionString:(function(flag){var perms=[\"r\",\"w\",\"rw\"][flag&3];if(flag&512){perms+=\"w\"}return perms}),nodePermissions:(function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf(\"r\")!==-1&&!(node.mode&292)){return ERRNO_CODES.EACCES}else if(perms.indexOf(\"w\")!==-1&&!(node.mode&146)){return ERRNO_CODES.EACCES}else if(perms.indexOf(\"x\")!==-1&&!(node.mode&73)){return ERRNO_CODES.EACCES}return 0}),mayLookup:(function(dir){var err=FS.nodePermissions(dir,\"x\");if(err)return err;if(!dir.node_ops.lookup)return ERRNO_CODES.EACCES;return 0}),mayCreate:(function(dir,name){try{var node=FS.lookupNode(dir,name);return ERRNO_CODES.EEXIST}catch(e){}return FS.nodePermissions(dir,\"wx\")}),mayDelete:(function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var err=FS.nodePermissions(dir,\"wx\");if(err){return err}if(isdir){if(!FS.isDir(node.mode)){return ERRNO_CODES.ENOTDIR}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return ERRNO_CODES.EBUSY}}else{if(FS.isDir(node.mode)){return ERRNO_CODES.EISDIR}}return 0}),mayOpen:(function(node,flags){if(!node){return ERRNO_CODES.ENOENT}if(FS.isLink(node.mode)){return ERRNO_CODES.ELOOP}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!==\"r\"||flags&512){return ERRNO_CODES.EISDIR}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))}),MAX_OPEN_FDS:4096,nextfd:(function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(ERRNO_CODES.EMFILE)}),getStream:(function(fd){return FS.streams[fd]}),createStream:(function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=(function(){});FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:(function(){return this.node}),set:(function(val){this.node=val})},isRead:{get:(function(){return(this.flags&2097155)!==1})},isWrite:{get:(function(){return(this.flags&2097155)!==0})},isAppend:{get:(function(){return this.flags&1024})}})}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream}),closeStream:(function(fd){FS.streams[fd]=null}),chrdev_stream_ops:{open:(function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}}),llseek:(function(){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)})},major:(function(dev){return dev>>8}),minor:(function(dev){return dev&255}),makedev:(function(ma,mi){return ma<<8|mi}),registerDevice:(function(dev,ops){FS.devices[dev]={stream_ops:ops}}),getDevice:(function(dev){return FS.devices[dev]}),getMounts:(function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts}),syncfs:(function(populate,callback){if(typeof populate===\"function\"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){console.log(\"warning: \"+FS.syncFSRequests+\" FS.syncfs operations in flight at once, probably just doing extra work\")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(err){assert(FS.syncFSRequests>0);FS.syncFSRequests--;return callback(err)}function done(err){if(err){if(!done.errored){done.errored=true;return doCallback(err)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach((function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)}))}),mount:(function(type,opts,mountpoint){var root=mountpoint===\"/\";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot}),unmount:(function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach((function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}}));node.mounted=null;var idx=node.mount.mounts.indexOf(mount);assert(idx!==-1);node.mount.mounts.splice(idx,1)}),lookup:(function(parent,name){return parent.node_ops.lookup(parent,name)}),mknod:(function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name===\".\"||name===\"..\"){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var err=FS.mayCreate(parent,name);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return parent.node_ops.mknod(parent,name,mode,dev)}),create:(function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)}),mkdir:(function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)}),mkdirTree:(function(path,mode){var dirs=path.split(\"/\");var d=\"\";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+=\"/\"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=ERRNO_CODES.EEXIST)throw e}}}),mkdev:(function(path,mode,dev){if(typeof dev===\"undefined\"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)}),symlink:(function(oldpath,newpath){if(!PATH.resolve(oldpath)){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}var newname=PATH.basename(newpath);var err=FS.mayCreate(parent,newname);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return parent.node_ops.symlink(parent,newname,oldpath)}),rename:(function(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;try{lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(!old_dir||!new_dir)throw new FS.ErrnoError(ERRNO_CODES.ENOENT);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(ERRNO_CODES.EXDEV)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH.relative(old_path,new_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}relative=PATH.relative(new_path,old_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var err=FS.mayDelete(old_dir,old_name,isdir);if(err){throw new FS.ErrnoError(err)}err=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(err){throw new FS.ErrnoError(err)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}if(new_dir!==old_dir){err=FS.nodePermissions(old_dir,\"w\");if(err){throw new FS.ErrnoError(err)}}try{if(FS.trackingDelegate[\"willMovePath\"]){FS.trackingDelegate[\"willMovePath\"](old_path,new_path)}}catch(e){console.log(\"FS.trackingDelegate['willMovePath']('\"+old_path+\"', '\"+new_path+\"') threw an exception: \"+e.message)}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}try{if(FS.trackingDelegate[\"onMovePath\"])FS.trackingDelegate[\"onMovePath\"](old_path,new_path)}catch(e){console.log(\"FS.trackingDelegate['onMovePath']('\"+old_path+\"', '\"+new_path+\"') threw an exception: \"+e.message)}}),rmdir:(function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,true);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}try{if(FS.trackingDelegate[\"willDeletePath\"]){FS.trackingDelegate[\"willDeletePath\"](path)}}catch(e){console.log(\"FS.trackingDelegate['willDeletePath']('\"+path+\"') threw an exception: \"+e.message)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate[\"onDeletePath\"])FS.trackingDelegate[\"onDeletePath\"](path)}catch(e){console.log(\"FS.trackingDelegate['onDeletePath']('\"+path+\"') threw an exception: \"+e.message)}}),readdir:(function(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}return node.node_ops.readdir(node)}),unlink:(function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,false);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(ERRNO_CODES.EBUSY)}try{if(FS.trackingDelegate[\"willDeletePath\"]){FS.trackingDelegate[\"willDeletePath\"](path)}}catch(e){console.log(\"FS.trackingDelegate['willDeletePath']('\"+path+\"') threw an exception: \"+e.message)}parent.node_ops.unlink(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate[\"onDeletePath\"])FS.trackingDelegate[\"onDeletePath\"](path)}catch(e){console.log(\"FS.trackingDelegate['onDeletePath']('\"+path+\"') threw an exception: \"+e.message)}}),readlink:(function(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!link.node_ops.readlink){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}return PATH.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))}),stat:(function(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!node.node_ops.getattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}return node.node_ops.getattr(node)}),lstat:(function(path){return FS.stat(path,true)}),chmod:(function(path,mode,dontFollow){var node;if(typeof path===\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})}),lchmod:(function(path,mode){FS.chmod(path,mode,true)}),fchmod:(function(fd,mode){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}FS.chmod(stream.node,mode)}),chown:(function(path,uid,gid,dontFollow){var node;if(typeof path===\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}node.node_ops.setattr(node,{timestamp:Date.now()})}),lchown:(function(path,uid,gid){FS.chown(path,uid,gid,true)}),fchown:(function(fd,uid,gid){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}FS.chown(stream.node,uid,gid)}),truncate:(function(path,len){if(len<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var node;if(typeof path===\"string\"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(ERRNO_CODES.EPERM)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var err=FS.nodePermissions(node,\"w\");if(err){throw new FS.ErrnoError(err)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})}),ftruncate:(function(fd,len){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}FS.truncate(stream.node,len)}),utime:(function(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})}),open:(function(path,flags,mode,fd_start,fd_end){if(path===\"\"){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}flags=typeof flags===\"string\"?FS.modeStringToFlags(flags):flags;mode=typeof mode===\"undefined\"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path===\"object\"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(ERRNO_CODES.EEXIST)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}if(!created){var err=FS.mayOpen(node,flags);if(err){throw new FS.ErrnoError(err)}}if(flags&512){FS.truncate(node,0)}flags&=~(128|512);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false},fd_start,fd_end);if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module[\"logReadFiles\"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1;Module[\"printErr\"](\"read file: \"+path)}}try{if(FS.trackingDelegate[\"onOpenFile\"]){var trackingFlags=0;if((flags&2097155)!==1){trackingFlags|=FS.tracking.openFlags.READ}if((flags&2097155)!==0){trackingFlags|=FS.tracking.openFlags.WRITE}FS.trackingDelegate[\"onOpenFile\"](path,trackingFlags)}}catch(e){console.log(\"FS.trackingDelegate['onOpenFile']('\"+path+\"', flags) threw an exception: \"+e.message)}return stream}),close:(function(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null}),isClosed:(function(stream){return stream.fd===null}),llseek:(function(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position}),read:(function(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if(FS.isClosed(stream)){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!stream.stream_ops.read){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}var seeking=typeof position!==\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead}),write:(function(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if(FS.isClosed(stream)){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.EISDIR)}if(!stream.stream_ops.write){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if(stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!==\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(ERRNO_CODES.ESPIPE)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;try{if(stream.path&&FS.trackingDelegate[\"onWriteToFile\"])FS.trackingDelegate[\"onWriteToFile\"](stream.path)}catch(e){console.log(\"FS.trackingDelegate['onWriteToFile']('\"+path+\"') threw an exception: \"+e.message)}return bytesWritten}),allocate:(function(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(offset<0||length<=0){throw new FS.ErrnoError(ERRNO_CODES.EINVAL)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(ERRNO_CODES.EBADF)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP)}stream.stream_ops.allocate(stream,offset,length)}),mmap:(function(stream,buffer,offset,length,position,prot,flags){if((stream.flags&2097155)===1){throw new FS.ErrnoError(ERRNO_CODES.EACCES)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(ERRNO_CODES.ENODEV)}return stream.stream_ops.mmap(stream,buffer,offset,length,position,prot,flags)}),msync:(function(stream,buffer,offset,length,mmapFlags){if(!stream||!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)}),munmap:(function(stream){return 0}),ioctl:(function(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(ERRNO_CODES.ENOTTY)}return stream.stream_ops.ioctl(stream,cmd,arg)}),readFile:(function(path,opts){opts=opts||{};opts.flags=opts.flags||\"r\";opts.encoding=opts.encoding||\"binary\";if(opts.encoding!==\"utf8\"&&opts.encoding!==\"binary\"){throw new Error('Invalid encoding type \"'+opts.encoding+'\"')}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding===\"utf8\"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding===\"binary\"){ret=buf}FS.close(stream);return ret}),writeFile:(function(path,data,opts){opts=opts||{};opts.flags=opts.flags||\"w\";var stream=FS.open(path,opts.flags,opts.mode);if(typeof data===\"string\"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error(\"Unsupported data type\")}FS.close(stream)}),cwd:(function(){return FS.currentPath}),chdir:(function(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(ERRNO_CODES.ENOENT)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR)}var err=FS.nodePermissions(lookup.node,\"x\");if(err){throw new FS.ErrnoError(err)}FS.currentPath=lookup.path}),createDefaultDirectories:(function(){FS.mkdir(\"/tmp\");FS.mkdir(\"/home\");FS.mkdir(\"/home/web_user\")}),createDefaultDevices:(function(){FS.mkdir(\"/dev\");FS.registerDevice(FS.makedev(1,3),{read:(function(){return 0}),write:(function(stream,buffer,offset,length,pos){return length})});FS.mkdev(\"/dev/null\",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev(\"/dev/tty\",FS.makedev(5,0));FS.mkdev(\"/dev/tty1\",FS.makedev(6,0));var random_device;if(typeof crypto!==\"undefined\"){var randomBuffer=new Uint8Array(1);random_device=(function(){crypto.getRandomValues(randomBuffer);return randomBuffer[0]})}else if(ENVIRONMENT_IS_NODE){random_device=(function(){return require(\"crypto\")[\"randomBytes\"](1)[0]})}else{random_device=(function(){return Math.random()*256|0})}FS.createDevice(\"/dev\",\"random\",random_device);FS.createDevice(\"/dev\",\"urandom\",random_device);FS.mkdir(\"/dev/shm\");FS.mkdir(\"/dev/shm/tmp\")}),createSpecialDirectories:(function(){FS.mkdir(\"/proc\");FS.mkdir(\"/proc/self\");FS.mkdir(\"/proc/self/fd\");FS.mount({mount:(function(){var node=FS.createNode(\"/proc/self\",\"fd\",16384|511,73);node.node_ops={lookup:(function(parent,name){var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);var ret={parent:null,mount:{mountpoint:\"fake\"},node_ops:{readlink:(function(){return stream.path})}};ret.parent=ret;return ret})};return node})},{},\"/proc/self/fd\")}),createStandardStreams:(function(){if(Module[\"stdin\"]){FS.createDevice(\"/dev\",\"stdin\",Module[\"stdin\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdin\")}if(Module[\"stdout\"]){FS.createDevice(\"/dev\",\"stdout\",null,Module[\"stdout\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdout\")}if(Module[\"stderr\"]){FS.createDevice(\"/dev\",\"stderr\",null,Module[\"stderr\"])}else{FS.symlink(\"/dev/tty1\",\"/dev/stderr\")}var stdin=FS.open(\"/dev/stdin\",\"r\");assert(stdin.fd===0,\"invalid handle for stdin (\"+stdin.fd+\")\");var stdout=FS.open(\"/dev/stdout\",\"w\");assert(stdout.fd===1,\"invalid handle for stdout (\"+stdout.fd+\")\");var stderr=FS.open(\"/dev/stderr\",\"w\");assert(stderr.fd===2,\"invalid handle for stderr (\"+stderr.fd+\")\")}),ensureErrnoError:(function(){if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.node=node;this.setErrno=(function(errno){this.errno=errno;for(var key in ERRNO_CODES){if(ERRNO_CODES[key]===errno){this.code=key;break}}});this.setErrno(errno);this.message=ERRNO_MESSAGES[errno];if(this.stack)Object.defineProperty(this,\"stack\",{value:(new Error).stack,writable:true})};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[ERRNO_CODES.ENOENT].forEach((function(code){FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=\"<generic error, no stack>\"}))}),staticInit:(function(){FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},\"/\");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={\"MEMFS\":MEMFS,\"IDBFS\":IDBFS,\"NODEFS\":NODEFS,\"WORKERFS\":WORKERFS}}),init:(function(input,output,error){assert(!FS.init.initialized,\"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)\");FS.init.initialized=true;FS.ensureErrnoError();Module[\"stdin\"]=input||Module[\"stdin\"];Module[\"stdout\"]=output||Module[\"stdout\"];Module[\"stderr\"]=error||Module[\"stderr\"];FS.createStandardStreams()}),quit:(function(){FS.init.initialized=false;var fflush=Module[\"_fflush\"];if(fflush)fflush(0);for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}}),getMode:(function(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}),joinPath:(function(parts,forceRelative){var path=PATH.join.apply(null,parts);if(forceRelative&&path[0]==\"/\")path=path.substr(1);return path}),absolutePath:(function(relative,base){return PATH.resolve(base,relative)}),standardizePath:(function(path){return PATH.normalize(path)}),findObject:(function(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(ret.exists){return ret.object}else{___setErrNo(ret.error);return null}}),analyzePath:(function(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path===\"/\"}catch(e){ret.error=e.errno}return ret}),createFolder:(function(parent,name,canRead,canWrite){var path=PATH.join2(typeof parent===\"string\"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.mkdir(path,mode)}),createPath:(function(parent,path,canRead,canWrite){parent=typeof parent===\"string\"?parent:FS.getPath(parent);var parts=path.split(\"/\").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current}),createFile:(function(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent===\"string\"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.create(path,mode)}),createDataFile:(function(parent,name,data,canRead,canWrite,canOwn){var path=name?PATH.join2(typeof parent===\"string\"?parent:FS.getPath(parent),name):parent;var mode=FS.getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data===\"string\"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,\"w\");FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node}),createDevice:(function(parent,name,input,output){var path=PATH.join2(typeof parent===\"string\"?parent:FS.getPath(parent),name);var mode=FS.getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:(function(stream){stream.seekable=false}),close:(function(stream){if(output&&output.buffer&&output.buffer.length){output(10)}}),read:(function(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(ERRNO_CODES.EAGAIN)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead}),write:(function(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EIO)}}if(length){stream.node.timestamp=Date.now()}return i})});return FS.mkdev(path,mode,dev)}),createLink:(function(parent,name,target,canRead,canWrite){var path=PATH.join2(typeof parent===\"string\"?parent:FS.getPath(parent),name);return FS.symlink(target,path)}),forceLoadFile:(function(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;var success=true;if(typeof XMLHttpRequest!==\"undefined\"){throw new Error(\"Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.\")}else if(Module[\"read\"]){try{obj.contents=intArrayFromString(Module[\"read\"](obj.url),true);obj.usedBytes=obj.contents.length}catch(e){success=false}}else{throw new Error(\"Cannot load without read() or XMLHttpRequest.\")}if(!success)___setErrNo(ERRNO_CODES.EIO);return success}),createLazyFile:(function(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open(\"HEAD\",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);var datalength=Number(xhr.getResponseHeader(\"Content-length\"));var header;var hasByteServing=(header=xhr.getResponseHeader(\"Accept-Ranges\"))&&header===\"bytes\";var usesGzip=(header=xhr.getResponseHeader(\"Content-Encoding\"))&&header===\"gzip\";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(function(from,to){if(from>to)throw new Error(\"invalid range (\"+from+\", \"+to+\") or no bytes requested!\");if(to>datalength-1)throw new Error(\"only \"+datalength+\" bytes available! programmer error!\");var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);if(datalength!==chunkSize)xhr.setRequestHeader(\"Range\",\"bytes=\"+from+\"-\"+to);if(typeof Uint8Array!=\"undefined\")xhr.responseType=\"arraybuffer\";if(xhr.overrideMimeType){xhr.overrideMimeType(\"text/plain; charset=x-user-defined\")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||\"\",true)}});var lazyArray=this;lazyArray.setDataGetter((function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]===\"undefined\"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]===\"undefined\")throw new Error(\"doXHR failed!\");return lazyArray.chunks[chunkNum]}));if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;console.log(\"LazyFiles on gzip forces download of the whole file when length is accessed\")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!==\"undefined\"){if(!ENVIRONMENT_IS_WORKER)throw\"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc\";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._length})},chunkSize:{get:(function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize})}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:(function(){return this.contents.length})}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach((function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}return fn.apply(null,arguments)}}));stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(ERRNO_CODES.EIO)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);assert(size>=0);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size};node.stream_ops=stream_ops;return node}),createPreloadedFile:(function(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){Browser.init();var fullname=name?PATH.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(\"cp \"+fullname);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}var handled=false;Module[\"preloadPlugins\"].forEach((function(plugin){if(handled)return;if(plugin[\"canHandle\"](fullname)){plugin[\"handle\"](byteArray,fullname,finish,(function(){if(onerror)onerror();removeRunDependency(dep)}));handled=true}}));if(!handled)finish(byteArray)}addRunDependency(dep);if(typeof url==\"string\"){Browser.asyncLoad(url,(function(byteArray){processData(byteArray)}),onerror)}else{processData(url)}}),indexedDB:(function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB}),DB_NAME:(function(){return\"EM_FS_\"+window.location.pathname}),DB_VERSION:20,DB_STORE_NAME:\"FILE_DATA\",saveFilesToDB:(function(paths,onload,onerror){onload=onload||(function(){});onerror=onerror||(function(){});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=function openRequest_onupgradeneeded(){console.log(\"creating db\");var db=openRequest.result;db.createObjectStore(FS.DB_STORE_NAME)};openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;var transaction=db.transaction([FS.DB_STORE_NAME],\"readwrite\");var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach((function(path){var putRequest=files.put(FS.analyzePath(path).object.contents,path);putRequest.onsuccess=function putRequest_onsuccess(){ok++;if(ok+fail==total)finish()};putRequest.onerror=function putRequest_onerror(){fail++;if(ok+fail==total)finish()}}));transaction.onerror=onerror};openRequest.onerror=onerror}),loadFilesFromDB:(function(paths,onload,onerror){onload=onload||(function(){});onerror=onerror||(function(){});var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=onerror;openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;try{var transaction=db.transaction([FS.DB_STORE_NAME],\"readonly\")}catch(e){onerror(e);return}var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach((function(path){var getRequest=files.get(path);getRequest.onsuccess=function getRequest_onsuccess(){if(FS.analyzePath(path).exists){FS.unlink(path)}FS.createDataFile(PATH.dirname(path),PATH.basename(path),getRequest.result,true,true,true);ok++;if(ok+fail==total)finish()};getRequest.onerror=function getRequest_onerror(){fail++;if(ok+fail==total)finish()}}));transaction.onerror=onerror};openRequest.onerror=onerror})};var SYSCALLS={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:(function(dirfd,path){if(path[0]!==\"/\"){var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=FS.getStream(dirfd);if(!dirstream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);dir=dirstream.path}path=PATH.join2(dir,path)}return path}),doStat:(function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-ERRNO_CODES.ENOTDIR}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;HEAP32[buf+36>>2]=stat.size;HEAP32[buf+40>>2]=4096;HEAP32[buf+44>>2]=stat.blocks;HEAP32[buf+48>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+52>>2]=0;HEAP32[buf+56>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ino;return 0}),doMsync:(function(addr,stream,len,flags){var buffer=new Uint8Array(HEAPU8.subarray(addr,addr+len));FS.msync(stream,buffer,0,len,flags)}),doMkdir:(function(path,mode){path=PATH.normalize(path);if(path[path.length-1]===\"/\")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}),doMknod:(function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-ERRNO_CODES.EINVAL}FS.mknod(path,mode,dev);return 0}),doReadlink:(function(path,buf,bufsize){if(bufsize<=0)return-ERRNO_CODES.EINVAL;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}),doAccess:(function(path,amode){if(amode&~7){return-ERRNO_CODES.EINVAL}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;var perms=\"\";if(amode&4)perms+=\"r\";if(amode&2)perms+=\"w\";if(amode&1)perms+=\"x\";if(perms&&FS.nodePermissions(node,perms)){return-ERRNO_CODES.EACCES}return 0}),doDup:(function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd}),doReadv:(function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break}return ret}),doWritev:(function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret}),varargs:0,get:(function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret}),getStr:(function(){var ret=Pointer_stringify(SYSCALLS.get());return ret}),getStreamFromFD:(function(){var stream=FS.getStream(SYSCALLS.get());if(!stream)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return stream}),getSocketFromFD:(function(){var socket=SOCKFS.getSocket(SYSCALLS.get());if(!socket)throw new FS.ErrnoError(ERRNO_CODES.EBADF);return socket}),getSocketAddress:(function(allowNull){var addrp=SYSCALLS.get(),addrlen=SYSCALLS.get();if(allowNull&&addrp===0)return null;var info=__read_sockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info}),get64:(function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low}),getZero:(function(){assert(SYSCALLS.get()===0)})};function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var offset=offset_low;FS.llseek(stream,offset,whence);HEAP32[result>>2]=stream.position;if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall145(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doReadv(stream,iov,iovcnt)}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doWritev(stream,iov,iovcnt)}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall180(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),buf=SYSCALLS.get(),count=SYSCALLS.get(),zero=SYSCALLS.getZero(),offset=SYSCALLS.get64();return FS.read(stream,HEAP8,buf,count,offset)}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall192(which,varargs){SYSCALLS.varargs=varargs;try{var addr=SYSCALLS.get(),len=SYSCALLS.get(),prot=SYSCALLS.get(),flags=SYSCALLS.get(),fd=SYSCALLS.get(),off=SYSCALLS.get();off<<=12;var ptr;var allocated=false;if(fd===-1){ptr=_memalign(PAGE_SIZE,len);if(!ptr)return-ERRNO_CODES.ENOMEM;_memset(ptr,0,len);allocated=true}else{var info=FS.getStream(fd);if(!info)return-ERRNO_CODES.EBADF;var res=FS.mmap(info,HEAPU8,addr,len,off,prot,flags);ptr=res.ptr;allocated=res.allocated}SYSCALLS.mappings[ptr]={malloc:ptr,len:len,allocated:allocated,fd:fd,flags:flags};return ptr}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall195(which,varargs){SYSCALLS.varargs=varargs;try{var path=SYSCALLS.getStr(),buf=SYSCALLS.get();return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall197(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),buf=SYSCALLS.get();return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall220(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),dirp=SYSCALLS.get(),count=SYSCALLS.get();if(!stream.getdents){stream.getdents=FS.readdir(stream.path)}var pos=0;while(stream.getdents.length>0&&pos+268<=count){var id;var type;var name=stream.getdents.pop();if(name[0]===\".\"){id=1;type=4}else{var child=FS.lookupNode(stream.node,name);id=child.id;type=FS.isChrdev(child.mode)?2:FS.isDir(child.mode)?4:FS.isLink(child.mode)?10:8}HEAP32[dirp+pos>>2]=id;HEAP32[dirp+pos+4>>2]=stream.position;HEAP16[dirp+pos+8>>1]=268;HEAP8[dirp+pos+10>>0]=type;stringToUTF8(name,dirp+pos+11,256);pos+=268}return pos}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall221(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),cmd=SYSCALLS.get();switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-ERRNO_CODES.EINVAL}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd};case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0};case 12:case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0};case 13:case 14:case 13:case 14:return 0;case 16:case 8:return-ERRNO_CODES.EINVAL;case 9:___setErrNo(ERRNO_CODES.EINVAL);return-1;default:{return-ERRNO_CODES.EINVAL}}}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall5(which,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(),flags=SYSCALLS.get(),mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall54(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),op=SYSCALLS.get();switch(op){case 21509:case 21505:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21519:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0};case 21520:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return-ERRNO_CODES.EINVAL};case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)};case 21523:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};case 21524:{if(!stream.tty)return-ERRNO_CODES.ENOTTY;return 0};default:abort(\"bad ioctl syscall \"+op)}}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall6(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD();FS.close(stream);return 0}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall91(which,varargs){SYSCALLS.varargs=varargs;try{var addr=SYSCALLS.get(),len=SYSCALLS.get();var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);SYSCALLS.doMsync(addr,stream,len,info.flags);FS.munmap(stream);SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}catch(e){if(typeof FS===\"undefined\"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___unlock(){}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError(\"Unknown type size: \"+size)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret=\"\";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return\"_unknown\"}name=name.replace(/[^a-zA-Z0-9_]/g,\"$\");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return\"_\"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return(new Function(\"body\",\"return function \"+name+\"() {\\n\"+'    \"use strict\";'+\"    return body.apply(this, arguments);\\n\"+\"};\\n\"))(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,(function(message){this.name=errorName;this.message=message;var stack=(new Error(message)).stack;if(stack!==undefined){this.stack=this.toString()+\"\\n\"+stack.replace(/^Error(:[^\\n]*)?\\n/,\"\")}}));errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=(function(){if(this.message===undefined){return this.name}else{return this.name+\": \"+this.message}});return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach((function(type){typeDependencies[type]=dependentTypes}));function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError(\"Mismatched type converter count\")}for(var i=0;i<myTypes.length;++i){registerType(myTypes[i],myTypeConverters[i])}}var typeConverters=new Array(dependentTypes.length);var unregisteredTypes=[];var registered=0;dependentTypes.forEach((function(dt,i){if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push((function(){typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}}))}}));if(0===unregisteredTypes.length){onComplete(typeConverters)}}function registerType(rawType,registeredInstance,options){options=options||{};if(!(\"argPackAdvance\"in registeredInstance)){throw new TypeError(\"registerType registeredInstance requires argPackAdvance\")}var name=registeredInstance.name;if(!rawType){throwBindingError('type \"'+name+'\" must have a positive integer typeid pointer')}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(\"Cannot register type '\"+name+\"' twice\")}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach((function(cb){cb()}))}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":(function(wt){return!!wt}),\"toWireType\":(function(destructors,o){return o?trueValue:falseValue}),\"argPackAdvance\":8,\"readValueFromPointer\":(function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError(\"Unknown boolean type size: \"+name)}return this[\"fromWireType\"](heap[pointer>>shift])}),destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+\" instance already deleted\")}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}});clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function runDestructor(handle){var $$=handle.$$;if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError(\"Object already scheduled for deletion\")}this.$$.count.value-=1;var toDelete=0===this.$$.count.value;if(toDelete){runDestructor(this)}if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj[\"delete\"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError(\"Object already scheduled for deletion\")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype[\"isAliasOf\"]=ClassHandle_isAliasOf;ClassHandle.prototype[\"clone\"]=ClassHandle_clone;ClassHandle.prototype[\"delete\"]=ClassHandle_delete;ClassHandle.prototype[\"isDeleted\"]=ClassHandle_isDeleted;ClassHandle.prototype[\"deleteLater\"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=(function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError(\"Function '\"+humanName+\"' called with an invalid number of arguments (\"+arguments.length+\") - expects one of (\"+proto[methodName].overloadTable+\")!\")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)});proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(\"Cannot register public name '\"+name+\"' twice\")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(\"Cannot register multiple overloads of a function with the same number of arguments (\"+numArguments+\")!\")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(\"Expected null or instance of \"+desiredClass.name+\", got an instance of \"+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(\"null is not a valid \"+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass \"'+_embind_repr(handle)+'\" as a '+this.name)}if(!handle.$$.ptr){throwBindingError(\"Cannot pass deleted object as a pointer of type \"+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(\"null is not a valid \"+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass \"'+_embind_repr(handle)+'\" as a '+this.name)}if(!handle.$$.ptr){throwBindingError(\"Cannot pass deleted object as a pointer of type \"+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(\"Cannot convert argument of type \"+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+\" to parameter type \"+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError(\"Passing raw pointer to smart pointer is illegal\")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(\"Cannot convert argument of type \"+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+\" to parameter type \"+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle[\"clone\"]();ptr=this.rawShare(ptr,__emval_register((function(){clonedHandle[\"delete\"]()})));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError(\"Unsupporting sharing policy\")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(\"null is not a valid \"+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass \"'+_embind_repr(handle)+'\" as a '+this.name)}if(!handle.$$.ptr){throwBindingError(\"Cannot pass deleted object as a pointer of type \"+this.name)}if(handle.$$.ptrType.isConst){throwBindingError(\"Cannot convert argument of type \"+handle.$$.ptrType.name+\" to parameter type \"+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this[\"fromWireType\"](HEAPU32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle[\"delete\"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module[\"getInheritedInstanceCount\"]=getInheritedInstanceCount;Module[\"getLiveInheritedInstances\"]=getLiveInheritedInstances;Module[\"flushPendingDeletes\"]=flushPendingDeletes;Module[\"setDelayFunction\"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError(\"ptr should not be undefined\")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError(\"makeClassHandle requires ptr and ptrType\")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError(\"Both smartPtrType and smartPtr must be specified\")}record.count={value:1};return Object.create(prototype,{$$:{value:record}})}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance[\"clone\"]()}else{var rv=registeredInstance[\"clone\"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype[\"argPackAdvance\"]=8;RegisteredPointer.prototype[\"readValueFromPointer\"]=simpleReadValueFromPointer;RegisteredPointer.prototype[\"deleteObject\"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype[\"fromWireType\"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&&registeredClass.baseClass===undefined){if(isConst){this[\"toWireType\"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this[\"toWireType\"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this[\"toWireType\"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError(\"Replacing nonexistant public symbol\")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(dynCall){var args=[];for(var i=1;i<signature.length;++i){args.push(\"a\"+i)}var name=\"dynCall_\"+signature+\"_\"+rawFunction;var body=\"return function \"+name+\"(\"+args.join(\", \")+\") {\\n\";body+=\"    return dynCall(rawFunction\"+(args.length?\", \":\"\")+args.join(\", \")+\");\\n\";body+=\"};\\n\";return(new Function(\"dynCall\",\"rawFunction\",body))(dynCall,rawFunction)}var fp;if(Module[\"FUNCTION_TABLE_\"+signature]!==undefined){fp=Module[\"FUNCTION_TABLE_\"+signature][rawFunction]}else if(typeof FUNCTION_TABLE!==\"undefined\"){fp=FUNCTION_TABLE[rawFunction]}else{var dc=Module[\"asm\"][\"dynCall_\"+signature];if(dc===undefined){dc=Module[\"asm\"][\"dynCall_\"+signature.replace(/f/g,\"d\")];if(dc===undefined){throwBindingError(\"No dynCall invoker for signature: \"+signature)}}fp=makeDynCaller(dc)}if(typeof fp!==\"function\"){throwBindingError(\"unknown function pointer with signature \"+signature+\": \"+rawFunction)}return fp}var UnboundTypeError=undefined;function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function throwUnboundTypeError(message,types){var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(message+\": \"+unboundTypes.map(getTypeName).join([\", \"]))}function __embind_register_class(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor){name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);if(upcast){upcast=embind__requireFunction(upcastSignature,upcast)}if(downcast){downcast=embind__requireFunction(downcastSignature,downcast)}rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,(function(){throwUnboundTypeError(\"Cannot construct \"+name+\" due to unbound types\",[baseClassRawType])}));whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],(function(base){base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(legalFunctionName,(function(){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError(\"Use 'new' to construct \"+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+\" has no accessible constructor\")}var body=registeredClass.constructor_body[arguments.length];if(undefined===body){throw new BindingError(\"Tried to invoke ctor of \"+name+\" with invalid number of parameters (\"+arguments.length+\") - expected (\"+Object.keys(registeredClass.constructor_body).toString()+\") parameters instead!\")}return body.apply(this,arguments)}));var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+\"*\",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+\" const*\",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]}))}function new_(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError(\"new_ called with constructor type \"+typeof constructor+\" which is not a function\")}var dummy=createNamedFunction(constructor.name||\"unknownFunctionName\",(function(){}));dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc){var argCount=argTypes.length;if(argCount<2){throwBindingError(\"argTypes array size mismatch! Must at least get return value and 'this' types!\")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i<argTypes.length;++i){if(argTypes[i]!==null&&argTypes[i].destructorFunction===undefined){needsDestructorStack=true;break}}var returns=argTypes[0].name!==\"void\";var argsList=\"\";var argsListWired=\"\";for(var i=0;i<argCount-2;++i){argsList+=(i!==0?\", \":\"\")+\"arg\"+i;argsListWired+=(i!==0?\", \":\"\")+\"arg\"+i+\"Wired\"}var invokerFnBody=\"return function \"+makeLegalFunctionName(humanName)+\"(\"+argsList+\") {\\n\"+\"if (arguments.length !== \"+(argCount-2)+\") {\\n\"+\"throwBindingError('function \"+humanName+\" called with ' + arguments.length + ' arguments, expected \"+(argCount-2)+\" args!');\\n\"+\"}\\n\";if(needsDestructorStack){invokerFnBody+=\"var destructors = [];\\n\"}var dtorStack=needsDestructorStack?\"destructors\":\"null\";var args1=[\"throwBindingError\",\"invoker\",\"fn\",\"runDestructors\",\"retType\",\"classParam\"];var args2=[throwBindingError,cppInvokerFunc,cppTargetFunc,runDestructors,argTypes[0],argTypes[1]];if(isClassMethodFunc){invokerFnBody+=\"var thisWired = classParam.toWireType(\"+dtorStack+\", this);\\n\"}for(var i=0;i<argCount-2;++i){invokerFnBody+=\"var arg\"+i+\"Wired = argType\"+i+\".toWireType(\"+dtorStack+\", arg\"+i+\"); // \"+argTypes[i+2].name+\"\\n\";args1.push(\"argType\"+i);args2.push(argTypes[i+2])}if(isClassMethodFunc){argsListWired=\"thisWired\"+(argsListWired.length>0?\", \":\"\")+argsListWired}invokerFnBody+=(returns?\"var rv = \":\"\")+\"invoker(fn\"+(argsListWired.length>0?\", \":\"\")+argsListWired+\");\\n\";if(needsDestructorStack){invokerFnBody+=\"runDestructors(destructors);\\n\"}else{for(var i=isClassMethodFunc?1:2;i<argTypes.length;++i){var paramName=i===1?\"thisWired\":\"arg\"+(i-2)+\"Wired\";if(argTypes[i].destructorFunction!==null){invokerFnBody+=paramName+\"_dtor(\"+paramName+\"); // \"+argTypes[i].name+\"\\n\";args1.push(paramName+\"_dtor\");args2.push(argTypes[i].destructorFunction)}}}if(returns){invokerFnBody+=\"var ret = retType.fromWireType(rv);\\n\"+\"return ret;\\n\"}else{}invokerFnBody+=\"}\\n\";args1.push(invokerFnBody);var invokerFunction=new_(Function,args1).apply(null,args2);return invokerFunction}function heap32VectorToArray(count,firstElement){var array=[];for(var i=0;i<count;i++){array.push(HEAP32[(firstElement>>2)+i])}return array}function __embind_register_class_class_function(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,fn){var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],(function(classType){classType=classType[0];var humanName=classType.name+\".\"+methodName;function unboundTypesHandler(){throwUnboundTypeError(\"Cannot call \"+humanName+\" due to unbound types\",rawArgTypes)}var proto=classType.registeredClass.constructor;if(undefined===proto[methodName]){unboundTypesHandler.argCount=argCount-1;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-1]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,(function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));var func=craftInvokerFunction(humanName,invokerArgsArray,null,rawInvoker,fn);if(undefined===proto[methodName].overloadTable){proto[methodName]=func}else{proto[methodName].overloadTable[argCount-1]=func}return[]}));return[]}))}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],(function(classType){classType=classType[0];var humanName=\"constructor \"+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(\"Cannot register multiple constructors with identical number of parameters (\"+(argCount-1)+\") for class '\"+classType.name+\"'! Overload resolution is currently only performed using the parameter count, not actual type info!\")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError(\"Cannot construct \"+classType.name+\" due to unbound types\",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,(function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+\" called with \"+arguments.length+\" arguments, expected \"+(argCount-1))}var destructors=[];var args=new Array(argCount);args[0]=rawConstructor;for(var i=1;i<argCount;++i){args[i]=argTypes[i][\"toWireType\"](destructors,arguments[i-1])}var ptr=invoker.apply(null,args);runDestructors(destructors);return argTypes[0][\"fromWireType\"](ptr)};return[]}));return[]}))}function __embind_register_class_function(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual){var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],(function(classType){classType=classType[0];var humanName=classType.name+\".\"+methodName;if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(\"Cannot call \"+humanName+\" due to unbound types\",rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,(function(argTypes){var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]}));return[]}))}function validateThis(this_,classType,humanName){if(!(this_ instanceof Object)){throwBindingError(humanName+' with invalid \"this\": '+this_)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(humanName+' incompatible with \"this\" of type '+this_.constructor.name)}if(!this_.$$.ptr){throwBindingError(\"cannot call emscripten binding method \"+humanName+\" on deleted object\")}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)}function __embind_register_class_property(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){fieldName=readLatin1String(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],(function(classType){classType=classType[0];var humanName=classType.name+\".\"+fieldName;var desc={get:(function(){throwUnboundTypeError(\"Cannot access \"+humanName+\" due to unbound types\",[getterReturnType,setterArgumentType])}),enumerable:true,configurable:true};if(setter){desc.set=(function(){throwUnboundTypeError(\"Cannot access \"+humanName+\" due to unbound types\",[getterReturnType,setterArgumentType])})}else{desc.set=(function(v){throwBindingError(humanName+\" is a read-only property\")})}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],(function(types){var getterReturnType=types[0];var desc={get:(function(){var ptr=validateThis(this,classType,humanName+\" getter\");return getterReturnType[\"fromWireType\"](getter(getterContext,ptr))}),enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=(function(v){var ptr=validateThis(this,classType,humanName+\" setter\");var destructors=[];setter(setterContext,ptr,setterArgumentType[\"toWireType\"](destructors,v));runDestructors(destructors)})}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]}));return[]}))}var emval_free_list=[];var emval_handle_array=[{},{value:undefined},{value:null},{value:true},{value:false}];function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_array.length;++i){if(emval_handle_array[i]!==undefined){++count}}return count}function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){if(emval_handle_array[i]!==undefined){return emval_handle_array[i]}}return null}function init_emval(){Module[\"count_emval_handles\"]=count_emval_handles;Module[\"get_first_emval\"]=get_first_emval}function __emval_register(value){switch(value){case undefined:{return 1};case null:{return 2};case true:{return 3};case false:{return 4};default:{var handle=emval_free_list.length?emval_free_list.pop():emval_handle_array.length;emval_handle_array[handle]={refcount:1,value:value};return handle}}}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":(function(handle){var rv=emval_handle_array[handle].value;__emval_decref(handle);return rv}),\"toWireType\":(function(destructors,value){return __emval_register(value)}),\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:null})}function enumReadValueFromPointer(name,shift,signed){switch(shift){case 0:return(function(pointer){var heap=signed?HEAP8:HEAPU8;return this[\"fromWireType\"](heap[pointer])});case 1:return(function(pointer){var heap=signed?HEAP16:HEAPU16;return this[\"fromWireType\"](heap[pointer>>1])});case 2:return(function(pointer){var heap=signed?HEAP32:HEAPU32;return this[\"fromWireType\"](heap[pointer>>2])});default:throw new TypeError(\"Unknown integer type: \"+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,\"fromWireType\":(function(c){return this.constructor.values[c]}),\"toWireType\":(function(destructors,c){return c.value}),\"argPackAdvance\":8,\"readValueFromPointer\":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+\" has unknown type \"+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,\"enum\");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+\"_\"+name,(function(){}))}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return\"null\"}var t=typeof v;if(t===\"object\"||t===\"array\"||t===\"function\"){return v.toString()}else{return\"\"+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return(function(pointer){return this[\"fromWireType\"](HEAPF32[pointer>>2])});case 3:return(function(pointer){return this[\"fromWireType\"](HEAPF64[pointer>>3])});default:throw new TypeError(\"Unknown float type: \"+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":(function(value){return value}),\"toWireType\":(function(destructors,value){if(typeof value!==\"number\"&&typeof value!==\"boolean\"){throw new TypeError('Cannot convert \"'+_embind_repr(value)+'\" to '+this.name)}return value}),\"argPackAdvance\":8,\"readValueFromPointer\":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,(function(){throwUnboundTypeError(\"Cannot call \"+name+\" due to unbound types\",argTypes)}),argCount-1);whenDependentTypesAreResolved([],argTypes,(function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]}))}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError(\"Unknown integer type: \"+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=(function(value){return value});if(minRange===0){var bitshift=32-8*size;fromWireType=(function(value){return value<<bitshift>>>bitshift})}var isUnsignedType=name.indexOf(\"unsigned\")!=-1;registerType(primitiveType,{name:name,\"fromWireType\":fromWireType,\"toWireType\":(function(destructors,value){if(typeof value!==\"number\"&&typeof value!==\"boolean\"){throw new TypeError('Cannot convert \"'+_embind_repr(value)+'\" to '+this.name)}if(value<minRange||value>maxRange){throw new TypeError('Passing a number \"'+_embind_repr(value)+'\" from JS side to C/C++ side to an argument of type \"'+name+'\", which is outside the valid range ['+minRange+\", \"+maxRange+\"]!\")}return isUnsignedType?value>>>0:value|0}),\"argPackAdvance\":8,\"readValueFromPointer\":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap[\"buffer\"],data,size)}name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":decodeMemoryView,\"argPackAdvance\":8,\"readValueFromPointer\":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_smart_ptr(rawType,rawPointeeType,name,sharingPolicy,getPointeeSignature,rawGetPointee,constructorSignature,rawConstructor,shareSignature,rawShare,destructorSignature,rawDestructor){name=readLatin1String(name);rawGetPointee=embind__requireFunction(getPointeeSignature,rawGetPointee);rawConstructor=embind__requireFunction(constructorSignature,rawConstructor);rawShare=embind__requireFunction(shareSignature,rawShare);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);whenDependentTypesAreResolved([rawType],[rawPointeeType],(function(pointeeType){pointeeType=pointeeType[0];var registeredPointer=new RegisteredPointer(name,pointeeType.registeredClass,false,false,true,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor);return[registeredPointer]}))}function __embind_register_std_string(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":(function(value){var length=HEAPU32[value>>2];var a=new Array(length);for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAPU8[value+4+i])}_free(value);return a.join(\"\")}),\"toWireType\":(function(destructors,value){if(value instanceof ArrayBuffer){value=new Uint8Array(value)}function getTAElement(ta,index){return ta[index]}function getStringElement(string,index){return string.charCodeAt(index)}var getElement;if(value instanceof Uint8Array){getElement=getTAElement}else if(value instanceof Uint8ClampedArray){getElement=getTAElement}else if(value instanceof Int8Array){getElement=getTAElement}else if(typeof value===\"string\"){getElement=getStringElement}else{throwBindingError(\"Cannot pass non-string to std::string\")}var length=value.length;var ptr=_malloc(4+length);HEAPU32[ptr>>2]=length;for(var i=0;i<length;++i){var charCode=getElement(value,i);if(charCode>255){_free(ptr);throwBindingError(\"String has UTF-16 code units that do not fit in 8 bits\")}HEAPU8[ptr+4+i]=charCode}if(destructors!==null){destructors.push(_free,ptr)}return ptr}),\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:(function(ptr){_free(ptr)})})}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var getHeap,shift;if(charSize===2){getHeap=(function(){return HEAPU16});shift=1}else if(charSize===4){getHeap=(function(){return HEAPU32});shift=2}registerType(rawType,{name:name,\"fromWireType\":(function(value){var HEAP=getHeap();var length=HEAPU32[value>>2];var a=new Array(length);var start=value+4>>shift;for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAP[start+i])}_free(value);return a.join(\"\")}),\"toWireType\":(function(destructors,value){var HEAP=getHeap();var length=value.length;var ptr=_malloc(4+length*charSize);HEAPU32[ptr>>2]=length;var start=ptr+4>>shift;for(var i=0;i<length;++i){HEAP[start+i]=value.charCodeAt(i)}if(destructors!==null){destructors.push(_free,ptr)}return ptr}),\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:(function(ptr){_free(ptr)})})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,\"argPackAdvance\":0,\"fromWireType\":(function(){return undefined}),\"toWireType\":(function(destructors,o){return undefined})})}function __emval_incref(handle){if(handle>4){emval_handle_array[handle].refcount+=1}}function __emval_take_value(type,argv){type=requireRegisteredType(type,\"_emval_take_value\");var v=type[\"readValueFromPointer\"](argv);return __emval_register(v)}function _abort(){Module[\"abort\"]()}function _emscripten_get_now(){abort()}function _emscripten_get_now_is_monotonic(){return ENVIRONMENT_IS_NODE||typeof dateNow!==\"undefined\"||(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&self[\"performance\"]&&self[\"performance\"][\"now\"]}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if(clk_id===1&&_emscripten_get_now_is_monotonic()){now=_emscripten_get_now()}else{___setErrNo(ERRNO_CODES.EINVAL);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}var DLFCN={error:null,errorMsg:null,loadedLibs:{},loadedLibNames:{}};function _dlclose(handle){if(!DLFCN.loadedLibs[handle]){DLFCN.errorMsg=\"Tried to dlclose() unopened handle: \"+handle;return 1}else{var lib_record=DLFCN.loadedLibs[handle];if(--lib_record.refcount==0){if(lib_record.module.cleanups){lib_record.module.cleanups.forEach((function(cleanup){cleanup()}))}delete DLFCN.loadedLibNames[lib_record.name];delete DLFCN.loadedLibs[handle]}return 0}}var _environ=STATICTOP;STATICTOP+=16;function ___buildEnvironment(env){var MAX_ENV_VALUES=64;var TOTAL_ENV_SIZE=1024;var poolPtr;var envPtr;if(!___buildEnvironment.called){___buildEnvironment.called=true;ENV[\"USER\"]=ENV[\"LOGNAME\"]=\"web_user\";ENV[\"PATH\"]=\"/\";ENV[\"PWD\"]=\"/\";ENV[\"HOME\"]=\"/home/web_user\";ENV[\"LANG\"]=\"C.UTF-8\";ENV[\"_\"]=Module[\"thisProgram\"];poolPtr=staticAlloc(TOTAL_ENV_SIZE);envPtr=staticAlloc(MAX_ENV_VALUES*4);HEAP32[envPtr>>2]=poolPtr;HEAP32[_environ>>2]=envPtr}else{envPtr=HEAP32[_environ>>2];poolPtr=HEAP32[envPtr>>2]}var strings=[];var totalSize=0;for(var key in env){if(typeof env[key]===\"string\"){var line=key+\"=\"+env[key];strings.push(line);totalSize+=line.length}}if(totalSize>TOTAL_ENV_SIZE){throw new Error(\"Environment size exceeded TOTAL_ENV_SIZE!\")}var ptrSize=4;for(var i=0;i<strings.length;i++){var line=strings[i];writeAsciiToMemory(line,poolPtr);HEAP32[envPtr+i*ptrSize>>2]=poolPtr;poolPtr+=line.length+1}HEAP32[envPtr+strings.length*ptrSize>>2]=0}var ENV={};function _dlopen(filename,flag){abort(\"To use dlopen, you need to use Emscripten's linking support, see https://github.com/kripken/emscripten/wiki/Linking\");var searchpaths=[];if(filename===0){filename=\"__self__\"}else{var strfilename=Pointer_stringify(filename);var isValidFile=(function(filename){var target=FS.findObject(filename);return target&&!target.isFolder&&!target.isDevice});if(isValidFile(strfilename)){filename=strfilename}else{if(ENV[\"LD_LIBRARY_PATH\"]){searchpaths=ENV[\"LD_LIBRARY_PATH\"].split(\":\")}for(var ident in searchpaths){var searchfile=PATH.join2(searchpaths[ident],strfilename);if(isValidFile(searchfile)){filename=searchfile;break}}}}if(DLFCN.loadedLibNames[filename]){var handle=DLFCN.loadedLibNames[filename];DLFCN.loadedLibs[handle].refcount++;return handle}if(filename===\"__self__\"){var handle=-1;var lib_module=Module}else{var target=FS.findObject(filename);if(!target||target.isFolder||target.isDevice){DLFCN.errorMsg=\"Could not find dynamic lib: \"+filename;return 0}FS.forceLoadFile(target);var lib_module;try{var lib_data=FS.readFile(filename,{encoding:\"binary\"});if(!(lib_data instanceof Uint8Array))lib_data=new Uint8Array(lib_data);lib_module=loadWebAssemblyModule(lib_data)}catch(e){DLFCN.errorMsg=\"Could not evaluate dynamic lib: \"+filename+\"\\n\"+e;return 0}var handle=1;for(var key in DLFCN.loadedLibs){if(DLFCN.loadedLibs.hasOwnProperty(key))handle++}if(flag&256){for(var ident in lib_module){if(lib_module.hasOwnProperty(ident)){if(ident[0]==\"_\"){Module[ident]=lib_module[ident]}}}}}DLFCN.loadedLibs[handle]={refcount:1,name:filename,module:lib_module};DLFCN.loadedLibNames[filename]=handle;return handle}function _dlsym(handle,symbol){symbol=Pointer_stringify(symbol);if(!DLFCN.loadedLibs[handle]){DLFCN.errorMsg=\"Tried to dlsym() from an unopened handle: \"+handle;return 0}else{var lib=DLFCN.loadedLibs[handle];symbol=\"_\"+symbol;if(!lib.module.hasOwnProperty(symbol)){DLFCN.errorMsg='Tried to lookup unknown symbol \"'+symbol+'\" in dynamic lib: '+lib.name;return 0}else{var result=lib.module[symbol];if(typeof result===\"function\"){return addFunction(result)}return result}}}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method=\"timeout\"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method=\"rAF\"}else if(mode==2){if(typeof setImmediate===\"undefined\"){var setImmediates=[];var emscriptenMainLoopMessageId=\"setimmediate\";function Browser_setImmediate_messageHandler(event){if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}}addEventListener(\"message\",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module[\"setImmediates\"]===undefined)Module[\"setImmediates\"]=[];Module[\"setImmediates\"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,\"*\")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method=\"immediate\"}return 0}function _emscripten_set_main_loop(func,fps,simulateInfiniteLoop,arg,noSetTiming){Module[\"noExitRuntime\"]=true;assert(!Browser.mainLoop.func,\"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.\");Browser.mainLoop.func=func;Browser.mainLoop.arg=arg;var browserIterationFunc;if(typeof arg!==\"undefined\"){browserIterationFunc=(function(){Module[\"dynCall_vi\"](func,arg)})}else{browserIterationFunc=(function(){Module[\"dynCall_v\"](func)})}var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}console.log('main loop blocker \"'+blocker.name+'\" took '+(Date.now()-start)+\" ms\");Browser.mainLoop.updateStatus();if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}if(Browser.mainLoop.method===\"timeout\"&&Module.ctx){Module.printErr(\"Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!\");Browser.mainLoop.method=\"\"}Browser.mainLoop.runIter(browserIterationFunc);if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;if(typeof SDL===\"object\"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0)_emscripten_set_main_loop_timing(0,1e3/fps);else _emscripten_set_main_loop_timing(1,1);Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw\"SimulateInfiniteLoop\"}}var Browser={mainLoop:{scheduler:null,method:\"\",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:(function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++}),resume:(function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;_emscripten_set_main_loop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()}),updateStatus:(function(){if(Module[\"setStatus\"]){var message=Module[\"statusMessage\"]||\"Please wait...\";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module[\"setStatus\"](message+\" (\"+(expected-remaining)+\"/\"+expected+\")\")}else{Module[\"setStatus\"](message)}}else{Module[\"setStatus\"](\"\")}}}),runIter:(function(func){if(ABORT)return;if(Module[\"preMainLoop\"]){var preRet=Module[\"preMainLoop\"]();if(preRet===false){return}}try{func()}catch(e){if(e instanceof ExitStatus){return}else{if(e&&typeof e===\"object\"&&e.stack)Module.printErr(\"exception thrown: \"+[e,e.stack]);throw e}}if(Module[\"postMainLoop\"])Module[\"postMainLoop\"]()})},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:(function(){if(!Module[\"preloadPlugins\"])Module[\"preloadPlugins\"]=[];if(Browser.initted)return;Browser.initted=true;try{new Blob;Browser.hasBlobConstructor=true}catch(e){Browser.hasBlobConstructor=false;console.log(\"warning: no blob constructor, cannot create blobs with mimetypes\")}Browser.BlobBuilder=typeof MozBlobBuilder!=\"undefined\"?MozBlobBuilder:typeof WebKitBlobBuilder!=\"undefined\"?WebKitBlobBuilder:!Browser.hasBlobConstructor?console.log(\"warning: no BlobBuilder\"):null;Browser.URLObject=typeof window!=\"undefined\"?window.URL?window.URL:window.webkitURL:undefined;if(!Module.noImageDecoding&&typeof Browser.URLObject===\"undefined\"){console.log(\"warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.\");Module.noImageDecoding=true}var imagePlugin={};imagePlugin[\"canHandle\"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin[\"handle\"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=null;if(Browser.hasBlobConstructor){try{b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([(new Uint8Array(byteArray)).buffer],{type:Browser.getMimetype(name)})}}catch(e){warnOnce(\"Blob constructor present but fails: \"+e+\"; falling back to blob builder\")}}if(!b){var bb=new Browser.BlobBuilder;bb.append((new Uint8Array(byteArray)).buffer);b=bb.getBlob()}var url=Browser.URLObject.createObjectURL(b);var img=new Image;img.onload=function img_onload(){assert(img.complete,\"Image \"+name+\" could not be decoded\");var canvas=document.createElement(\"canvas\");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext(\"2d\");ctx.drawImage(img,0,0);Module[\"preloadedImages\"][name]=canvas;Browser.URLObject.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=function img_onerror(event){console.log(\"Image \"+url+\" could not be decoded\");if(onerror)onerror()};img.src=url};Module[\"preloadPlugins\"].push(imagePlugin);var audioPlugin={};audioPlugin[\"canHandle\"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{\".ogg\":1,\".wav\":1,\".mp3\":1}};audioPlugin[\"handle\"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;Module[\"preloadedAudios\"][name]=audio;if(onload)onload(byteArray)}function fail(){if(done)return;done=true;Module[\"preloadedAudios\"][name]=new Audio;if(onerror)onerror()}if(Browser.hasBlobConstructor){try{var b=new Blob([byteArray],{type:Browser.getMimetype(name)})}catch(e){return fail()}var url=Browser.URLObject.createObjectURL(b);var audio=new Audio;audio.addEventListener(\"canplaythrough\",(function(){finish(audio)}),false);audio.onerror=function audio_onerror(event){if(done)return;console.log(\"warning: browser could not fully decode audio \"+name+\", trying slower base64 approach\");function encode64(data){var BASE=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";var PAD=\"=\";var ret=\"\";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src=\"data:audio/x-\"+name.substr(-3)+\";base64,\"+encode64(byteArray);finish(audio)};audio.src=url;Browser.safeSetTimeout((function(){finish(audio)}),1e4)}else{return fail()}};Module[\"preloadPlugins\"].push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document[\"pointerLockElement\"]===Module[\"canvas\"]||document[\"mozPointerLockElement\"]===Module[\"canvas\"]||document[\"webkitPointerLockElement\"]===Module[\"canvas\"]||document[\"msPointerLockElement\"]===Module[\"canvas\"]}var canvas=Module[\"canvas\"];if(canvas){canvas.requestPointerLock=canvas[\"requestPointerLock\"]||canvas[\"mozRequestPointerLock\"]||canvas[\"webkitRequestPointerLock\"]||canvas[\"msRequestPointerLock\"]||(function(){});canvas.exitPointerLock=document[\"exitPointerLock\"]||document[\"mozExitPointerLock\"]||document[\"webkitExitPointerLock\"]||document[\"msExitPointerLock\"]||(function(){});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener(\"pointerlockchange\",pointerLockChange,false);document.addEventListener(\"mozpointerlockchange\",pointerLockChange,false);document.addEventListener(\"webkitpointerlockchange\",pointerLockChange,false);document.addEventListener(\"mspointerlockchange\",pointerLockChange,false);if(Module[\"elementPointerLock\"]){canvas.addEventListener(\"click\",(function(ev){if(!Browser.pointerLock&&Module[\"canvas\"].requestPointerLock){Module[\"canvas\"].requestPointerLock();ev.preventDefault()}}),false)}}}),createContext:(function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}else{ctx=canvas.getContext(\"2d\")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx===\"undefined\",\"cannot set in module if GLctx is used, but we are a non-GL context that would replace it\");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach((function(callback){callback()}));Browser.init()}return ctx}),destroyContext:(function(canvas,useWebGL,setInModule){}),fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:(function(lockPointer,resizeCanvas,vrDevice){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;Browser.vrDevice=vrDevice;if(typeof Browser.lockPointer===\"undefined\")Browser.lockPointer=true;if(typeof Browser.resizeCanvas===\"undefined\")Browser.resizeCanvas=false;if(typeof Browser.vrDevice===\"undefined\")Browser.vrDevice=null;var canvas=Module[\"canvas\"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvasContainer){canvas.exitFullscreen=document[\"exitFullscreen\"]||document[\"cancelFullScreen\"]||document[\"mozCancelFullScreen\"]||document[\"msExitFullscreen\"]||document[\"webkitCancelFullScreen\"]||(function(){});canvas.exitFullscreen=canvas.exitFullscreen.bind(document);if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module[\"onFullScreen\"])Module[\"onFullScreen\"](Browser.isFullscreen);if(Module[\"onFullscreen\"])Module[\"onFullscreen\"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener(\"fullscreenchange\",fullscreenChange,false);document.addEventListener(\"mozfullscreenchange\",fullscreenChange,false);document.addEventListener(\"webkitfullscreenchange\",fullscreenChange,false);document.addEventListener(\"MSFullscreenChange\",fullscreenChange,false)}var canvasContainer=document.createElement(\"div\");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer[\"requestFullscreen\"]||canvasContainer[\"mozRequestFullScreen\"]||canvasContainer[\"msRequestFullscreen\"]||(canvasContainer[\"webkitRequestFullscreen\"]?(function(){canvasContainer[\"webkitRequestFullscreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"])}):null)||(canvasContainer[\"webkitRequestFullScreen\"]?(function(){canvasContainer[\"webkitRequestFullScreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"])}):null);if(vrDevice){canvasContainer.requestFullscreen({vrDisplay:vrDevice})}else{canvasContainer.requestFullscreen()}}),requestFullScreen:(function(lockPointer,resizeCanvas,vrDevice){Module.printErr(\"Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.\");Browser.requestFullScreen=(function(lockPointer,resizeCanvas,vrDevice){return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)});return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)}),nextRAF:0,fakeRequestAnimationFrame:(function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)}),requestAnimationFrame:function requestAnimationFrame(func){if(typeof window===\"undefined\"){Browser.fakeRequestAnimationFrame(func)}else{if(!window.requestAnimationFrame){window.requestAnimationFrame=window[\"requestAnimationFrame\"]||window[\"mozRequestAnimationFrame\"]||window[\"webkitRequestAnimationFrame\"]||window[\"msRequestAnimationFrame\"]||window[\"oRequestAnimationFrame\"]||Browser.fakeRequestAnimationFrame}window.requestAnimationFrame(func)}},safeCallback:(function(func){return(function(){if(!ABORT)return func.apply(null,arguments)})}),allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:(function(){Browser.allowAsyncCallbacks=false}),resumeAsyncCallbacks:(function(){Browser.allowAsyncCallbacks=true;if(Browser.queuedAsyncCallbacks.length>0){var callbacks=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[];callbacks.forEach((function(func){func()}))}}),safeRequestAnimationFrame:(function(func){return Browser.requestAnimationFrame((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}}))}),safeSetTimeout:(function(func,timeout){Module[\"noExitRuntime\"]=true;return setTimeout((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}}),timeout)}),safeSetInterval:(function(func,timeout){Module[\"noExitRuntime\"]=true;return setInterval((function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}}),timeout)}),getMimetype:(function(name){return{\"jpg\":\"image/jpeg\",\"jpeg\":\"image/jpeg\",\"png\":\"image/png\",\"bmp\":\"image/bmp\",\"ogg\":\"audio/ogg\",\"wav\":\"audio/wav\",\"mp3\":\"audio/mpeg\"}[name.substr(name.lastIndexOf(\".\")+1)]}),getUserMedia:(function(func){if(!window.getUserMedia){window.getUserMedia=navigator[\"getUserMedia\"]||navigator[\"mozGetUserMedia\"]}window.getUserMedia(func)}),getMovementX:(function(event){return event[\"movementX\"]||event[\"mozMovementX\"]||event[\"webkitMovementX\"]||0}),getMovementY:(function(event){return event[\"movementY\"]||event[\"mozMovementY\"]||event[\"webkitMovementY\"]||0}),getMouseWheelDelta:(function(event){var delta=0;switch(event.type){case\"DOMMouseScroll\":delta=event.detail;break;case\"mousewheel\":delta=event.wheelDelta;break;case\"wheel\":delta=event[\"deltaY\"];break;default:throw\"unrecognized mouse wheel event: \"+event.type}return delta}),mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:(function(event){if(Browser.pointerLock){if(event.type!=\"mousemove\"&&\"mozMovementX\"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!=\"undefined\"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module[\"canvas\"].getBoundingClientRect();var cw=Module[\"canvas\"].width;var ch=Module[\"canvas\"].height;var scrollX=typeof window.scrollX!==\"undefined\"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!==\"undefined\"?window.scrollY:window.pageYOffset;if(event.type===\"touchstart\"||event.type===\"touchend\"||event.type===\"touchmove\"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type===\"touchstart\"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type===\"touchend\"||event.type===\"touchmove\"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}}),asyncLoad:(function(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency(\"al \"+url):\"\";Module[\"readAsync\"](url,(function(arrayBuffer){assert(arrayBuffer,'Loading data file \"'+url+'\" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)}),(function(event){if(onerror){onerror()}else{throw'Loading data file \"'+url+'\" failed.'}}));if(dep)addRunDependency(dep)}),resizeListeners:[],updateResizeListeners:(function(){var canvas=Module[\"canvas\"];Browser.resizeListeners.forEach((function(listener){listener(canvas.width,canvas.height)}))}),setCanvasSize:(function(width,height,noUpdates){var canvas=Module[\"canvas\"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()}),windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:(function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()}),setWindowedCanvasSize:(function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()}),updateCanvasDimensions:(function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module[\"forcedAspectRatio\"]&&Module[\"forcedAspectRatio\"]>0){if(w/h<Module[\"forcedAspectRatio\"]){w=Math.round(h*Module[\"forcedAspectRatio\"])}else{h=Math.round(w/Module[\"forcedAspectRatio\"])}}if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvas.parentNode&&typeof screen!=\"undefined\"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!=\"undefined\"){canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!=\"undefined\"){if(w!=wNative||h!=hNative){canvas.style.setProperty(\"width\",w+\"px\",\"important\");canvas.style.setProperty(\"height\",h+\"px\",\"important\")}else{canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}}}),wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:(function(){var handle=Browser.nextWgetRequestHandle;Browser.nextWgetRequestHandle++;return handle})};var EGL={errorCode:12288,defaultDisplayInitialized:false,currentContext:0,currentReadSurface:0,currentDrawSurface:0,stringCache:{},setErrorCode:(function(code){EGL.errorCode=code}),chooseConfig:(function(display,attribList,config,config_size,numConfigs){if(display!=62e3){EGL.setErrorCode(12296);return 0}if((!config||!config_size)&&!numConfigs){EGL.setErrorCode(12300);return 0}if(numConfigs){HEAP32[numConfigs>>2]=1}if(config&&config_size>0){HEAP32[config>>2]=62002}EGL.setErrorCode(12288);return 1})};function _eglGetCurrentDisplay(){return EGL.currentContext?62e3:0}function _eglGetProcAddress(name_){return _emscripten_GetProcAddress(name_)}function _eglQueryString(display,name){if(display!=62e3){EGL.setErrorCode(12296);return 0}EGL.setErrorCode(12288);if(EGL.stringCache[name])return EGL.stringCache[name];var ret;switch(name){case 12371:ret=allocate(intArrayFromString(\"Emscripten\"),\"i8\",ALLOC_NORMAL);break;case 12372:ret=allocate(intArrayFromString(\"1.4 Emscripten EGL\"),\"i8\",ALLOC_NORMAL);break;case 12373:ret=allocate(intArrayFromString(\"\"),\"i8\",ALLOC_NORMAL);break;case 12429:ret=allocate(intArrayFromString(\"OpenGL_ES\"),\"i8\",ALLOC_NORMAL);break;default:EGL.setErrorCode(12300);return 0}EGL.stringCache[name]=ret;return ret}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},stringiCache:{},tempFixedLengthArray:[],packAlignment:4,unpackAlignment:4,init:(function(){GL.miniTempBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i<GL.MINI_TEMP_BUFFER_SIZE;i++){GL.miniTempBufferViews[i]=GL.miniTempBuffer.subarray(0,i+1)}for(var i=0;i<32;i++){GL.tempFixedLengthArray.push(new Array(i))}}),recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:(function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret}),MINI_TEMP_BUFFER_SIZE:256,miniTempBuffer:null,miniTempBufferViews:[0],getSource:(function(shader,count,string,length){var source=\"\";for(var i=0;i<count;++i){var frag;if(length){var len=HEAP32[length+i*4>>2];if(len<0){frag=Pointer_stringify(HEAP32[string+i*4>>2])}else{frag=Pointer_stringify(HEAP32[string+i*4>>2],len)}}else{frag=Pointer_stringify(HEAP32[string+i*4>>2])}source+=frag}return source}),createContext:(function(canvas,webGLContextAttributes){if(typeof webGLContextAttributes[\"majorVersion\"]===\"undefined\"&&typeof webGLContextAttributes[\"minorVersion\"]===\"undefined\"){if(typeof WebGL2RenderingContext!==\"undefined\")webGLContextAttributes[\"majorVersion\"]=2;else webGLContextAttributes[\"majorVersion\"]=1;webGLContextAttributes[\"minorVersion\"]=0}var ctx;var errorInfo=\"?\";function onContextCreationError(event){errorInfo=event.statusMessage||errorInfo}try{canvas.addEventListener(\"webglcontextcreationerror\",onContextCreationError,false);try{if(webGLContextAttributes[\"majorVersion\"]==1&&webGLContextAttributes[\"minorVersion\"]==0){ctx=canvas.getContext(\"webgl\",webGLContextAttributes)||canvas.getContext(\"experimental-webgl\",webGLContextAttributes)}else if(webGLContextAttributes[\"majorVersion\"]==2&&webGLContextAttributes[\"minorVersion\"]==0){ctx=canvas.getContext(\"webgl2\",webGLContextAttributes)}else{throw\"Unsupported WebGL context version \"+majorVersion+\".\"+minorVersion+\"!\"}}finally{canvas.removeEventListener(\"webglcontextcreationerror\",onContextCreationError,false)}if(!ctx)throw\":(\"}catch(e){Module.print(\"Could not create canvas: \"+[errorInfo,e,JSON.stringify(webGLContextAttributes)]);return 0}if(!ctx)return 0;var context=GL.registerContext(ctx,webGLContextAttributes);return context}),registerContext:(function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes[\"majorVersion\"],GLctx:ctx};function getChromeVersion(){var raw=navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./);return raw?parseInt(raw[2],10):false}context.supportsWebGL2EntryPoints=context.version>=2&&(getChromeVersion()===false||getChromeVersion()>=58);if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes[\"enableExtensionsByDefault\"]===\"undefined\"||webGLContextAttributes[\"enableExtensionsByDefault\"]){GL.initExtensions(context)}return handle}),makeContextCurrent:(function(contextHandle){var context=GL.contexts[contextHandle];if(!context)return false;GLctx=Module.ctx=context.GLctx;GL.currentContext=context;return true}),getContext:(function(contextHandle){return GL.contexts[contextHandle]}),deleteContext:(function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents===\"object\")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null}),initExtensions:(function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;context.maxVertexAttribs=GLctx.getParameter(GLctx.MAX_VERTEX_ATTRIBS);if(context.version<2){var instancedArraysExt=GLctx.getExtension(\"ANGLE_instanced_arrays\");if(instancedArraysExt){GLctx[\"vertexAttribDivisor\"]=(function(index,divisor){instancedArraysExt[\"vertexAttribDivisorANGLE\"](index,divisor)});GLctx[\"drawArraysInstanced\"]=(function(mode,first,count,primcount){instancedArraysExt[\"drawArraysInstancedANGLE\"](mode,first,count,primcount)});GLctx[\"drawElementsInstanced\"]=(function(mode,count,type,indices,primcount){instancedArraysExt[\"drawElementsInstancedANGLE\"](mode,count,type,indices,primcount)})}var vaoExt=GLctx.getExtension(\"OES_vertex_array_object\");if(vaoExt){GLctx[\"createVertexArray\"]=(function(){return vaoExt[\"createVertexArrayOES\"]()});GLctx[\"deleteVertexArray\"]=(function(vao){vaoExt[\"deleteVertexArrayOES\"](vao)});GLctx[\"bindVertexArray\"]=(function(vao){vaoExt[\"bindVertexArrayOES\"](vao)});GLctx[\"isVertexArray\"]=(function(vao){return vaoExt[\"isVertexArrayOES\"](vao)})}var drawBuffersExt=GLctx.getExtension(\"WEBGL_draw_buffers\");if(drawBuffersExt){GLctx[\"drawBuffers\"]=(function(n,bufs){drawBuffersExt[\"drawBuffersWEBGL\"](n,bufs)})}}GLctx.disjointTimerQueryExt=GLctx.getExtension(\"EXT_disjoint_timer_query\");var automaticallyEnabledExtensions=[\"OES_texture_float\",\"OES_texture_half_float\",\"OES_standard_derivatives\",\"OES_vertex_array_object\",\"WEBGL_compressed_texture_s3tc\",\"WEBGL_depth_texture\",\"OES_element_index_uint\",\"EXT_texture_filter_anisotropic\",\"ANGLE_instanced_arrays\",\"OES_texture_float_linear\",\"OES_texture_half_float_linear\",\"WEBGL_compressed_texture_atc\",\"WEBKIT_WEBGL_compressed_texture_pvrtc\",\"WEBGL_compressed_texture_pvrtc\",\"EXT_color_buffer_half_float\",\"WEBGL_color_buffer_float\",\"EXT_frag_depth\",\"EXT_sRGB\",\"WEBGL_draw_buffers\",\"WEBGL_shared_resources\",\"EXT_shader_texture_lod\",\"EXT_color_buffer_float\"];var exts=GLctx.getSupportedExtensions();if(exts&&exts.length>0){GLctx.getSupportedExtensions().forEach((function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext)}}))}}),populateUniformTable:(function(program){var p=GL.programs[program];GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var ptable=GL.programInfos[program];var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,GLctx.ACTIVE_UNIFORMS);for(var i=0;i<numUniforms;++i){var u=GLctx.getActiveUniform(p,i);var name=u.name;ptable.maxUniformLength=Math.max(ptable.maxUniformLength,name.length+1);if(name.indexOf(\"]\",name.length-1)!==-1){var ls=name.lastIndexOf(\"[\");name=name.slice(0,ls)}var loc=GLctx.getUniformLocation(p,name);if(loc!=null){var id=GL.getNewId(GL.uniforms);utable[name]=[u.size,id];GL.uniforms[id]=loc;for(var j=1;j<u.size;++j){var n=name+\"[\"+j+\"]\";loc=GLctx.getUniformLocation(p,n);id=GL.getNewId(GL.uniforms);GL.uniforms[id]=loc}}}})};function _emscripten_glActiveTexture(x0){GLctx[\"activeTexture\"](x0)}function _emscripten_glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glBindAttribLocation(program,index,name){name=Pointer_stringify(name);GLctx.bindAttribLocation(GL.programs[program],index,name)}function _emscripten_glBindBuffer(target,buffer){var bufferObj=buffer?GL.buffers[buffer]:null;if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,bufferObj)}function _emscripten_glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,framebuffer?GL.framebuffers[framebuffer]:null)}function _emscripten_glBindProgramARB(){Module[\"printErr\"](\"missing function: emscripten_glBindProgramARB\");abort(-1)}function _emscripten_glBindRenderbuffer(target,renderbuffer){GLctx.bindRenderbuffer(target,renderbuffer?GL.renderbuffers[renderbuffer]:null)}function _emscripten_glBindTexture(target,texture){GLctx.bindTexture(target,texture?GL.textures[texture]:null)}function _emscripten_glBindVertexArray(vao){GLctx[\"bindVertexArray\"](GL.vaos[vao])}function _emscripten_glBlendColor(x0,x1,x2,x3){GLctx[\"blendColor\"](x0,x1,x2,x3)}function _emscripten_glBlendEquation(x0){GLctx[\"blendEquation\"](x0)}function _emscripten_glBlendEquationSeparate(x0,x1){GLctx[\"blendEquationSeparate\"](x0,x1)}function _emscripten_glBlendFunc(x0,x1){GLctx[\"blendFunc\"](x0,x1)}function _emscripten_glBlendFuncSeparate(x0,x1,x2,x3){GLctx[\"blendFuncSeparate\"](x0,x1,x2,x3)}function _emscripten_glBufferData(target,size,data,usage){if(!data){GLctx.bufferData(target,size,usage)}else{if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferData(target,HEAPU8,usage,data,size);return}GLctx.bufferData(target,HEAPU8.subarray(data,data+size),usage)}}function _emscripten_glBufferSubData(target,offset,size,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _emscripten_glCheckFramebufferStatus(x0){return GLctx[\"checkFramebufferStatus\"](x0)}function _emscripten_glClear(x0){GLctx[\"clear\"](x0)}function _emscripten_glClearColor(x0,x1,x2,x3){GLctx[\"clearColor\"](x0,x1,x2,x3)}function _emscripten_glClearDepth(x0){GLctx[\"clearDepth\"](x0)}function _emscripten_glClearDepthf(x0){GLctx[\"clearDepth\"](x0)}function _emscripten_glClearStencil(x0){GLctx[\"clearStencil\"](x0)}function _emscripten_glClientActiveTexture(){Module[\"printErr\"](\"missing function: emscripten_glClientActiveTexture\");abort(-1)}function _emscripten_glColorMask(red,green,blue,alpha){GLctx.colorMask(!!red,!!green,!!blue,!!alpha)}function _emscripten_glColorPointer(){Module[\"printErr\"](\"missing function: emscripten_glColorPointer\");abort(-1)}function _emscripten_glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _emscripten_glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx[\"compressedTexImage2D\"](target,level,internalFormat,width,height,border,HEAPU8,data,imageSize);return}GLctx[\"compressedTexImage2D\"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCompressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx[\"compressedTexSubImage2D\"](target,level,xoffset,yoffset,width,height,format,HEAPU8,data,imageSize);return}GLctx[\"compressedTexSubImage2D\"](target,level,xoffset,yoffset,width,height,format,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCopyTexImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx[\"copyTexImage2D\"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCopyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx[\"copyTexSubImage2D\"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _emscripten_glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _emscripten_glCullFace(x0){GLctx[\"cullFace\"](x0)}function _emscripten_glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GL.currArrayBuffer)GL.currArrayBuffer=0;if(id==GL.currElementArrayBuffer)GL.currElementArrayBuffer=0}}function _emscripten_glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _emscripten_glDeleteObjectARB(){Module[\"printErr\"](\"missing function: emscripten_glDeleteObjectARB\");abort(-1)}function _emscripten_glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _emscripten_glDeleteRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}}function _emscripten_glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _emscripten_glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _emscripten_glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx[\"deleteVertexArray\"](GL.vaos[id]);GL.vaos[id]=null}}function _emscripten_glDepthFunc(x0){GLctx[\"depthFunc\"](x0)}function _emscripten_glDepthMask(flag){GLctx.depthMask(!!flag)}function _emscripten_glDepthRange(x0,x1){GLctx[\"depthRange\"](x0,x1)}function _emscripten_glDepthRangef(x0,x1){GLctx[\"depthRange\"](x0,x1)}function _emscripten_glDetachShader(program,shader){GLctx.detachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glDisable(x0){GLctx[\"disable\"](x0)}function _emscripten_glDisableVertexAttribArray(index){GLctx.disableVertexAttribArray(index)}function _emscripten_glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _emscripten_glDrawArraysInstanced(mode,first,count,primcount){GLctx[\"drawArraysInstanced\"](mode,first,count,primcount)}function _emscripten_glDrawBuffers(n,bufs){var bufArray=GL.tempFixedLengthArray[n];for(var i=0;i<n;i++){bufArray[i]=HEAP32[bufs+i*4>>2]}GLctx[\"drawBuffers\"](bufArray)}function _emscripten_glDrawElements(mode,count,type,indices){GLctx.drawElements(mode,count,type,indices)}function _emscripten_glDrawElementsInstanced(mode,count,type,indices,primcount){GLctx[\"drawElementsInstanced\"](mode,count,type,indices,primcount)}function _emscripten_glDrawRangeElements(mode,start,end,count,type,indices){_emscripten_glDrawElements(mode,count,type,indices)}function _emscripten_glEnable(x0){GLctx[\"enable\"](x0)}function _emscripten_glEnableClientState(){Module[\"printErr\"](\"missing function: emscripten_glEnableClientState\");abort(-1)}function _emscripten_glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function _emscripten_glFinish(){GLctx[\"finish\"]()}function _emscripten_glFlush(){GLctx[\"flush\"]()}function _emscripten_glFramebufferRenderbuffer(target,attachment,renderbuffertarget,renderbuffer){GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])}function _emscripten_glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _emscripten_glFrontFace(x0){GLctx[\"frontFace\"](x0)}function _emscripten_glFrustum(){Module[\"printErr\"](\"missing function: emscripten_glFrustum\");abort(-1)}function _emscripten_glGenBuffers(n,buffers){for(var i=0;i<n;i++){var buffer=GLctx.createBuffer();if(!buffer){GL.recordError(1282);while(i<n)HEAP32[buffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.buffers);buffer.name=id;GL.buffers[id]=buffer;HEAP32[buffers+i*4>>2]=id}}function _emscripten_glGenFramebuffers(n,ids){for(var i=0;i<n;++i){var framebuffer=GLctx.createFramebuffer();if(!framebuffer){GL.recordError(1282);while(i<n)HEAP32[ids+i++*4>>2]=0;return}var id=GL.getNewId(GL.framebuffers);framebuffer.name=id;GL.framebuffers[id]=framebuffer;HEAP32[ids+i*4>>2]=id}}function _emscripten_glGenRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var renderbuffer=GLctx.createRenderbuffer();if(!renderbuffer){GL.recordError(1282);while(i<n)HEAP32[renderbuffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.renderbuffers);renderbuffer.name=id;GL.renderbuffers[id]=renderbuffer;HEAP32[renderbuffers+i*4>>2]=id}}function _emscripten_glGenTextures(n,textures){for(var i=0;i<n;i++){var texture=GLctx.createTexture();if(!texture){GL.recordError(1282);while(i<n)HEAP32[textures+i++*4>>2]=0;return}var id=GL.getNewId(GL.textures);texture.name=id;GL.textures[id]=texture;HEAP32[textures+i*4>>2]=id}}function _emscripten_glGenVertexArrays(n,arrays){for(var i=0;i<n;i++){var vao=GLctx[\"createVertexArray\"]();if(!vao){GL.recordError(1282);while(i<n)HEAP32[arrays+i++*4>>2]=0;return}var id=GL.getNewId(GL.vaos);vao.name=id;GL.vaos[id]=vao;HEAP32[arrays+i*4>>2]=id}}function _emscripten_glGenerateMipmap(x0){GLctx[\"generateMipmap\"](x0)}function _emscripten_glGetActiveAttrib(program,index,bufSize,length,size,type,name){program=GL.programs[program];var info=GLctx.getActiveAttrib(program,index);if(!info)return;if(bufSize>0&&name){var numBytesWrittenExclNull=stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}function _emscripten_glGetActiveUniform(program,index,bufSize,length,size,type,name){program=GL.programs[program];var info=GLctx.getActiveUniform(program,index);if(!info)return;if(bufSize>0&&name){var numBytesWrittenExclNull=stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}function _emscripten_glGetAttachedShaders(program,maxCount,count,shaders){var result=GLctx.getAttachedShaders(GL.programs[program]);var len=result.length;if(len>maxCount){len=maxCount}HEAP32[count>>2]=len;for(var i=0;i<len;++i){var id=GL.shaders.indexOf(result[i]);HEAP32[shaders+i*4>>2]=id}}function _emscripten_glGetAttribLocation(program,name){program=GL.programs[program];name=Pointer_stringify(name);return GLctx.getAttribLocation(program,name)}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!==\"Integer\"&&type!==\"Integer64\"){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats.length;break;case 33309:if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1282);return}var exts=GLctx.getSupportedExtensions();ret=2*exts.length;break;case 33307:case 33308:if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case\"number\":ret=result;break;case\"boolean\":ret=result?1:0;break;case\"string\":GL.recordError(1280);return;case\"object\":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 35097:case 36389:case 34068:{ret=0;break};default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case\"Integer\":HEAP32[p+i*4>>2]=result[i];break;case\"Float\":HEAPF32[p+i*4>>2]=result[i];break;case\"Boolean\":HEAP8[p+i>>0]=result[i]?1:0;break;default:throw\"internal glGet error, bad type: \"+type}}return}else if(result instanceof WebGLBuffer||result instanceof WebGLProgram||result instanceof WebGLFramebuffer||result instanceof WebGLRenderbuffer||result instanceof WebGLQuery||result instanceof WebGLSampler||result instanceof WebGLSync||result instanceof WebGLTransformFeedback||result instanceof WebGLVertexArrayObject||result instanceof WebGLTexture){ret=result.name|0}else{GL.recordError(1280);return}break;default:GL.recordError(1280);return}}switch(type){case\"Integer64\":tempI64=[ret>>>0,(tempDouble=ret,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[p>>2]=tempI64[0],HEAP32[p+4>>2]=tempI64[1];break;case\"Integer\":HEAP32[p>>2]=ret;break;case\"Float\":HEAPF32[p>>2]=ret;break;case\"Boolean\":HEAP8[p>>0]=ret?1:0;break;default:throw\"internal glGet error, bad type: \"+type}}function _emscripten_glGetBooleanv(name_,p){emscriptenWebGLGet(name_,p,\"Boolean\")}function _emscripten_glGetBufferParameteriv(target,value,data){if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)}function _emscripten_glGetError(){if(GL.lastError){var error=GL.lastError;GL.lastError=0;return error}else{return GLctx.getError()}}function _emscripten_glGetFloatv(name_,p){emscriptenWebGLGet(name_,p,\"Float\")}function _emscripten_glGetFramebufferAttachmentParameteriv(target,attachment,pname,params){var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result}function _emscripten_glGetInfoLogARB(){Module[\"printErr\"](\"missing function: emscripten_glGetInfoLogARB\");abort(-1)}function _emscripten_glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,\"Integer\")}function _emscripten_glGetObjectParameterivARB(){Module[\"printErr\"](\"missing function: emscripten_glGetObjectParameterivARB\");abort(-1)}function _emscripten_glGetPointerv(){Module[\"printErr\"](\"missing function: emscripten_glGetPointerv\");abort(-1)}function _emscripten_glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log=\"(unknown error)\";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _emscripten_glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,GLctx.ACTIVE_ATTRIBUTES);ptable.maxAttributeLength=0;for(var i=0;i<numAttribs;++i){var activeAttrib=GLctx.getActiveAttrib(program,i);ptable.maxAttributeLength=Math.max(ptable.maxAttributeLength,activeAttrib.name.length+1)}}HEAP32[p>>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,GLctx.ACTIVE_UNIFORM_BLOCKS);ptable.maxUniformBlockNameLength=0;for(var i=0;i<numBlocks;++i){var activeBlockName=GLctx.getActiveUniformBlockName(program,i);ptable.maxUniformBlockNameLength=Math.max(ptable.maxUniformBlockNameLength,activeBlockName.length+1)}}HEAP32[p>>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _emscripten_glGetRenderbufferParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)}function _emscripten_glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _emscripten_glGetShaderPrecisionFormat(shaderType,precisionType,range,precision){var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision}function _emscripten_glGetShaderSource(shader,bufSize,length,source){var result=GLctx.getShaderSource(GL.shaders[shader]);if(!result)return;if(bufSize>0&&source){var numBytesWrittenExclNull=stringToUTF8(result,source,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _emscripten_glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source===null||source.length==0?0:source.length+1;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _emscripten_glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7936:case 7937:case 37445:case 37446:ret=allocate(intArrayFromString(GLctx.getParameter(name_)),\"i8\",ALLOC_NORMAL);break;case 7938:var glVersion=GLctx.getParameter(GLctx.VERSION);if(GLctx.canvas.GLctxObject.version>=2)glVersion=\"OpenGL ES 3.0 (\"+glVersion+\")\";else{glVersion=\"OpenGL ES 2.0 (\"+glVersion+\")\"}ret=allocate(intArrayFromString(glVersion),\"i8\",ALLOC_NORMAL);break;case 7939:var exts=GLctx.getSupportedExtensions();var gl_exts=[];for(var i=0;i<exts.length;++i){gl_exts.push(exts[i]);gl_exts.push(\"GL_\"+exts[i])}ret=allocate(intArrayFromString(gl_exts.join(\" \")),\"i8\",ALLOC_NORMAL);break;case 35724:var glslVersion=GLctx.getParameter(GLctx.SHADING_LANGUAGE_VERSION);var ver_re=/^WebGL GLSL ES ([0-9]\\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+\"0\";glslVersion=\"OpenGL ES GLSL ES \"+ver_num[1]+\" (\"+glslVersion+\")\"}ret=allocate(intArrayFromString(glslVersion),\"i8\",ALLOC_NORMAL);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _emscripten_glGetStringi(name,index){if(GLctx.canvas.GLctxObject.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=GLctx.getSupportedExtensions();var gl_exts=[];for(var i=0;i<exts.length;++i){gl_exts.push(allocate(intArrayFromString(exts[i]),\"i8\",ALLOC_NORMAL));gl_exts.push(allocate(intArrayFromString(\"GL_\"+exts[i]),\"i8\",ALLOC_NORMAL))}stringiCache=GL.stringiCache[name]=gl_exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}}function _emscripten_glGetTexParameterfv(target,pname,params){if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetTexParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetUniformLocation(program,name){name=Pointer_stringify(name);var arrayOffset=0;if(name.indexOf(\"]\",name.length-1)!==-1){var ls=name.lastIndexOf(\"[\");var arrayIndex=name.slice(ls+1,-1);if(arrayIndex.length>0){arrayOffset=parseInt(arrayIndex);if(arrayOffset<0){return-1}}name=name.slice(0,ls)}var ptable=GL.programInfos[program];if(!ptable){return-1}var utable=ptable.uniforms;var uniformInfo=utable[name];if(uniformInfo&&arrayOffset<uniformInfo[0]){return uniformInfo[1]+arrayOffset}else{return-1}}function emscriptenWebGLGetUniform(program,location,params,type){if(!params){GL.recordError(1281);return}var data=GLctx.getUniform(GL.programs[program],GL.uniforms[location]);if(typeof data==\"number\"||typeof data==\"boolean\"){switch(type){case\"Integer\":HEAP32[params>>2]=data;break;case\"Float\":HEAPF32[params>>2]=data;break;default:throw\"internal emscriptenWebGLGetUniform() error, bad type: \"+type}}else{for(var i=0;i<data.length;i++){switch(type){case\"Integer\":HEAP32[params+i*4>>2]=data[i];break;case\"Float\":HEAPF32[params+i*4>>2]=data[i];break;default:throw\"internal emscriptenWebGLGetUniform() error, bad type: \"+type}}}}function _emscripten_glGetUniformfv(program,location,params){emscriptenWebGLGetUniform(program,location,params,\"Float\")}function _emscripten_glGetUniformiv(program,location,params){emscriptenWebGLGetUniform(program,location,params,\"Integer\")}function _emscripten_glGetVertexAttribPointerv(index,pname,pointer){if(!pointer){GL.recordError(1281);return}HEAP32[pointer>>2]=GLctx.getVertexAttribOffset(index,pname)}function emscriptenWebGLGetVertexAttrib(index,pname,params,type){if(!params){GL.recordError(1281);return}var data=GLctx.getVertexAttrib(index,pname);if(pname==34975){HEAP32[params>>2]=data[\"name\"]}else if(typeof data==\"number\"||typeof data==\"boolean\"){switch(type){case\"Integer\":HEAP32[params>>2]=data;break;case\"Float\":HEAPF32[params>>2]=data;break;case\"FloatToInteger\":HEAP32[params>>2]=Math.fround(data);break;default:throw\"internal emscriptenWebGLGetVertexAttrib() error, bad type: \"+type}}else{for(var i=0;i<data.length;i++){switch(type){case\"Integer\":HEAP32[params+i*4>>2]=data[i];break;case\"Float\":HEAPF32[params+i*4>>2]=data[i];break;case\"FloatToInteger\":HEAP32[params+i*4>>2]=Math.fround(data[i]);break;default:throw\"internal emscriptenWebGLGetVertexAttrib() error, bad type: \"+type}}}}function _emscripten_glGetVertexAttribfv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,\"Float\")}function _emscripten_glGetVertexAttribiv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,\"FloatToInteger\")}function _emscripten_glHint(x0,x1){GLctx[\"hint\"](x0,x1)}function _emscripten_glIsBuffer(buffer){var b=GL.buffers[buffer];if(!b)return 0;return GLctx.isBuffer(b)}function _emscripten_glIsEnabled(x0){return GLctx[\"isEnabled\"](x0)}function _emscripten_glIsFramebuffer(framebuffer){var fb=GL.framebuffers[framebuffer];if(!fb)return 0;return GLctx.isFramebuffer(fb)}function _emscripten_glIsProgram(program){program=GL.programs[program];if(!program)return 0;return GLctx.isProgram(program)}function _emscripten_glIsRenderbuffer(renderbuffer){var rb=GL.renderbuffers[renderbuffer];if(!rb)return 0;return GLctx.isRenderbuffer(rb)}function _emscripten_glIsShader(shader){var s=GL.shaders[shader];if(!s)return 0;return GLctx.isShader(s)}function _emscripten_glIsTexture(texture){var texture=GL.textures[texture];if(!texture)return 0;return GLctx.isTexture(texture)}function _emscripten_glIsVertexArray(array){var vao=GL.vaos[array];if(!vao)return 0;return GLctx[\"isVertexArray\"](vao)}function _emscripten_glLineWidth(x0){GLctx[\"lineWidth\"](x0)}function _emscripten_glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.programInfos[program]=null;GL.populateUniformTable(program)}function _emscripten_glLoadIdentity(){throw\"Legacy GL function (glLoadIdentity) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.\"}function _emscripten_glLoadMatrixf(){Module[\"printErr\"](\"missing function: emscripten_glLoadMatrixf\");abort(-1)}function _emscripten_glMatrixMode(){throw\"Legacy GL function (glMatrixMode) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.\"}function _emscripten_glNormalPointer(){Module[\"printErr\"](\"missing function: emscripten_glNormalPointer\");abort(-1)}function _emscripten_glPixelStorei(pname,param){if(pname==3333){GL.packAlignment=param}else if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _emscripten_glPolygonOffset(x0,x1){GLctx[\"polygonOffset\"](x0,x1)}function emscriptenWebGLComputeImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return Math.floor((x+y-1)/y)*y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height<=0?0:(height-1)*alignedRowSize+plainRowSize}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var sizePerPixel;var numChannels;switch(format){case 6406:case 6409:case 6402:case 6403:case 36244:numChannels=1;break;case 6410:case 33319:case 33320:numChannels=2;break;case 6407:case 35904:case 36248:numChannels=3;break;case 6408:case 35906:case 36249:numChannels=4;break;default:GL.recordError(1280);return null}switch(type){case 5121:case 5120:sizePerPixel=numChannels*1;break;case 5123:case 36193:case 5131:case 5122:sizePerPixel=numChannels*2;break;case 5125:case 5126:case 5124:sizePerPixel=numChannels*4;break;case 34042:case 35902:case 33640:case 35899:case 34042:sizePerPixel=4;break;case 33635:case 32819:case 32820:sizePerPixel=2;break;default:GL.recordError(1280);return null}var bytes=emscriptenWebGLComputeImageSize(width,height,sizePerPixel,GL.unpackAlignment);switch(type){case 5120:return HEAP8.subarray(pixels,pixels+bytes);case 5121:return HEAPU8.subarray(pixels,pixels+bytes);case 5122:return HEAP16.subarray(pixels>>1,pixels+bytes>>1);case 5124:return HEAP32.subarray(pixels>>2,pixels+bytes>>2);case 5126:return HEAPF32.subarray(pixels>>2,pixels+bytes>>2);case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return HEAPU32.subarray(pixels>>2,pixels+bytes>>2);case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return HEAPU16.subarray(pixels>>1,pixels+bytes>>1);default:GL.recordError(1280);return null}}function emscriptenWebGLGetHeapForType(type){switch(type){case 5120:return HEAP8;case 5121:return HEAPU8;case 5122:return HEAP16;case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return HEAPU16;case 5124:return HEAP32;case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return HEAPU32;case 5126:return HEAPF32;default:return null}}function emscriptenWebGLGetShiftForType(type){switch(type){case 5120:case 5121:return 0;case 5122:case 5123:case 33635:case 32819:case 32820:case 36193:case 5131:return 1;case 5124:case 5126:case 5125:case 34042:case 35902:case 33640:case 35899:case 34042:return 2;default:return 0}}function _emscripten_glReadPixels(x,y,width,height,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{GLctx.readPixels(x,y,width,height,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _emscripten_glReleaseShaderCompiler(){}function _emscripten_glRenderbufferStorage(x0,x1,x2,x3){GLctx[\"renderbufferStorage\"](x0,x1,x2,x3)}function _emscripten_glRotatef(){Module[\"printErr\"](\"missing function: emscripten_glRotatef\");abort(-1)}function _emscripten_glSampleCoverage(value,invert){GLctx.sampleCoverage(value,!!invert)}function _emscripten_glScissor(x0,x1,x2,x3){GLctx[\"scissor\"](x0,x1,x2,x3)}function _emscripten_glShaderBinary(){GL.recordError(1280)}function _emscripten_glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _emscripten_glStencilFunc(x0,x1,x2){GLctx[\"stencilFunc\"](x0,x1,x2)}function _emscripten_glStencilFuncSeparate(x0,x1,x2,x3){GLctx[\"stencilFuncSeparate\"](x0,x1,x2,x3)}function _emscripten_glStencilMask(x0){GLctx[\"stencilMask\"](x0)}function _emscripten_glStencilMaskSeparate(x0,x1){GLctx[\"stencilMaskSeparate\"](x0,x1)}function _emscripten_glStencilOp(x0,x1,x2){GLctx[\"stencilOp\"](x0,x1,x2)}function _emscripten_glStencilOpSeparate(x0,x1,x2,x3){GLctx[\"stencilOpSeparate\"](x0,x1,x2,x3)}function _emscripten_glTexCoordPointer(){Module[\"printErr\"](\"missing function: emscripten_glTexCoordPointer\");abort(-1)}function _emscripten_glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels!=0){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixelData)}function _emscripten_glTexImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx[\"texImage3D\"](target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels!=0){GLctx[\"texImage3D\"](target,level,internalFormat,width,height,depth,border,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx[\"texImage3D\"](target,level,internalFormat,width,height,depth,border,format,type,null)}}function _emscripten_glTexParameterf(x0,x1,x2){GLctx[\"texParameterf\"](x0,x1,x2)}function _emscripten_glTexParameterfv(target,pname,params){var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)}function _emscripten_glTexParameteri(x0,x1,x2){GLctx[\"texParameteri\"](x0,x1,x2)}function _emscripten_glTexParameteriv(target,pname,params){var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)}function _emscripten_glTexStorage2D(x0,x1,x2,x3,x4){GLctx[\"texStorage2D\"](x0,x1,x2,x3,x4)}function _emscripten_glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx[\"texStorage3D\"](x0,x1,x2,x3,x4,x5)}function _emscripten_glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels!=0){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _emscripten_glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx[\"texSubImage3D\"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels!=0){GLctx[\"texSubImage3D\"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx[\"texSubImage3D\"](target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}}function _emscripten_glUniform1f(location,v0){GLctx.uniform1f(GL.uniforms[location],v0)}function _emscripten_glUniform1fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform1fv(GL.uniforms[location],HEAPF32,value>>2,count);return}var view;if(count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[count-1];for(var i=0;i<count;++i){view[i]=HEAPF32[value+4*i>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(GL.uniforms[location],view)}function _emscripten_glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}function _emscripten_glUniform1iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform1iv(GL.uniforms[location],HEAP32,value>>2,count);return}GLctx.uniform1iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*4>>2))}function _emscripten_glUniform2f(location,v0,v1){GLctx.uniform2f(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2fv(GL.uniforms[location],HEAPF32,value>>2,count*2);return}var view;if(2*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(GL.uniforms[location],view)}function _emscripten_glUniform2i(location,v0,v1){GLctx.uniform2i(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2iv(GL.uniforms[location],HEAP32,value>>2,count*2);return}GLctx.uniform2iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*8>>2))}function _emscripten_glUniform3f(location,v0,v1,v2){GLctx.uniform3f(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform3fv(GL.uniforms[location],HEAPF32,value>>2,count*3);return}var view;if(3*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(GL.uniforms[location],view)}function _emscripten_glUniform3i(location,v0,v1,v2){GLctx.uniform3i(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform3iv(GL.uniforms[location],HEAP32,value>>2,count*3);return}GLctx.uniform3iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*12>>2))}function _emscripten_glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform4fv(GL.uniforms[location],HEAPF32,value>>2,count*4);return}var view;if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(GL.uniforms[location],view)}function _emscripten_glUniform4i(location,v0,v1,v2,v3){GLctx.uniform4i(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform4iv(GL.uniforms[location],HEAP32,value>>2,count*4);return}GLctx.uniform4iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*16>>2))}function _emscripten_glUniformMatrix2fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*4);return}var view;if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix3fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*9);return}var view;if(9*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[9*count-1];for(var i=0;i<9*count;i+=9){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix4fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*16);return}var view;if(16*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[16*count-1];for(var i=0;i<16*count;i+=16){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2];view[i+9]=HEAPF32[value+(4*i+36)>>2];view[i+10]=HEAPF32[value+(4*i+40)>>2];view[i+11]=HEAPF32[value+(4*i+44)>>2];view[i+12]=HEAPF32[value+(4*i+48)>>2];view[i+13]=HEAPF32[value+(4*i+52)>>2];view[i+14]=HEAPF32[value+(4*i+56)>>2];view[i+15]=HEAPF32[value+(4*i+60)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUseProgram(program){GLctx.useProgram(program?GL.programs[program]:null)}function _emscripten_glValidateProgram(program){GLctx.validateProgram(GL.programs[program])}function _emscripten_glVertexAttrib1f(x0,x1){GLctx[\"vertexAttrib1f\"](x0,x1)}function _emscripten_glVertexAttrib1fv(index,v){GLctx.vertexAttrib1f(index,HEAPF32[v>>2])}function _emscripten_glVertexAttrib2f(x0,x1,x2){GLctx[\"vertexAttrib2f\"](x0,x1,x2)}function _emscripten_glVertexAttrib2fv(index,v){GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])}function _emscripten_glVertexAttrib3f(x0,x1,x2,x3){GLctx[\"vertexAttrib3f\"](x0,x1,x2,x3)}function _emscripten_glVertexAttrib3fv(index,v){GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])}function _emscripten_glVertexAttrib4f(x0,x1,x2,x3,x4){GLctx[\"vertexAttrib4f\"](x0,x1,x2,x3,x4)}function _emscripten_glVertexAttrib4fv(index,v){GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])}function _emscripten_glVertexAttribDivisor(index,divisor){GLctx[\"vertexAttribDivisor\"](index,divisor)}function _emscripten_glVertexAttribIPointer(index,size,type,stride,ptr){GLctx.vertexAttribIPointer(index,size,type,stride,ptr)}function _emscripten_glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _emscripten_glVertexPointer(){throw\"Legacy GL function (glVertexPointer) called. If you want legacy GL emulation, you need to compile with -s LEGACY_GL_EMULATION=1 to enable legacy GL emulation.\"}function _emscripten_glViewport(x0,x1,x2,x3){GLctx[\"viewport\"](x0,x1,x2,x3)}function _longjmp(env,value){Module[\"setThrew\"](env,value||1);throw\"longjmp\"}function _emscripten_longjmp(env,value){_longjmp(env,value)}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,lastGamepadState:null,lastGamepadStateFrame:null,numGamepadsConnected:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,staticInit:(function(){if(typeof window!==\"undefined\"){window.addEventListener(\"gamepadconnected\",(function(){++JSEvents.numGamepadsConnected}));window.addEventListener(\"gamepaddisconnected\",(function(){--JSEvents.numGamepadsConnected}));var firstState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads():null;if(firstState){JSEvents.numGamepadsConnected=firstState.length}}}),registerRemoveEventListeners:(function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push((function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}}));JSEvents.removeEventListenersRegistered=true}}),findEventTarget:(function(target){if(target){if(typeof target==\"number\"){target=Pointer_stringify(target)}if(target==\"#window\")return window;else if(target==\"#document\")return document;else if(target==\"#screen\")return window.screen;else if(target==\"#canvas\")return Module[\"canvas\"];if(typeof target==\"string\")return document.getElementById(target);else return target}else{return window}}),deferredCalls:[],deferCall:(function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort((function(x,y){return x.precedence<y.precedence}))}),removeDeferredCalls:(function(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}}),canPerformEventHandlerRequests:(function(){return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls}),runDeferredCalls:(function(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(this,call.argsList)}}),inEventHandler:0,currentEventHandler:null,eventHandlers:[],isInternetExplorer:(function(){return navigator.userAgent.indexOf(\"MSIE\")!==-1||navigator.appVersion.indexOf(\"Trident/\")>0}),removeAllHandlersOnTarget:(function(target,eventTypeString){for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}}),_removeHandler:(function(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)}),registerOrRemoveHandler:(function(eventHandler){var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}}),registerKeyEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.keyEvent){JSEvents.keyEvent=_malloc(164)}var handlerFunc=(function(event){var e=event||window.event;stringToUTF8(e.key?e.key:\"\",JSEvents.keyEvent+0,32);stringToUTF8(e.code?e.code:\"\",JSEvents.keyEvent+32,32);HEAP32[JSEvents.keyEvent+64>>2]=e.location;HEAP32[JSEvents.keyEvent+68>>2]=e.ctrlKey;HEAP32[JSEvents.keyEvent+72>>2]=e.shiftKey;HEAP32[JSEvents.keyEvent+76>>2]=e.altKey;HEAP32[JSEvents.keyEvent+80>>2]=e.metaKey;HEAP32[JSEvents.keyEvent+84>>2]=e.repeat;stringToUTF8(e.locale?e.locale:\"\",JSEvents.keyEvent+88,32);stringToUTF8(e.char?e.char:\"\",JSEvents.keyEvent+120,32);HEAP32[JSEvents.keyEvent+152>>2]=e.charCode;HEAP32[JSEvents.keyEvent+156>>2]=e.keyCode;HEAP32[JSEvents.keyEvent+160>>2]=e.which;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.keyEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:JSEvents.isInternetExplorer()?false:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),getBoundingClientRectOrZeros:(function(target){return target.getBoundingClientRect?target.getBoundingClientRect():{left:0,top:0}}),fillMouseEventData:(function(eventStruct,e,target){HEAPF64[eventStruct>>3]=JSEvents.tick();HEAP32[eventStruct+8>>2]=e.screenX;HEAP32[eventStruct+12>>2]=e.screenY;HEAP32[eventStruct+16>>2]=e.clientX;HEAP32[eventStruct+20>>2]=e.clientY;HEAP32[eventStruct+24>>2]=e.ctrlKey;HEAP32[eventStruct+28>>2]=e.shiftKey;HEAP32[eventStruct+32>>2]=e.altKey;HEAP32[eventStruct+36>>2]=e.metaKey;HEAP16[eventStruct+40>>1]=e.button;HEAP16[eventStruct+42>>1]=e.buttons;HEAP32[eventStruct+44>>2]=e[\"movementX\"]||e[\"mozMovementX\"]||e[\"webkitMovementX\"]||e.screenX-JSEvents.previousScreenX;HEAP32[eventStruct+48>>2]=e[\"movementY\"]||e[\"mozMovementY\"]||e[\"webkitMovementY\"]||e.screenY-JSEvents.previousScreenY;if(Module[\"canvas\"]){var rect=Module[\"canvas\"].getBoundingClientRect();HEAP32[eventStruct+60>>2]=e.clientX-rect.left;HEAP32[eventStruct+64>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+60>>2]=0;HEAP32[eventStruct+64>>2]=0}if(target){var rect=JSEvents.getBoundingClientRectOrZeros(target);HEAP32[eventStruct+52>>2]=e.clientX-rect.left;HEAP32[eventStruct+56>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+52>>2]=0;HEAP32[eventStruct+56>>2]=0}if(e.type!==\"wheel\"&&e.type!==\"mousewheel\"){JSEvents.previousScreenX=e.screenX;JSEvents.previousScreenY=e.screenY}}),registerMouseEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.mouseEvent){JSEvents.mouseEvent=_malloc(72)}target=JSEvents.findEventTarget(target);var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.mouseEvent,e,target);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.mouseEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:eventTypeString!=\"mousemove\"&&eventTypeString!=\"mouseenter\"&&eventTypeString!=\"mouseleave\",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};if(JSEvents.isInternetExplorer()&&eventTypeString==\"mousedown\")eventHandler.allowsDeferredCalls=false;JSEvents.registerOrRemoveHandler(eventHandler)}),registerWheelEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.wheelEvent){JSEvents.wheelEvent=_malloc(104)}target=JSEvents.findEventTarget(target);var wheelHandlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.wheelEvent,e,target);HEAPF64[JSEvents.wheelEvent+72>>3]=e[\"deltaX\"];HEAPF64[JSEvents.wheelEvent+80>>3]=e[\"deltaY\"];HEAPF64[JSEvents.wheelEvent+88>>3]=e[\"deltaZ\"];HEAP32[JSEvents.wheelEvent+96>>2]=e[\"deltaMode\"];var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.wheelEvent,userData);if(shouldCancel){e.preventDefault()}});var mouseWheelHandlerFunc=(function(event){var e=event||window.event;JSEvents.fillMouseEventData(JSEvents.wheelEvent,e,target);HEAPF64[JSEvents.wheelEvent+72>>3]=e[\"wheelDeltaX\"]||0;HEAPF64[JSEvents.wheelEvent+80>>3]=-(e[\"wheelDeltaY\"]?e[\"wheelDeltaY\"]:e[\"wheelDelta\"]);HEAPF64[JSEvents.wheelEvent+88>>3]=0;HEAP32[JSEvents.wheelEvent+96>>2]=0;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.wheelEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:eventTypeString==\"wheel\"?wheelHandlerFunc:mouseWheelHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),pageScrollPos:(function(){if(window.pageXOffset>0||window.pageYOffset>0){return[window.pageXOffset,window.pageYOffset]}if(typeof document.documentElement.scrollLeft!==\"undefined\"||typeof document.documentElement.scrollTop!==\"undefined\"){return[document.documentElement.scrollLeft,document.documentElement.scrollTop]}return[document.body.scrollLeft|0,document.body.scrollTop|0]}),registerUiEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.uiEvent){JSEvents.uiEvent=_malloc(36)}if(eventTypeString==\"scroll\"&&!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;if(e.target!=target){return}var scrollPos=JSEvents.pageScrollPos();HEAP32[JSEvents.uiEvent>>2]=e.detail;HEAP32[JSEvents.uiEvent+4>>2]=document.body.clientWidth;HEAP32[JSEvents.uiEvent+8>>2]=document.body.clientHeight;HEAP32[JSEvents.uiEvent+12>>2]=window.innerWidth;HEAP32[JSEvents.uiEvent+16>>2]=window.innerHeight;HEAP32[JSEvents.uiEvent+20>>2]=window.outerWidth;HEAP32[JSEvents.uiEvent+24>>2]=window.outerHeight;HEAP32[JSEvents.uiEvent+28>>2]=scrollPos[0];HEAP32[JSEvents.uiEvent+32>>2]=scrollPos[1];var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.uiEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),getNodeNameForTarget:(function(target){if(!target)return\"\";if(target==window)return\"#window\";if(target==window.screen)return\"#screen\";return target&&target.nodeName?target.nodeName:\"\"}),registerFocusEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.focusEvent){JSEvents.focusEvent=_malloc(256)}var handlerFunc=(function(event){var e=event||window.event;var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:\"\";stringToUTF8(nodeName,JSEvents.focusEvent+0,128);stringToUTF8(id,JSEvents.focusEvent+128,128);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.focusEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),tick:(function(){if(window[\"performance\"]&&window[\"performance\"][\"now\"])return window[\"performance\"][\"now\"]();else return Date.now()}),registerDeviceOrientationEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.deviceOrientationEvent){JSEvents.deviceOrientationEvent=_malloc(40)}var handlerFunc=(function(event){var e=event||window.event;HEAPF64[JSEvents.deviceOrientationEvent>>3]=JSEvents.tick();HEAPF64[JSEvents.deviceOrientationEvent+8>>3]=e.alpha;HEAPF64[JSEvents.deviceOrientationEvent+16>>3]=e.beta;HEAPF64[JSEvents.deviceOrientationEvent+24>>3]=e.gamma;HEAP32[JSEvents.deviceOrientationEvent+32>>2]=e.absolute;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.deviceOrientationEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerDeviceMotionEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.deviceMotionEvent){JSEvents.deviceMotionEvent=_malloc(80)}var handlerFunc=(function(event){var e=event||window.event;HEAPF64[JSEvents.deviceMotionEvent>>3]=JSEvents.tick();HEAPF64[JSEvents.deviceMotionEvent+8>>3]=e.acceleration.x;HEAPF64[JSEvents.deviceMotionEvent+16>>3]=e.acceleration.y;HEAPF64[JSEvents.deviceMotionEvent+24>>3]=e.acceleration.z;HEAPF64[JSEvents.deviceMotionEvent+32>>3]=e.accelerationIncludingGravity.x;HEAPF64[JSEvents.deviceMotionEvent+40>>3]=e.accelerationIncludingGravity.y;HEAPF64[JSEvents.deviceMotionEvent+48>>3]=e.accelerationIncludingGravity.z;HEAPF64[JSEvents.deviceMotionEvent+56>>3]=e.rotationRate.alpha;HEAPF64[JSEvents.deviceMotionEvent+64>>3]=e.rotationRate.beta;HEAPF64[JSEvents.deviceMotionEvent+72>>3]=e.rotationRate.gamma;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.deviceMotionEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),screenOrientation:(function(){if(!window.screen)return undefined;return window.screen.orientation||window.screen.mozOrientation||window.screen.webkitOrientation||window.screen.msOrientation}),fillOrientationChangeEventData:(function(eventStruct,e){var orientations=[\"portrait-primary\",\"portrait-secondary\",\"landscape-primary\",\"landscape-secondary\"];var orientations2=[\"portrait\",\"portrait\",\"landscape\",\"landscape\"];var orientationString=JSEvents.screenOrientation();var orientation=orientations.indexOf(orientationString);if(orientation==-1){orientation=orientations2.indexOf(orientationString)}HEAP32[eventStruct>>2]=1<<orientation;HEAP32[eventStruct+4>>2]=window.orientation}),registerOrientationChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.orientationChangeEvent){JSEvents.orientationChangeEvent=_malloc(8)}if(!target){target=window.screen}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillOrientationChangeEventData(JSEvents.orientationChangeEvent,e);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.orientationChangeEvent,userData);if(shouldCancel){e.preventDefault()}});if(eventTypeString==\"orientationchange\"&&window.screen.mozOrientation!==undefined){eventTypeString=\"mozorientationchange\"}var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),fullscreenEnabled:(function(){return document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled}),fillFullscreenChangeEventData:(function(eventStruct,e){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;var isFullscreen=!!fullscreenElement;HEAP32[eventStruct>>2]=isFullscreen;HEAP32[eventStruct+4>>2]=JSEvents.fullscreenEnabled();var reportedElement=isFullscreen?fullscreenElement:JSEvents.previousFullscreenElement;var nodeName=JSEvents.getNodeNameForTarget(reportedElement);var id=reportedElement&&reportedElement.id?reportedElement.id:\"\";stringToUTF8(nodeName,eventStruct+8,128);stringToUTF8(id,eventStruct+136,128);HEAP32[eventStruct+264>>2]=reportedElement?reportedElement.clientWidth:0;HEAP32[eventStruct+268>>2]=reportedElement?reportedElement.clientHeight:0;HEAP32[eventStruct+272>>2]=screen.width;HEAP32[eventStruct+276>>2]=screen.height;if(isFullscreen){JSEvents.previousFullscreenElement=fullscreenElement}}),registerFullscreenChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.fullscreenChangeEvent){JSEvents.fullscreenChangeEvent=_malloc(280)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillFullscreenChangeEventData(JSEvents.fullscreenChangeEvent,e);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.fullscreenChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),resizeCanvasForFullscreen:(function(target,strategy){var restoreOldStyle=__registerRestoreOldStyle(target);var cssWidth=strategy.softFullscreen?window.innerWidth:screen.width;var cssHeight=strategy.softFullscreen?window.innerHeight:screen.height;var rect=target.getBoundingClientRect();var windowedCssWidth=rect.right-rect.left;var windowedCssHeight=rect.bottom-rect.top;var windowedRttWidth=target.width;var windowedRttHeight=target.height;if(strategy.scaleMode==3){__setLetterbox(target,(cssHeight-windowedCssHeight)/2,(cssWidth-windowedCssWidth)/2);cssWidth=windowedCssWidth;cssHeight=windowedCssHeight}else if(strategy.scaleMode==2){if(cssWidth*windowedRttHeight<windowedRttWidth*cssHeight){var desiredCssHeight=windowedRttHeight*cssWidth/windowedRttWidth;__setLetterbox(target,(cssHeight-desiredCssHeight)/2,0);cssHeight=desiredCssHeight}else{var desiredCssWidth=windowedRttWidth*cssHeight/windowedRttHeight;__setLetterbox(target,0,(cssWidth-desiredCssWidth)/2);cssWidth=desiredCssWidth}}if(!target.style.backgroundColor)target.style.backgroundColor=\"black\";if(!document.body.style.backgroundColor)document.body.style.backgroundColor=\"black\";target.style.width=cssWidth+\"px\";target.style.height=cssHeight+\"px\";if(strategy.filteringMode==1){target.style.imageRendering=\"optimizeSpeed\";target.style.imageRendering=\"-moz-crisp-edges\";target.style.imageRendering=\"-o-crisp-edges\";target.style.imageRendering=\"-webkit-optimize-contrast\";target.style.imageRendering=\"optimize-contrast\";target.style.imageRendering=\"crisp-edges\";target.style.imageRendering=\"pixelated\"}var dpiScale=strategy.canvasResolutionScaleMode==2?window.devicePixelRatio:1;if(strategy.canvasResolutionScaleMode!=0){target.width=cssWidth*dpiScale;target.height=cssHeight*dpiScale;if(target.GLctxObject)target.GLctxObject.GLctx.viewport(0,0,target.width,target.height)}return restoreOldStyle}),requestFullscreen:(function(target,strategy){if(strategy.scaleMode!=0||strategy.canvasResolutionScaleMode!=0){JSEvents.resizeCanvasForFullscreen(target,strategy)}if(target.requestFullscreen){target.requestFullscreen()}else if(target.msRequestFullscreen){target.msRequestFullscreen()}else if(target.mozRequestFullScreen){target.mozRequestFullScreen()}else if(target.mozRequestFullscreen){target.mozRequestFullscreen()}else if(target.webkitRequestFullscreen){target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}else{if(typeof JSEvents.fullscreenEnabled()===\"undefined\"){return-1}else{return-3}}if(strategy.canvasResizedCallback){Module[\"dynCall_iiii\"](strategy.canvasResizedCallback,37,0,strategy.canvasResizedCallbackUserData)}return 0}),fillPointerlockChangeEventData:(function(eventStruct,e){var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement&&pointerLockElement.id?pointerLockElement.id:\"\";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)}),registerPointerlockChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.pointerlockChangeEvent){JSEvents.pointerlockChangeEvent=_malloc(260)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillPointerlockChangeEventData(JSEvents.pointerlockChangeEvent,e);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.pointerlockChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerPointerlockErrorEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,0,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),requestPointerLock:(function(target){if(target.requestPointerLock){target.requestPointerLock()}else if(target.mozRequestPointerLock){target.mozRequestPointerLock()}else if(target.webkitRequestPointerLock){target.webkitRequestPointerLock()}else if(target.msRequestPointerLock){target.msRequestPointerLock()}else{if(document.body.requestPointerLock||document.body.mozRequestPointerLock||document.body.webkitRequestPointerLock||document.body.msRequestPointerLock){return-3}else{return-1}}return 0}),fillVisibilityChangeEventData:(function(eventStruct,e){var visibilityStates=[\"hidden\",\"visible\",\"prerender\",\"unloaded\"];var visibilityState=visibilityStates.indexOf(document.visibilityState);HEAP32[eventStruct>>2]=document.hidden;HEAP32[eventStruct+4>>2]=visibilityState}),registerVisibilityChangeEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.visibilityChangeEvent){JSEvents.visibilityChangeEvent=_malloc(8)}if(!target){target=document}else{target=JSEvents.findEventTarget(target)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillVisibilityChangeEventData(JSEvents.visibilityChangeEvent,e);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.visibilityChangeEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerTouchEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.touchEvent){JSEvents.touchEvent=_malloc(1684)}target=JSEvents.findEventTarget(target);var handlerFunc=(function(event){var e=event||window.event;var touches={};for(var i=0;i<e.touches.length;++i){var touch=e.touches[i];touches[touch.identifier]=touch}for(var i=0;i<e.changedTouches.length;++i){var touch=e.changedTouches[i];touches[touch.identifier]=touch;touch.changed=true}for(var i=0;i<e.targetTouches.length;++i){var touch=e.targetTouches[i];touches[touch.identifier].onTarget=true}var ptr=JSEvents.touchEvent;HEAP32[ptr+4>>2]=e.ctrlKey;HEAP32[ptr+8>>2]=e.shiftKey;HEAP32[ptr+12>>2]=e.altKey;HEAP32[ptr+16>>2]=e.metaKey;ptr+=20;var canvasRect=Module[\"canvas\"]?Module[\"canvas\"].getBoundingClientRect():undefined;var targetRect=JSEvents.getBoundingClientRectOrZeros(target);var numTouches=0;for(var i in touches){var t=touches[i];HEAP32[ptr>>2]=t.identifier;HEAP32[ptr+4>>2]=t.screenX;HEAP32[ptr+8>>2]=t.screenY;HEAP32[ptr+12>>2]=t.clientX;HEAP32[ptr+16>>2]=t.clientY;HEAP32[ptr+20>>2]=t.pageX;HEAP32[ptr+24>>2]=t.pageY;HEAP32[ptr+28>>2]=t.changed;HEAP32[ptr+32>>2]=t.onTarget;if(canvasRect){HEAP32[ptr+44>>2]=t.clientX-canvasRect.left;HEAP32[ptr+48>>2]=t.clientY-canvasRect.top}else{HEAP32[ptr+44>>2]=0;HEAP32[ptr+48>>2]=0}HEAP32[ptr+36>>2]=t.clientX-targetRect.left;HEAP32[ptr+40>>2]=t.clientY-targetRect.top;ptr+=52;if(++numTouches>=32){break}}HEAP32[JSEvents.touchEvent>>2]=numTouches;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.touchEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:target,allowsDeferredCalls:eventTypeString==\"touchstart\"||eventTypeString==\"touchend\",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),fillGamepadEventData:(function(eventStruct,e){HEAPF64[eventStruct>>3]=e.timestamp;for(var i=0;i<e.axes.length;++i){HEAPF64[eventStruct+i*8+16>>3]=e.axes[i]}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]===\"object\"){HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i].value}else{HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i]}}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]===\"object\"){HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i].pressed}else{HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i]==1}}HEAP32[eventStruct+1296>>2]=e.connected;HEAP32[eventStruct+1300>>2]=e.index;HEAP32[eventStruct+8>>2]=e.axes.length;HEAP32[eventStruct+12>>2]=e.buttons.length;stringToUTF8(e.id,eventStruct+1304,64);stringToUTF8(e.mapping,eventStruct+1368,64)}),registerGamepadEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.gamepadEvent){JSEvents.gamepadEvent=_malloc(1432)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillGamepadEventData(JSEvents.gamepadEvent,e.gamepad);var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.gamepadEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerBeforeUnloadEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){var handlerFunc=(function(event){var e=event||window.event;var confirmationMessage=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,0,userData);if(confirmationMessage){confirmationMessage=Pointer_stringify(confirmationMessage)}if(confirmationMessage){e.preventDefault();e.returnValue=confirmationMessage;return confirmationMessage}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),battery:(function(){return navigator.battery||navigator.mozBattery||navigator.webkitBattery}),fillBatteryEventData:(function(eventStruct,e){HEAPF64[eventStruct>>3]=e.chargingTime;HEAPF64[eventStruct+8>>3]=e.dischargingTime;HEAPF64[eventStruct+16>>3]=e.level;HEAP32[eventStruct+24>>2]=e.charging}),registerBatteryEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!JSEvents.batteryEvent){JSEvents.batteryEvent=_malloc(32)}var handlerFunc=(function(event){var e=event||window.event;JSEvents.fillBatteryEventData(JSEvents.batteryEvent,JSEvents.battery());var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,JSEvents.batteryEvent,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}),registerWebGlEventCallback:(function(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){if(!target){target=Module[\"canvas\"]}var handlerFunc=(function(event){var e=event||window.event;var shouldCancel=Module[\"dynCall_iiii\"](callbackfunc,eventTypeId,0,userData);if(shouldCancel){e.preventDefault()}});var eventHandler={target:JSEvents.findEventTarget(target),allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:handlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)})};function _emscripten_webgl_create_context(target,attributes){var contextAttributes={};contextAttributes[\"alpha\"]=!!HEAP32[attributes>>2];contextAttributes[\"depth\"]=!!HEAP32[attributes+4>>2];contextAttributes[\"stencil\"]=!!HEAP32[attributes+8>>2];contextAttributes[\"antialias\"]=!!HEAP32[attributes+12>>2];contextAttributes[\"premultipliedAlpha\"]=!!HEAP32[attributes+16>>2];contextAttributes[\"preserveDrawingBuffer\"]=!!HEAP32[attributes+20>>2];contextAttributes[\"preferLowPowerToHighPerformance\"]=!!HEAP32[attributes+24>>2];contextAttributes[\"failIfMajorPerformanceCaveat\"]=!!HEAP32[attributes+28>>2];contextAttributes[\"majorVersion\"]=HEAP32[attributes+32>>2];contextAttributes[\"minorVersion\"]=HEAP32[attributes+36>>2];contextAttributes[\"explicitSwapControl\"]=HEAP32[attributes+44>>2];target=Pointer_stringify(target);var canvas;if((!target||target===\"#canvas\")&&Module[\"canvas\"]){canvas=Module[\"canvas\"].id?GL.offscreenCanvases[Module[\"canvas\"].id]||JSEvents.findEventTarget(Module[\"canvas\"].id):Module[\"canvas\"]}else{canvas=GL.offscreenCanvases[target]||JSEvents.findEventTarget(target)}if(!canvas){return 0}if(contextAttributes[\"explicitSwapControl\"]){console.error(\"emscripten_webgl_create_context failed: explicitSwapControl is not supported, please rebuild with -s OFFSCREENCANVAS_SUPPORT=1 to enable targeting the experimental OffscreenCanvas specification!\");return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_init_context_attributes(attributes){HEAP32[attributes>>2]=1;HEAP32[attributes+4>>2]=1;HEAP32[attributes+8>>2]=0;HEAP32[attributes+12>>2]=1;HEAP32[attributes+16>>2]=1;HEAP32[attributes+20>>2]=0;HEAP32[attributes+24>>2]=0;HEAP32[attributes+28>>2]=0;HEAP32[attributes+32>>2]=1;HEAP32[attributes+36>>2]=0;HEAP32[attributes+40>>2]=1;HEAP32[attributes+44>>2]=0}function _emscripten_webgl_make_context_current(contextHandle){var success=GL.makeContextCurrent(contextHandle);return success?0:-5}function _getenv(name){if(name===0)return 0;name=Pointer_stringify(name);if(!ENV.hasOwnProperty(name))return 0;if(_getenv.ret)_free(_getenv.ret);_getenv.ret=allocateUTF8(ENV[name]);return _getenv.ret}function _glActiveTexture(x0){GLctx[\"activeTexture\"](x0)}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindAttribLocation(program,index,name){name=Pointer_stringify(name);GLctx.bindAttribLocation(GL.programs[program],index,name)}function _glBindBuffer(target,buffer){var bufferObj=buffer?GL.buffers[buffer]:null;if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,bufferObj)}function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,framebuffer?GL.framebuffers[framebuffer]:null)}function _glBindRenderbuffer(target,renderbuffer){GLctx.bindRenderbuffer(target,renderbuffer?GL.renderbuffers[renderbuffer]:null)}function _glBindTexture(target,texture){GLctx.bindTexture(target,texture?GL.textures[texture]:null)}function _glBlendColor(x0,x1,x2,x3){GLctx[\"blendColor\"](x0,x1,x2,x3)}function _glBlendEquation(x0){GLctx[\"blendEquation\"](x0)}function _glBlendFunc(x0,x1){GLctx[\"blendFunc\"](x0,x1)}function _glBufferData(target,size,data,usage){if(!data){GLctx.bufferData(target,size,usage)}else{if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferData(target,HEAPU8,usage,data,size);return}GLctx.bufferData(target,HEAPU8.subarray(data,data+size),usage)}}function _glBufferSubData(target,offset,size,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _glCheckFramebufferStatus(x0){return GLctx[\"checkFramebufferStatus\"](x0)}function _glClear(x0){GLctx[\"clear\"](x0)}function _glClearColor(x0,x1,x2,x3){GLctx[\"clearColor\"](x0,x1,x2,x3)}function _glClearStencil(x0){GLctx[\"clearStencil\"](x0)}function _glColorMask(red,green,blue,alpha){GLctx.colorMask(!!red,!!green,!!blue,!!alpha)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx[\"compressedTexImage2D\"](target,level,internalFormat,width,height,border,HEAPU8,data,imageSize);return}GLctx[\"compressedTexImage2D\"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _glCompressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx[\"compressedTexSubImage2D\"](target,level,xoffset,yoffset,width,height,format,HEAPU8,data,imageSize);return}GLctx[\"compressedTexSubImage2D\"](target,level,xoffset,yoffset,width,height,format,data?HEAPU8.subarray(data,data+imageSize):null)}function _glCopyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx[\"copyTexSubImage2D\"](x0,x1,x2,x3,x4,x5,x6,x7)}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glCullFace(x0){GLctx[\"cullFace\"](x0)}function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GL.currArrayBuffer)GL.currArrayBuffer=0;if(id==GL.currElementArrayBuffer)GL.currElementArrayBuffer=0}}function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _glDeleteRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDepthMask(flag){GLctx.depthMask(!!flag)}function _glDisable(x0){GLctx[\"disable\"](x0)}function _glDisableVertexAttribArray(index){GLctx.disableVertexAttribArray(index)}function _glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _glDrawElements(mode,count,type,indices){GLctx.drawElements(mode,count,type,indices)}function _glEnable(x0){GLctx[\"enable\"](x0)}function _glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function _glFinish(){GLctx[\"finish\"]()}function _glFlush(){GLctx[\"flush\"]()}function _glFramebufferRenderbuffer(target,attachment,renderbuffertarget,renderbuffer){GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])}function _glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _glFrontFace(x0){GLctx[\"frontFace\"](x0)}function _glGenBuffers(n,buffers){for(var i=0;i<n;i++){var buffer=GLctx.createBuffer();if(!buffer){GL.recordError(1282);while(i<n)HEAP32[buffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.buffers);buffer.name=id;GL.buffers[id]=buffer;HEAP32[buffers+i*4>>2]=id}}function _glGenFramebuffers(n,ids){for(var i=0;i<n;++i){var framebuffer=GLctx.createFramebuffer();if(!framebuffer){GL.recordError(1282);while(i<n)HEAP32[ids+i++*4>>2]=0;return}var id=GL.getNewId(GL.framebuffers);framebuffer.name=id;GL.framebuffers[id]=framebuffer;HEAP32[ids+i*4>>2]=id}}function _glGenRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var renderbuffer=GLctx.createRenderbuffer();if(!renderbuffer){GL.recordError(1282);while(i<n)HEAP32[renderbuffers+i++*4>>2]=0;return}var id=GL.getNewId(GL.renderbuffers);renderbuffer.name=id;GL.renderbuffers[id]=renderbuffer;HEAP32[renderbuffers+i*4>>2]=id}}function _glGenTextures(n,textures){for(var i=0;i<n;i++){var texture=GLctx.createTexture();if(!texture){GL.recordError(1282);while(i<n)HEAP32[textures+i++*4>>2]=0;return}var id=GL.getNewId(GL.textures);texture.name=id;GL.textures[id]=texture;HEAP32[textures+i*4>>2]=id}}function _glGenerateMipmap(x0){GLctx[\"generateMipmap\"](x0)}function _glGetBufferParameteriv(target,value,data){if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)}function _glGetError(){if(GL.lastError){var error=GL.lastError;GL.lastError=0;return error}else{return GLctx.getError()}}function _glGetFramebufferAttachmentParameteriv(target,attachment,pname,params){var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result}function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,\"Integer\")}function _glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log=\"(unknown error)\";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,GLctx.ACTIVE_ATTRIBUTES);ptable.maxAttributeLength=0;for(var i=0;i<numAttribs;++i){var activeAttrib=GLctx.getActiveAttrib(program,i);ptable.maxAttributeLength=Math.max(ptable.maxAttributeLength,activeAttrib.name.length+1)}}HEAP32[p>>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,GLctx.ACTIVE_UNIFORM_BLOCKS);ptable.maxUniformBlockNameLength=0;for(var i=0;i<numBlocks;++i){var activeBlockName=GLctx.getActiveUniformBlockName(program,i);ptable.maxUniformBlockNameLength=Math.max(ptable.maxUniformBlockNameLength,activeBlockName.length+1)}}HEAP32[p>>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _glGetRenderbufferParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)}function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";if(maxLength>0&&infoLog){var numBytesWrittenExclNull=stringToUTF8(log,infoLog,maxLength);if(length)HEAP32[length>>2]=numBytesWrittenExclNull}else{if(length)HEAP32[length>>2]=0}}function _glGetShaderPrecisionFormat(shaderType,precisionType,range,precision){var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision}function _glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source===null||source.length==0?0:source.length+1;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7936:case 7937:case 37445:case 37446:ret=allocate(intArrayFromString(GLctx.getParameter(name_)),\"i8\",ALLOC_NORMAL);break;case 7938:var glVersion=GLctx.getParameter(GLctx.VERSION);if(GLctx.canvas.GLctxObject.version>=2)glVersion=\"OpenGL ES 3.0 (\"+glVersion+\")\";else{glVersion=\"OpenGL ES 2.0 (\"+glVersion+\")\"}ret=allocate(intArrayFromString(glVersion),\"i8\",ALLOC_NORMAL);break;case 7939:var exts=GLctx.getSupportedExtensions();var gl_exts=[];for(var i=0;i<exts.length;++i){gl_exts.push(exts[i]);gl_exts.push(\"GL_\"+exts[i])}ret=allocate(intArrayFromString(gl_exts.join(\" \")),\"i8\",ALLOC_NORMAL);break;case 35724:var glslVersion=GLctx.getParameter(GLctx.SHADING_LANGUAGE_VERSION);var ver_re=/^WebGL GLSL ES ([0-9]\\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+\"0\";glslVersion=\"OpenGL ES GLSL ES \"+ver_num[1]+\" (\"+glslVersion+\")\"}ret=allocate(intArrayFromString(glslVersion),\"i8\",ALLOC_NORMAL);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _glGetUniformLocation(program,name){name=Pointer_stringify(name);var arrayOffset=0;if(name.indexOf(\"]\",name.length-1)!==-1){var ls=name.lastIndexOf(\"[\");var arrayIndex=name.slice(ls+1,-1);if(arrayIndex.length>0){arrayOffset=parseInt(arrayIndex);if(arrayOffset<0){return-1}}name=name.slice(0,ls)}var ptable=GL.programInfos[program];if(!ptable){return-1}var utable=ptable.uniforms;var uniformInfo=utable[name];if(uniformInfo&&arrayOffset<uniformInfo[0]){return uniformInfo[1]+arrayOffset}else{return-1}}function _glIsTexture(texture){var texture=GL.textures[texture];if(!texture)return 0;return GLctx.isTexture(texture)}function _glLineWidth(x0){GLctx[\"lineWidth\"](x0)}function _glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.programInfos[program]=null;GL.populateUniformTable(program)}function _glPixelStorei(pname,param){if(pname==3333){GL.packAlignment=param}else if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{GLctx.readPixels(x,y,width,height,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glRenderbufferStorage(x0,x1,x2,x3){GLctx[\"renderbufferStorage\"](x0,x1,x2,x3)}function _glScissor(x0,x1,x2,x3){GLctx[\"scissor\"](x0,x1,x2,x3)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glStencilFunc(x0,x1,x2){GLctx[\"stencilFunc\"](x0,x1,x2)}function _glStencilFuncSeparate(x0,x1,x2,x3){GLctx[\"stencilFuncSeparate\"](x0,x1,x2,x3)}function _glStencilMask(x0){GLctx[\"stencilMask\"](x0)}function _glStencilMaskSeparate(x0,x1){GLctx[\"stencilMaskSeparate\"](x0,x1)}function _glStencilOp(x0,x1,x2){GLctx[\"stencilOp\"](x0,x1,x2)}function _glStencilOpSeparate(x0,x1,x2,x3){GLctx[\"stencilOpSeparate\"](x0,x1,x2,x3)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels!=0){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixelData)}function _glTexParameteri(x0,x1,x2){GLctx[\"texParameteri\"](x0,x1,x2)}function _glTexParameteriv(target,pname,params){var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)}function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){if(GL.currentContext.supportsWebGL2EntryPoints){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels!=0){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,emscriptenWebGLGetHeapForType(type),pixels>>emscriptenWebGLGetShiftForType(type))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _glUniform1f(location,v0){GLctx.uniform1f(GL.uniforms[location],v0)}function _glUniform1fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform1fv(GL.uniforms[location],HEAPF32,value>>2,count);return}var view;if(count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[count-1];for(var i=0;i<count;++i){view[i]=HEAPF32[value+4*i>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(GL.uniforms[location],view)}function _glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}function _glUniform1iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform1iv(GL.uniforms[location],HEAP32,value>>2,count);return}GLctx.uniform1iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*4>>2))}function _glUniform2f(location,v0,v1){GLctx.uniform2f(GL.uniforms[location],v0,v1)}function _glUniform2fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2fv(GL.uniforms[location],HEAPF32,value>>2,count*2);return}var view;if(2*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(GL.uniforms[location],view)}function _glUniform2i(location,v0,v1){GLctx.uniform2i(GL.uniforms[location],v0,v1)}function _glUniform2iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform2iv(GL.uniforms[location],HEAP32,value>>2,count*2);return}GLctx.uniform2iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*8>>2))}function _glUniform3f(location,v0,v1,v2){GLctx.uniform3f(GL.uniforms[location],v0,v1,v2)}function _glUniform3fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform3fv(GL.uniforms[location],HEAPF32,value>>2,count*3);return}var view;if(3*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(GL.uniforms[location],view)}function _glUniform3i(location,v0,v1,v2){GLctx.uniform3i(GL.uniforms[location],v0,v1,v2)}function _glUniform3iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform3iv(GL.uniforms[location],HEAP32,value>>2,count*3);return}GLctx.uniform3iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*12>>2))}function _glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _glUniform4fv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform4fv(GL.uniforms[location],HEAPF32,value>>2,count*4);return}var view;if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(GL.uniforms[location],view)}function _glUniform4i(location,v0,v1,v2,v3){GLctx.uniform4i(GL.uniforms[location],v0,v1,v2,v3)}function _glUniform4iv(location,count,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniform4iv(GL.uniforms[location],HEAP32,value>>2,count*4);return}GLctx.uniform4iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*16>>2))}function _glUniformMatrix2fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*4);return}var view;if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,view)}function _glUniformMatrix3fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*9);return}var view;if(9*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[9*count-1];for(var i=0;i<9*count;i+=9){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,view)}function _glUniformMatrix4fv(location,count,transpose,value){if(GL.currentContext.supportsWebGL2EntryPoints){GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,HEAPF32,value>>2,count*16);return}var view;if(16*count<=GL.MINI_TEMP_BUFFER_SIZE){view=GL.miniTempBufferViews[16*count-1];for(var i=0;i<16*count;i+=16){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2];view[i+9]=HEAPF32[value+(4*i+36)>>2];view[i+10]=HEAPF32[value+(4*i+40)>>2];view[i+11]=HEAPF32[value+(4*i+44)>>2];view[i+12]=HEAPF32[value+(4*i+48)>>2];view[i+13]=HEAPF32[value+(4*i+52)>>2];view[i+14]=HEAPF32[value+(4*i+56)>>2];view[i+15]=HEAPF32[value+(4*i+60)>>2]}}else{view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _glUseProgram(program){GLctx.useProgram(program?GL.programs[program]:null)}function _glVertexAttrib1f(x0,x1){GLctx[\"vertexAttrib1f\"](x0,x1)}function _glVertexAttrib2fv(index,v){GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])}function _glVertexAttrib3fv(index,v){GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])}function _glVertexAttrib4fv(index,v){GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx[\"viewport\"](x0,x1,x2,x3)}function _llvm_exp2_f32(x){return Math.pow(2,x)}function _llvm_log2_f32(x){return Math.log(x)/Math.LN2}function _llvm_stackrestore(p){var self=_llvm_stacksave;var ret=self.LLVM_SAVEDSTACKS[p];self.LLVM_SAVEDSTACKS.splice(p,1);stackRestore(ret)}function _llvm_stacksave(){var self=_llvm_stacksave;if(!self.LLVM_SAVEDSTACKS){self.LLVM_SAVEDSTACKS=[]}self.LLVM_SAVEDSTACKS.push(stackSave());return self.LLVM_SAVEDSTACKS.length-1}function _llvm_trap(){abort(\"trap!\")}var _llvm_trunc_f32=Math_trunc;function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest);return dest}function _pthread_cond_wait(){return 0}var PTHREAD_SPECIFIC={};function _pthread_getspecific(key){return PTHREAD_SPECIFIC[key]||0}var PTHREAD_SPECIFIC_NEXT_KEY=1;function _pthread_key_create(key,destructor){if(key==0){return ERRNO_CODES.EINVAL}HEAP32[key>>2]=PTHREAD_SPECIFIC_NEXT_KEY;PTHREAD_SPECIFIC[PTHREAD_SPECIFIC_NEXT_KEY]=0;PTHREAD_SPECIFIC_NEXT_KEY++;return 0}function _pthread_once(ptr,func){if(!_pthread_once.seen)_pthread_once.seen={};if(ptr in _pthread_once.seen)return;Module[\"dynCall_v\"](func);_pthread_once.seen[ptr]=1}function _pthread_setspecific(key,value){if(!(key in PTHREAD_SPECIFIC)){return ERRNO_CODES.EINVAL}PTHREAD_SPECIFIC[key]=value;return 0}function _sem_destroy(){}function _sem_init(){}function _sem_post(){}function _sem_wait(){}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]);return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?Pointer_stringify(tm_zone):\"\"};var pattern=Pointer_stringify(format);var EXPANSION_RULES_1={\"%c\":\"%a %b %d %H:%M:%S %Y\",\"%D\":\"%m/%d/%y\",\"%F\":\"%Y-%m-%d\",\"%h\":\"%b\",\"%r\":\"%I:%M:%S %p\",\"%R\":\"%H:%M\",\"%T\":\"%H:%M:%S\",\"%x\":\"%m/%d/%y\",\"%X\":\"%H:%M:%S\"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_1[rule])}var WEEKDAYS=[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"];var MONTHS=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];function leadingSomething(value,digits,character){var str=typeof value===\"number\"?value.toString():value||\"\";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,\"0\")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={\"%a\":(function(date){return WEEKDAYS[date.tm_wday].substring(0,3)}),\"%A\":(function(date){return WEEKDAYS[date.tm_wday]}),\"%b\":(function(date){return MONTHS[date.tm_mon].substring(0,3)}),\"%B\":(function(date){return MONTHS[date.tm_mon]}),\"%C\":(function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)}),\"%d\":(function(date){return leadingNulls(date.tm_mday,2)}),\"%e\":(function(date){return leadingSomething(date.tm_mday,2,\" \")}),\"%g\":(function(date){return getWeekBasedYear(date).toString().substring(2)}),\"%G\":(function(date){return getWeekBasedYear(date)}),\"%H\":(function(date){return leadingNulls(date.tm_hour,2)}),\"%I\":(function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)}),\"%j\":(function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)}),\"%m\":(function(date){return leadingNulls(date.tm_mon+1,2)}),\"%M\":(function(date){return leadingNulls(date.tm_min,2)}),\"%n\":(function(){return\"\\n\"}),\"%p\":(function(date){if(date.tm_hour>=0&&date.tm_hour<12){return\"AM\"}else{return\"PM\"}}),\"%S\":(function(date){return leadingNulls(date.tm_sec,2)}),\"%t\":(function(){return\"\\t\"}),\"%u\":(function(date){var day=new Date(date.tm_year+1900,date.tm_mon+1,date.tm_mday,0,0,0,0);return day.getDay()||7}),\"%U\":(function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?\"01\":\"00\"}),\"%V\":(function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return\"53\"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return\"01\"}var daysDifference;if(firstWeekStartThisYear.getFullYear()<date.tm_year+1900){daysDifference=date.tm_yday+32-firstWeekStartThisYear.getDate()}else{daysDifference=date.tm_yday+1-firstWeekStartThisYear.getDate()}return leadingNulls(Math.ceil(daysDifference/7),2)}),\"%w\":(function(date){var day=new Date(date.tm_year+1900,date.tm_mon+1,date.tm_mday,0,0,0,0);return day.getDay()}),\"%W\":(function(date){var janFirst=new Date(date.tm_year,0,1);var firstMonday=janFirst.getDay()===1?janFirst:__addDays(janFirst,janFirst.getDay()===0?1:7-janFirst.getDay()+1);var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstMonday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstMondayUntilEndJanuary=31-firstMonday.getDate();var days=firstMondayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstMonday,janFirst)===0?\"01\":\"00\"}),\"%y\":(function(date){return(date.tm_year+1900).toString().substring(2)}),\"%Y\":(function(date){return date.tm_year+1900}),\"%z\":(function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?\"+\":\"-\")+String(\"0000\"+off).slice(-4)}),\"%Z\":(function(date){return date.tm_zone}),\"%%\":(function(){return\"%\"})};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,format,tm)}FS.staticInit();__ATINIT__.unshift((function(){if(!Module[\"noFSInit\"]&&!FS.init.initialized)FS.init()}));__ATMAIN__.push((function(){FS.ignorePermissions=false}));__ATEXIT__.push((function(){FS.quit()}));__ATINIT__.unshift((function(){TTY.init()}));__ATEXIT__.push((function(){TTY.shutdown()}));if(ENVIRONMENT_IS_NODE){var fs=require(\"fs\");var NODEJS_PATH=require(\"path\");NODEFS.staticInit()}embind_init_charCodes();BindingError=Module[\"BindingError\"]=extendError(Error,\"BindingError\");InternalError=Module[\"InternalError\"]=extendError(Error,\"InternalError\");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module[\"UnboundTypeError\"]=extendError(Error,\"UnboundTypeError\");init_emval();if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function _emscripten_get_now_actual(){var t=process[\"hrtime\"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!==\"undefined\"){_emscripten_get_now=dateNow}else if(typeof self===\"object\"&&self[\"performance\"]&&typeof self[\"performance\"][\"now\"]===\"function\"){_emscripten_get_now=(function(){return self[\"performance\"][\"now\"]()})}else if(typeof performance===\"object\"&&typeof performance[\"now\"]===\"function\"){_emscripten_get_now=(function(){return performance[\"now\"]()})}else{_emscripten_get_now=Date.now}___buildEnvironment(ENV);Module[\"requestFullScreen\"]=function Module_requestFullScreen(lockPointer,resizeCanvas,vrDevice){Module.printErr(\"Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.\");Module[\"requestFullScreen\"]=Module[\"requestFullscreen\"];Browser.requestFullScreen(lockPointer,resizeCanvas,vrDevice)};Module[\"requestFullscreen\"]=function Module_requestFullscreen(lockPointer,resizeCanvas,vrDevice){Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)};Module[\"requestAnimationFrame\"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module[\"setCanvasSize\"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module[\"pauseMainLoop\"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module[\"resumeMainLoop\"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module[\"getUserMedia\"]=function Module_getUserMedia(){Browser.getUserMedia()};Module[\"createContext\"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var GLctx;GL.init();JSEvents.staticInit();DYNAMICTOP_PTR=staticAlloc(4);STACK_BASE=STACKTOP=alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}Module[\"wasmTableSize\"]=8953;Module[\"wasmMaxTableSize\"]=8953;function invoke_ii(index,a1){try{return Module[\"dynCall_ii\"](index,a1)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_iii(index,a1,a2){try{return Module[\"dynCall_iii\"](index,a1,a2)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_iiii(index,a1,a2,a3){try{return Module[\"dynCall_iiii\"](index,a1,a2,a3)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){try{return Module[\"dynCall_iiiii\"](index,a1,a2,a3,a4)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_vi(index,a1){try{Module[\"dynCall_vi\"](index,a1)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_vii(index,a1,a2){try{Module[\"dynCall_vii\"](index,a1,a2)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_viii(index,a1,a2,a3){try{Module[\"dynCall_viii\"](index,a1,a2,a3)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_viiii(index,a1,a2,a3,a4){try{Module[\"dynCall_viiii\"](index,a1,a2,a3,a4)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_viiiii(index,a1,a2,a3,a4,a5){try{Module[\"dynCall_viiiii\"](index,a1,a2,a3,a4,a5)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){try{Module[\"dynCall_viiiiii\"](index,a1,a2,a3,a4,a5,a6)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){try{Module[\"dynCall_viiiiiiiii\"](index,a1,a2,a3,a4,a5,a6,a7,a8,a9)}catch(e){if(typeof e!==\"number\"&&e!==\"longjmp\")throw e;Module[\"setThrew\"](1,0)}}Module.asmGlobalArg={};Module.asmLibraryArg={\"abort\":abort,\"enlargeMemory\":enlargeMemory,\"getTotalMemory\":getTotalMemory,\"abortOnCannotGrowMemory\":abortOnCannotGrowMemory,\"invoke_ii\":invoke_ii,\"invoke_iii\":invoke_iii,\"invoke_iiii\":invoke_iiii,\"invoke_iiiii\":invoke_iiiii,\"invoke_vi\":invoke_vi,\"invoke_vii\":invoke_vii,\"invoke_viii\":invoke_viii,\"invoke_viiii\":invoke_viiii,\"invoke_viiiii\":invoke_viiiii,\"invoke_viiiiii\":invoke_viiiiii,\"invoke_viiiiiiiii\":invoke_viiiiiiiii,\"___cxa_allocate_exception\":___cxa_allocate_exception,\"___cxa_pure_virtual\":___cxa_pure_virtual,\"___cxa_throw\":___cxa_throw,\"___cxa_uncaught_exception\":___cxa_uncaught_exception,\"___lock\":___lock,\"___map_file\":___map_file,\"___setErrNo\":___setErrNo,\"___syscall140\":___syscall140,\"___syscall145\":___syscall145,\"___syscall146\":___syscall146,\"___syscall180\":___syscall180,\"___syscall192\":___syscall192,\"___syscall195\":___syscall195,\"___syscall197\":___syscall197,\"___syscall220\":___syscall220,\"___syscall221\":___syscall221,\"___syscall5\":___syscall5,\"___syscall54\":___syscall54,\"___syscall6\":___syscall6,\"___syscall91\":___syscall91,\"___unlock\":___unlock,\"__embind_register_bool\":__embind_register_bool,\"__embind_register_class\":__embind_register_class,\"__embind_register_class_class_function\":__embind_register_class_class_function,\"__embind_register_class_constructor\":__embind_register_class_constructor,\"__embind_register_class_function\":__embind_register_class_function,\"__embind_register_class_property\":__embind_register_class_property,\"__embind_register_emval\":__embind_register_emval,\"__embind_register_enum\":__embind_register_enum,\"__embind_register_enum_value\":__embind_register_enum_value,\"__embind_register_float\":__embind_register_float,\"__embind_register_function\":__embind_register_function,\"__embind_register_integer\":__embind_register_integer,\"__embind_register_memory_view\":__embind_register_memory_view,\"__embind_register_smart_ptr\":__embind_register_smart_ptr,\"__embind_register_std_string\":__embind_register_std_string,\"__embind_register_std_wstring\":__embind_register_std_wstring,\"__embind_register_void\":__embind_register_void,\"__emval_decref\":__emval_decref,\"__emval_incref\":__emval_incref,\"__emval_take_value\":__emval_take_value,\"_abort\":_abort,\"_clock_gettime\":_clock_gettime,\"_dlclose\":_dlclose,\"_dlopen\":_dlopen,\"_dlsym\":_dlsym,\"_eglGetCurrentDisplay\":_eglGetCurrentDisplay,\"_eglGetProcAddress\":_eglGetProcAddress,\"_eglQueryString\":_eglQueryString,\"_emscripten_asm_const_i\":_emscripten_asm_const_i,\"_emscripten_glActiveTexture\":_emscripten_glActiveTexture,\"_emscripten_glAttachShader\":_emscripten_glAttachShader,\"_emscripten_glBindAttribLocation\":_emscripten_glBindAttribLocation,\"_emscripten_glBindBuffer\":_emscripten_glBindBuffer,\"_emscripten_glBindFramebuffer\":_emscripten_glBindFramebuffer,\"_emscripten_glBindProgramARB\":_emscripten_glBindProgramARB,\"_emscripten_glBindRenderbuffer\":_emscripten_glBindRenderbuffer,\"_emscripten_glBindTexture\":_emscripten_glBindTexture,\"_emscripten_glBindVertexArray\":_emscripten_glBindVertexArray,\"_emscripten_glBlendColor\":_emscripten_glBlendColor,\"_emscripten_glBlendEquation\":_emscripten_glBlendEquation,\"_emscripten_glBlendEquationSeparate\":_emscripten_glBlendEquationSeparate,\"_emscripten_glBlendFunc\":_emscripten_glBlendFunc,\"_emscripten_glBlendFuncSeparate\":_emscripten_glBlendFuncSeparate,\"_emscripten_glBufferData\":_emscripten_glBufferData,\"_emscripten_glBufferSubData\":_emscripten_glBufferSubData,\"_emscripten_glCheckFramebufferStatus\":_emscripten_glCheckFramebufferStatus,\"_emscripten_glClear\":_emscripten_glClear,\"_emscripten_glClearColor\":_emscripten_glClearColor,\"_emscripten_glClearDepth\":_emscripten_glClearDepth,\"_emscripten_glClearDepthf\":_emscripten_glClearDepthf,\"_emscripten_glClearStencil\":_emscripten_glClearStencil,\"_emscripten_glClientActiveTexture\":_emscripten_glClientActiveTexture,\"_emscripten_glColorMask\":_emscripten_glColorMask,\"_emscripten_glColorPointer\":_emscripten_glColorPointer,\"_emscripten_glCompileShader\":_emscripten_glCompileShader,\"_emscripten_glCompressedTexImage2D\":_emscripten_glCompressedTexImage2D,\"_emscripten_glCompressedTexSubImage2D\":_emscripten_glCompressedTexSubImage2D,\"_emscripten_glCopyTexImage2D\":_emscripten_glCopyTexImage2D,\"_emscripten_glCopyTexSubImage2D\":_emscripten_glCopyTexSubImage2D,\"_emscripten_glCreateProgram\":_emscripten_glCreateProgram,\"_emscripten_glCreateShader\":_emscripten_glCreateShader,\"_emscripten_glCullFace\":_emscripten_glCullFace,\"_emscripten_glDeleteBuffers\":_emscripten_glDeleteBuffers,\"_emscripten_glDeleteFramebuffers\":_emscripten_glDeleteFramebuffers,\"_emscripten_glDeleteObjectARB\":_emscripten_glDeleteObjectARB,\"_emscripten_glDeleteProgram\":_emscripten_glDeleteProgram,\"_emscripten_glDeleteRenderbuffers\":_emscripten_glDeleteRenderbuffers,\"_emscripten_glDeleteShader\":_emscripten_glDeleteShader,\"_emscripten_glDeleteTextures\":_emscripten_glDeleteTextures,\"_emscripten_glDeleteVertexArrays\":_emscripten_glDeleteVertexArrays,\"_emscripten_glDepthFunc\":_emscripten_glDepthFunc,\"_emscripten_glDepthMask\":_emscripten_glDepthMask,\"_emscripten_glDepthRange\":_emscripten_glDepthRange,\"_emscripten_glDepthRangef\":_emscripten_glDepthRangef,\"_emscripten_glDetachShader\":_emscripten_glDetachShader,\"_emscripten_glDisable\":_emscripten_glDisable,\"_emscripten_glDisableVertexAttribArray\":_emscripten_glDisableVertexAttribArray,\"_emscripten_glDrawArrays\":_emscripten_glDrawArrays,\"_emscripten_glDrawArraysInstanced\":_emscripten_glDrawArraysInstanced,\"_emscripten_glDrawBuffers\":_emscripten_glDrawBuffers,\"_emscripten_glDrawElements\":_emscripten_glDrawElements,\"_emscripten_glDrawElementsInstanced\":_emscripten_glDrawElementsInstanced,\"_emscripten_glDrawRangeElements\":_emscripten_glDrawRangeElements,\"_emscripten_glEnable\":_emscripten_glEnable,\"_emscripten_glEnableClientState\":_emscripten_glEnableClientState,\"_emscripten_glEnableVertexAttribArray\":_emscripten_glEnableVertexAttribArray,\"_emscripten_glFinish\":_emscripten_glFinish,\"_emscripten_glFlush\":_emscripten_glFlush,\"_emscripten_glFramebufferRenderbuffer\":_emscripten_glFramebufferRenderbuffer,\"_emscripten_glFramebufferTexture2D\":_emscripten_glFramebufferTexture2D,\"_emscripten_glFrontFace\":_emscripten_glFrontFace,\"_emscripten_glFrustum\":_emscripten_glFrustum,\"_emscripten_glGenBuffers\":_emscripten_glGenBuffers,\"_emscripten_glGenFramebuffers\":_emscripten_glGenFramebuffers,\"_emscripten_glGenRenderbuffers\":_emscripten_glGenRenderbuffers,\"_emscripten_glGenTextures\":_emscripten_glGenTextures,\"_emscripten_glGenVertexArrays\":_emscripten_glGenVertexArrays,\"_emscripten_glGenerateMipmap\":_emscripten_glGenerateMipmap,\"_emscripten_glGetActiveAttrib\":_emscripten_glGetActiveAttrib,\"_emscripten_glGetActiveUniform\":_emscripten_glGetActiveUniform,\"_emscripten_glGetAttachedShaders\":_emscripten_glGetAttachedShaders,\"_emscripten_glGetAttribLocation\":_emscripten_glGetAttribLocation,\"_emscripten_glGetBooleanv\":_emscripten_glGetBooleanv,\"_emscripten_glGetBufferParameteriv\":_emscripten_glGetBufferParameteriv,\"_emscripten_glGetError\":_emscripten_glGetError,\"_emscripten_glGetFloatv\":_emscripten_glGetFloatv,\"_emscripten_glGetFramebufferAttachmentParameteriv\":_emscripten_glGetFramebufferAttachmentParameteriv,\"_emscripten_glGetInfoLogARB\":_emscripten_glGetInfoLogARB,\"_emscripten_glGetIntegerv\":_emscripten_glGetIntegerv,\"_emscripten_glGetObjectParameterivARB\":_emscripten_glGetObjectParameterivARB,\"_emscripten_glGetPointerv\":_emscripten_glGetPointerv,\"_emscripten_glGetProgramInfoLog\":_emscripten_glGetProgramInfoLog,\"_emscripten_glGetProgramiv\":_emscripten_glGetProgramiv,\"_emscripten_glGetRenderbufferParameteriv\":_emscripten_glGetRenderbufferParameteriv,\"_emscripten_glGetShaderInfoLog\":_emscripten_glGetShaderInfoLog,\"_emscripten_glGetShaderPrecisionFormat\":_emscripten_glGetShaderPrecisionFormat,\"_emscripten_glGetShaderSource\":_emscripten_glGetShaderSource,\"_emscripten_glGetShaderiv\":_emscripten_glGetShaderiv,\"_emscripten_glGetString\":_emscripten_glGetString,\"_emscripten_glGetStringi\":_emscripten_glGetStringi,\"_emscripten_glGetTexParameterfv\":_emscripten_glGetTexParameterfv,\"_emscripten_glGetTexParameteriv\":_emscripten_glGetTexParameteriv,\"_emscripten_glGetUniformLocation\":_emscripten_glGetUniformLocation,\"_emscripten_glGetUniformfv\":_emscripten_glGetUniformfv,\"_emscripten_glGetUniformiv\":_emscripten_glGetUniformiv,\"_emscripten_glGetVertexAttribPointerv\":_emscripten_glGetVertexAttribPointerv,\"_emscripten_glGetVertexAttribfv\":_emscripten_glGetVertexAttribfv,\"_emscripten_glGetVertexAttribiv\":_emscripten_glGetVertexAttribiv,\"_emscripten_glHint\":_emscripten_glHint,\"_emscripten_glIsBuffer\":_emscripten_glIsBuffer,\"_emscripten_glIsEnabled\":_emscripten_glIsEnabled,\"_emscripten_glIsFramebuffer\":_emscripten_glIsFramebuffer,\"_emscripten_glIsProgram\":_emscripten_glIsProgram,\"_emscripten_glIsRenderbuffer\":_emscripten_glIsRenderbuffer,\"_emscripten_glIsShader\":_emscripten_glIsShader,\"_emscripten_glIsTexture\":_emscripten_glIsTexture,\"_emscripten_glIsVertexArray\":_emscripten_glIsVertexArray,\"_emscripten_glLineWidth\":_emscripten_glLineWidth,\"_emscripten_glLinkProgram\":_emscripten_glLinkProgram,\"_emscripten_glLoadIdentity\":_emscripten_glLoadIdentity,\"_emscripten_glLoadMatrixf\":_emscripten_glLoadMatrixf,\"_emscripten_glMatrixMode\":_emscripten_glMatrixMode,\"_emscripten_glNormalPointer\":_emscripten_glNormalPointer,\"_emscripten_glPixelStorei\":_emscripten_glPixelStorei,\"_emscripten_glPolygonOffset\":_emscripten_glPolygonOffset,\"_emscripten_glReadPixels\":_emscripten_glReadPixels,\"_emscripten_glReleaseShaderCompiler\":_emscripten_glReleaseShaderCompiler,\"_emscripten_glRenderbufferStorage\":_emscripten_glRenderbufferStorage,\"_emscripten_glRotatef\":_emscripten_glRotatef,\"_emscripten_glSampleCoverage\":_emscripten_glSampleCoverage,\"_emscripten_glScissor\":_emscripten_glScissor,\"_emscripten_glShaderBinary\":_emscripten_glShaderBinary,\"_emscripten_glShaderSource\":_emscripten_glShaderSource,\"_emscripten_glStencilFunc\":_emscripten_glStencilFunc,\"_emscripten_glStencilFuncSeparate\":_emscripten_glStencilFuncSeparate,\"_emscripten_glStencilMask\":_emscripten_glStencilMask,\"_emscripten_glStencilMaskSeparate\":_emscripten_glStencilMaskSeparate,\"_emscripten_glStencilOp\":_emscripten_glStencilOp,\"_emscripten_glStencilOpSeparate\":_emscripten_glStencilOpSeparate,\"_emscripten_glTexCoordPointer\":_emscripten_glTexCoordPointer,\"_emscripten_glTexImage2D\":_emscripten_glTexImage2D,\"_emscripten_glTexImage3D\":_emscripten_glTexImage3D,\"_emscripten_glTexParameterf\":_emscripten_glTexParameterf,\"_emscripten_glTexParameterfv\":_emscripten_glTexParameterfv,\"_emscripten_glTexParameteri\":_emscripten_glTexParameteri,\"_emscripten_glTexParameteriv\":_emscripten_glTexParameteriv,\"_emscripten_glTexStorage2D\":_emscripten_glTexStorage2D,\"_emscripten_glTexStorage3D\":_emscripten_glTexStorage3D,\"_emscripten_glTexSubImage2D\":_emscripten_glTexSubImage2D,\"_emscripten_glTexSubImage3D\":_emscripten_glTexSubImage3D,\"_emscripten_glUniform1f\":_emscripten_glUniform1f,\"_emscripten_glUniform1fv\":_emscripten_glUniform1fv,\"_emscripten_glUniform1i\":_emscripten_glUniform1i,\"_emscripten_glUniform1iv\":_emscripten_glUniform1iv,\"_emscripten_glUniform2f\":_emscripten_glUniform2f,\"_emscripten_glUniform2fv\":_emscripten_glUniform2fv,\"_emscripten_glUniform2i\":_emscripten_glUniform2i,\"_emscripten_glUniform2iv\":_emscripten_glUniform2iv,\"_emscripten_glUniform3f\":_emscripten_glUniform3f,\"_emscripten_glUniform3fv\":_emscripten_glUniform3fv,\"_emscripten_glUniform3i\":_emscripten_glUniform3i,\"_emscripten_glUniform3iv\":_emscripten_glUniform3iv,\"_emscripten_glUniform4f\":_emscripten_glUniform4f,\"_emscripten_glUniform4fv\":_emscripten_glUniform4fv,\"_emscripten_glUniform4i\":_emscripten_glUniform4i,\"_emscripten_glUniform4iv\":_emscripten_glUniform4iv,\"_emscripten_glUniformMatrix2fv\":_emscripten_glUniformMatrix2fv,\"_emscripten_glUniformMatrix3fv\":_emscripten_glUniformMatrix3fv,\"_emscripten_glUniformMatrix4fv\":_emscripten_glUniformMatrix4fv,\"_emscripten_glUseProgram\":_emscripten_glUseProgram,\"_emscripten_glValidateProgram\":_emscripten_glValidateProgram,\"_emscripten_glVertexAttrib1f\":_emscripten_glVertexAttrib1f,\"_emscripten_glVertexAttrib1fv\":_emscripten_glVertexAttrib1fv,\"_emscripten_glVertexAttrib2f\":_emscripten_glVertexAttrib2f,\"_emscripten_glVertexAttrib2fv\":_emscripten_glVertexAttrib2fv,\"_emscripten_glVertexAttrib3f\":_emscripten_glVertexAttrib3f,\"_emscripten_glVertexAttrib3fv\":_emscripten_glVertexAttrib3fv,\"_emscripten_glVertexAttrib4f\":_emscripten_glVertexAttrib4f,\"_emscripten_glVertexAttrib4fv\":_emscripten_glVertexAttrib4fv,\"_emscripten_glVertexAttribDivisor\":_emscripten_glVertexAttribDivisor,\"_emscripten_glVertexAttribIPointer\":_emscripten_glVertexAttribIPointer,\"_emscripten_glVertexAttribPointer\":_emscripten_glVertexAttribPointer,\"_emscripten_glVertexPointer\":_emscripten_glVertexPointer,\"_emscripten_glViewport\":_emscripten_glViewport,\"_emscripten_longjmp\":_emscripten_longjmp,\"_emscripten_memcpy_big\":_emscripten_memcpy_big,\"_emscripten_webgl_create_context\":_emscripten_webgl_create_context,\"_emscripten_webgl_init_context_attributes\":_emscripten_webgl_init_context_attributes,\"_emscripten_webgl_make_context_current\":_emscripten_webgl_make_context_current,\"_getenv\":_getenv,\"_glActiveTexture\":_glActiveTexture,\"_glAttachShader\":_glAttachShader,\"_glBindAttribLocation\":_glBindAttribLocation,\"_glBindBuffer\":_glBindBuffer,\"_glBindFramebuffer\":_glBindFramebuffer,\"_glBindRenderbuffer\":_glBindRenderbuffer,\"_glBindTexture\":_glBindTexture,\"_glBlendColor\":_glBlendColor,\"_glBlendEquation\":_glBlendEquation,\"_glBlendFunc\":_glBlendFunc,\"_glBufferData\":_glBufferData,\"_glBufferSubData\":_glBufferSubData,\"_glCheckFramebufferStatus\":_glCheckFramebufferStatus,\"_glClear\":_glClear,\"_glClearColor\":_glClearColor,\"_glClearStencil\":_glClearStencil,\"_glColorMask\":_glColorMask,\"_glCompileShader\":_glCompileShader,\"_glCompressedTexImage2D\":_glCompressedTexImage2D,\"_glCompressedTexSubImage2D\":_glCompressedTexSubImage2D,\"_glCopyTexSubImage2D\":_glCopyTexSubImage2D,\"_glCreateProgram\":_glCreateProgram,\"_glCreateShader\":_glCreateShader,\"_glCullFace\":_glCullFace,\"_glDeleteBuffers\":_glDeleteBuffers,\"_glDeleteFramebuffers\":_glDeleteFramebuffers,\"_glDeleteProgram\":_glDeleteProgram,\"_glDeleteRenderbuffers\":_glDeleteRenderbuffers,\"_glDeleteShader\":_glDeleteShader,\"_glDeleteTextures\":_glDeleteTextures,\"_glDepthMask\":_glDepthMask,\"_glDisable\":_glDisable,\"_glDisableVertexAttribArray\":_glDisableVertexAttribArray,\"_glDrawArrays\":_glDrawArrays,\"_glDrawElements\":_glDrawElements,\"_glEnable\":_glEnable,\"_glEnableVertexAttribArray\":_glEnableVertexAttribArray,\"_glFinish\":_glFinish,\"_glFlush\":_glFlush,\"_glFramebufferRenderbuffer\":_glFramebufferRenderbuffer,\"_glFramebufferTexture2D\":_glFramebufferTexture2D,\"_glFrontFace\":_glFrontFace,\"_glGenBuffers\":_glGenBuffers,\"_glGenFramebuffers\":_glGenFramebuffers,\"_glGenRenderbuffers\":_glGenRenderbuffers,\"_glGenTextures\":_glGenTextures,\"_glGenerateMipmap\":_glGenerateMipmap,\"_glGetBufferParameteriv\":_glGetBufferParameteriv,\"_glGetError\":_glGetError,\"_glGetFramebufferAttachmentParameteriv\":_glGetFramebufferAttachmentParameteriv,\"_glGetIntegerv\":_glGetIntegerv,\"_glGetProgramInfoLog\":_glGetProgramInfoLog,\"_glGetProgramiv\":_glGetProgramiv,\"_glGetRenderbufferParameteriv\":_glGetRenderbufferParameteriv,\"_glGetShaderInfoLog\":_glGetShaderInfoLog,\"_glGetShaderPrecisionFormat\":_glGetShaderPrecisionFormat,\"_glGetShaderiv\":_glGetShaderiv,\"_glGetString\":_glGetString,\"_glGetUniformLocation\":_glGetUniformLocation,\"_glIsTexture\":_glIsTexture,\"_glLineWidth\":_glLineWidth,\"_glLinkProgram\":_glLinkProgram,\"_glPixelStorei\":_glPixelStorei,\"_glReadPixels\":_glReadPixels,\"_glRenderbufferStorage\":_glRenderbufferStorage,\"_glScissor\":_glScissor,\"_glShaderSource\":_glShaderSource,\"_glStencilFunc\":_glStencilFunc,\"_glStencilFuncSeparate\":_glStencilFuncSeparate,\"_glStencilMask\":_glStencilMask,\"_glStencilMaskSeparate\":_glStencilMaskSeparate,\"_glStencilOp\":_glStencilOp,\"_glStencilOpSeparate\":_glStencilOpSeparate,\"_glTexImage2D\":_glTexImage2D,\"_glTexParameteri\":_glTexParameteri,\"_glTexParameteriv\":_glTexParameteriv,\"_glTexSubImage2D\":_glTexSubImage2D,\"_glUniform1f\":_glUniform1f,\"_glUniform1fv\":_glUniform1fv,\"_glUniform1i\":_glUniform1i,\"_glUniform1iv\":_glUniform1iv,\"_glUniform2f\":_glUniform2f,\"_glUniform2fv\":_glUniform2fv,\"_glUniform2i\":_glUniform2i,\"_glUniform2iv\":_glUniform2iv,\"_glUniform3f\":_glUniform3f,\"_glUniform3fv\":_glUniform3fv,\"_glUniform3i\":_glUniform3i,\"_glUniform3iv\":_glUniform3iv,\"_glUniform4f\":_glUniform4f,\"_glUniform4fv\":_glUniform4fv,\"_glUniform4i\":_glUniform4i,\"_glUniform4iv\":_glUniform4iv,\"_glUniformMatrix2fv\":_glUniformMatrix2fv,\"_glUniformMatrix3fv\":_glUniformMatrix3fv,\"_glUniformMatrix4fv\":_glUniformMatrix4fv,\"_glUseProgram\":_glUseProgram,\"_glVertexAttrib1f\":_glVertexAttrib1f,\"_glVertexAttrib2fv\":_glVertexAttrib2fv,\"_glVertexAttrib3fv\":_glVertexAttrib3fv,\"_glVertexAttrib4fv\":_glVertexAttrib4fv,\"_glVertexAttribPointer\":_glVertexAttribPointer,\"_glViewport\":_glViewport,\"_llvm_exp2_f32\":_llvm_exp2_f32,\"_llvm_log2_f32\":_llvm_log2_f32,\"_llvm_stackrestore\":_llvm_stackrestore,\"_llvm_stacksave\":_llvm_stacksave,\"_llvm_trap\":_llvm_trap,\"_llvm_trunc_f32\":_llvm_trunc_f32,\"_longjmp\":_longjmp,\"_pthread_cond_wait\":_pthread_cond_wait,\"_pthread_getspecific\":_pthread_getspecific,\"_pthread_key_create\":_pthread_key_create,\"_pthread_once\":_pthread_once,\"_pthread_setspecific\":_pthread_setspecific,\"_sem_destroy\":_sem_destroy,\"_sem_init\":_sem_init,\"_sem_post\":_sem_post,\"_sem_wait\":_sem_wait,\"_strftime_l\":_strftime_l,\"DYNAMICTOP_PTR\":DYNAMICTOP_PTR,\"STACKTOP\":STACKTOP};var asm=Module[\"asm\"](Module.asmGlobalArg,Module.asmLibraryArg,buffer);Module[\"asm\"]=asm;var __GLOBAL__sub_I_bind_cpp=Module[\"__GLOBAL__sub_I_bind_cpp\"]=(function(){return Module[\"asm\"][\"__GLOBAL__sub_I_bind_cpp\"].apply(null,arguments)});var __GLOBAL__sub_I_skia_bindings_cpp=Module[\"__GLOBAL__sub_I_skia_bindings_cpp\"]=(function(){return Module[\"asm\"][\"__GLOBAL__sub_I_skia_bindings_cpp\"].apply(null,arguments)});var __ZSt18uncaught_exceptionv=Module[\"__ZSt18uncaught_exceptionv\"]=(function(){return Module[\"asm\"][\"__ZSt18uncaught_exceptionv\"].apply(null,arguments)});var ___errno_location=Module[\"___errno_location\"]=(function(){return Module[\"asm\"][\"___errno_location\"].apply(null,arguments)});var ___getTypeName=Module[\"___getTypeName\"]=(function(){return Module[\"asm\"][\"___getTypeName\"].apply(null,arguments)});var _emscripten_GetProcAddress=Module[\"_emscripten_GetProcAddress\"]=(function(){return Module[\"asm\"][\"_emscripten_GetProcAddress\"].apply(null,arguments)});var _emscripten_replace_memory=Module[\"_emscripten_replace_memory\"]=(function(){return Module[\"asm\"][\"_emscripten_replace_memory\"].apply(null,arguments)});var _free=Module[\"_free\"]=(function(){return Module[\"asm\"][\"_free\"].apply(null,arguments)});var _malloc=Module[\"_malloc\"]=(function(){return Module[\"asm\"][\"_malloc\"].apply(null,arguments)});var _memalign=Module[\"_memalign\"]=(function(){return Module[\"asm\"][\"_memalign\"].apply(null,arguments)});var _memset=Module[\"_memset\"]=(function(){return Module[\"asm\"][\"_memset\"].apply(null,arguments)});var setThrew=Module[\"setThrew\"]=(function(){return Module[\"asm\"][\"setThrew\"].apply(null,arguments)});var stackAlloc=Module[\"stackAlloc\"]=(function(){return Module[\"asm\"][\"stackAlloc\"].apply(null,arguments)});var stackRestore=Module[\"stackRestore\"]=(function(){return Module[\"asm\"][\"stackRestore\"].apply(null,arguments)});var stackSave=Module[\"stackSave\"]=(function(){return Module[\"asm\"][\"stackSave\"].apply(null,arguments)});var dynCall_di=Module[\"dynCall_di\"]=(function(){return Module[\"asm\"][\"dynCall_di\"].apply(null,arguments)});var dynCall_fi=Module[\"dynCall_fi\"]=(function(){return Module[\"asm\"][\"dynCall_fi\"].apply(null,arguments)});var dynCall_fif=Module[\"dynCall_fif\"]=(function(){return Module[\"asm\"][\"dynCall_fif\"].apply(null,arguments)});var dynCall_fiff=Module[\"dynCall_fiff\"]=(function(){return Module[\"asm\"][\"dynCall_fiff\"].apply(null,arguments)});var dynCall_fii=Module[\"dynCall_fii\"]=(function(){return Module[\"asm\"][\"dynCall_fii\"].apply(null,arguments)});var dynCall_fiifi=Module[\"dynCall_fiifi\"]=(function(){return Module[\"asm\"][\"dynCall_fiifi\"].apply(null,arguments)});var dynCall_i=Module[\"dynCall_i\"]=(function(){return Module[\"asm\"][\"dynCall_i\"].apply(null,arguments)});var dynCall_ii=Module[\"dynCall_ii\"]=(function(){return Module[\"asm\"][\"dynCall_ii\"].apply(null,arguments)});var dynCall_iidi=Module[\"dynCall_iidi\"]=(function(){return Module[\"asm\"][\"dynCall_iidi\"].apply(null,arguments)});var dynCall_iiff=Module[\"dynCall_iiff\"]=(function(){return Module[\"asm\"][\"dynCall_iiff\"].apply(null,arguments)});var dynCall_iiffff=Module[\"dynCall_iiffff\"]=(function(){return Module[\"asm\"][\"dynCall_iiffff\"].apply(null,arguments)});var dynCall_iiffi=Module[\"dynCall_iiffi\"]=(function(){return Module[\"asm\"][\"dynCall_iiffi\"].apply(null,arguments)});var dynCall_iii=Module[\"dynCall_iii\"]=(function(){return Module[\"asm\"][\"dynCall_iii\"].apply(null,arguments)});var dynCall_iiii=Module[\"dynCall_iiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiii\"].apply(null,arguments)});var dynCall_iiiif=Module[\"dynCall_iiiif\"]=(function(){return Module[\"asm\"][\"dynCall_iiiif\"].apply(null,arguments)});var dynCall_iiiii=Module[\"dynCall_iiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiii\"].apply(null,arguments)});var dynCall_iiiiid=Module[\"dynCall_iiiiid\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiid\"].apply(null,arguments)});var dynCall_iiiiii=Module[\"dynCall_iiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiii\"].apply(null,arguments)});var dynCall_iiiiiid=Module[\"dynCall_iiiiiid\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiid\"].apply(null,arguments)});var dynCall_iiiiiii=Module[\"dynCall_iiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiii\"].apply(null,arguments)});var dynCall_iiiiiiii=Module[\"dynCall_iiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiiii\"].apply(null,arguments)});var dynCall_iiiiiiiii=Module[\"dynCall_iiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiiiii\"].apply(null,arguments)});var dynCall_iiiiiiiiii=Module[\"dynCall_iiiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiiiiii\"].apply(null,arguments)});var dynCall_iiiiiiiiiii=Module[\"dynCall_iiiiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiiiiiiii\"].apply(null,arguments)});var dynCall_iiiiij=Module[\"dynCall_iiiiij\"]=(function(){return Module[\"asm\"][\"dynCall_iiiiij\"].apply(null,arguments)});var dynCall_iiiij=Module[\"dynCall_iiiij\"]=(function(){return Module[\"asm\"][\"dynCall_iiiij\"].apply(null,arguments)});var dynCall_iiij=Module[\"dynCall_iiij\"]=(function(){return Module[\"asm\"][\"dynCall_iiij\"].apply(null,arguments)});var dynCall_iijj=Module[\"dynCall_iijj\"]=(function(){return Module[\"asm\"][\"dynCall_iijj\"].apply(null,arguments)});var dynCall_ji=Module[\"dynCall_ji\"]=(function(){return Module[\"asm\"][\"dynCall_ji\"].apply(null,arguments)});var dynCall_jii=Module[\"dynCall_jii\"]=(function(){return Module[\"asm\"][\"dynCall_jii\"].apply(null,arguments)});var dynCall_jiiiijiiiii=Module[\"dynCall_jiiiijiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_jiiiijiiiii\"].apply(null,arguments)});var dynCall_v=Module[\"dynCall_v\"]=(function(){return Module[\"asm\"][\"dynCall_v\"].apply(null,arguments)});var dynCall_vd=Module[\"dynCall_vd\"]=(function(){return Module[\"asm\"][\"dynCall_vd\"].apply(null,arguments)});var dynCall_vdd=Module[\"dynCall_vdd\"]=(function(){return Module[\"asm\"][\"dynCall_vdd\"].apply(null,arguments)});var dynCall_vdddddd=Module[\"dynCall_vdddddd\"]=(function(){return Module[\"asm\"][\"dynCall_vdddddd\"].apply(null,arguments)});var dynCall_vf=Module[\"dynCall_vf\"]=(function(){return Module[\"asm\"][\"dynCall_vf\"].apply(null,arguments)});var dynCall_vff=Module[\"dynCall_vff\"]=(function(){return Module[\"asm\"][\"dynCall_vff\"].apply(null,arguments)});var dynCall_vffff=Module[\"dynCall_vffff\"]=(function(){return Module[\"asm\"][\"dynCall_vffff\"].apply(null,arguments)});var dynCall_vfi=Module[\"dynCall_vfi\"]=(function(){return Module[\"asm\"][\"dynCall_vfi\"].apply(null,arguments)});var dynCall_vi=Module[\"dynCall_vi\"]=(function(){return Module[\"asm\"][\"dynCall_vi\"].apply(null,arguments)});var dynCall_vif=Module[\"dynCall_vif\"]=(function(){return Module[\"asm\"][\"dynCall_vif\"].apply(null,arguments)});var dynCall_viff=Module[\"dynCall_viff\"]=(function(){return Module[\"asm\"][\"dynCall_viff\"].apply(null,arguments)});var dynCall_vifff=Module[\"dynCall_vifff\"]=(function(){return Module[\"asm\"][\"dynCall_vifff\"].apply(null,arguments)});var dynCall_viffff=Module[\"dynCall_viffff\"]=(function(){return Module[\"asm\"][\"dynCall_viffff\"].apply(null,arguments)});var dynCall_viffi=Module[\"dynCall_viffi\"]=(function(){return Module[\"asm\"][\"dynCall_viffi\"].apply(null,arguments)});var dynCall_vifii=Module[\"dynCall_vifii\"]=(function(){return Module[\"asm\"][\"dynCall_vifii\"].apply(null,arguments)});var dynCall_vii=Module[\"dynCall_vii\"]=(function(){return Module[\"asm\"][\"dynCall_vii\"].apply(null,arguments)});var dynCall_viid=Module[\"dynCall_viid\"]=(function(){return Module[\"asm\"][\"dynCall_viid\"].apply(null,arguments)});var dynCall_viif=Module[\"dynCall_viif\"]=(function(){return Module[\"asm\"][\"dynCall_viif\"].apply(null,arguments)});var dynCall_viifd=Module[\"dynCall_viifd\"]=(function(){return Module[\"asm\"][\"dynCall_viifd\"].apply(null,arguments)});var dynCall_viiff=Module[\"dynCall_viiff\"]=(function(){return Module[\"asm\"][\"dynCall_viiff\"].apply(null,arguments)});var dynCall_viifff=Module[\"dynCall_viifff\"]=(function(){return Module[\"asm\"][\"dynCall_viifff\"].apply(null,arguments)});var dynCall_viiffff=Module[\"dynCall_viiffff\"]=(function(){return Module[\"asm\"][\"dynCall_viiffff\"].apply(null,arguments)});var dynCall_viiffi=Module[\"dynCall_viiffi\"]=(function(){return Module[\"asm\"][\"dynCall_viiffi\"].apply(null,arguments)});var dynCall_viiffii=Module[\"dynCall_viiffii\"]=(function(){return Module[\"asm\"][\"dynCall_viiffii\"].apply(null,arguments)});var dynCall_viii=Module[\"dynCall_viii\"]=(function(){return Module[\"asm\"][\"dynCall_viii\"].apply(null,arguments)});var dynCall_viiif=Module[\"dynCall_viiif\"]=(function(){return Module[\"asm\"][\"dynCall_viiif\"].apply(null,arguments)});var dynCall_viiiffi=Module[\"dynCall_viiiffi\"]=(function(){return Module[\"asm\"][\"dynCall_viiiffi\"].apply(null,arguments)});var dynCall_viiii=Module[\"dynCall_viiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiii\"].apply(null,arguments)});var dynCall_viiiifi=Module[\"dynCall_viiiifi\"]=(function(){return Module[\"asm\"][\"dynCall_viiiifi\"].apply(null,arguments)});var dynCall_viiiii=Module[\"dynCall_viiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiii\"].apply(null,arguments)});var dynCall_viiiiif=Module[\"dynCall_viiiiif\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiif\"].apply(null,arguments)});var dynCall_viiiiiffii=Module[\"dynCall_viiiiiffii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiffii\"].apply(null,arguments)});var dynCall_viiiiii=Module[\"dynCall_viiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiii\"].apply(null,arguments)});var dynCall_viiiiiiffi=Module[\"dynCall_viiiiiiffi\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiffi\"].apply(null,arguments)});var dynCall_viiiiiii=Module[\"dynCall_viiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiii\"].apply(null,arguments)});var dynCall_viiiiiiii=Module[\"dynCall_viiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiii\"].apply(null,arguments)});var dynCall_viiiiiiiii=Module[\"dynCall_viiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiiii\"].apply(null,arguments)});var dynCall_viiiiiiiiii=Module[\"dynCall_viiiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiiiii\"].apply(null,arguments)});var dynCall_viiiiiiiiiii=Module[\"dynCall_viiiiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiiiiii\"].apply(null,arguments)});var dynCall_viiiiiiiiiiii=Module[\"dynCall_viiiiiiiiiiii\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiiiiiiiii\"].apply(null,arguments)});var dynCall_viiiij=Module[\"dynCall_viiiij\"]=(function(){return Module[\"asm\"][\"dynCall_viiiij\"].apply(null,arguments)});var dynCall_viiiiji=Module[\"dynCall_viiiiji\"]=(function(){return Module[\"asm\"][\"dynCall_viiiiji\"].apply(null,arguments)});var dynCall_viiij=Module[\"dynCall_viiij\"]=(function(){return Module[\"asm\"][\"dynCall_viiij\"].apply(null,arguments)});var dynCall_viij=Module[\"dynCall_viij\"]=(function(){return Module[\"asm\"][\"dynCall_viij\"].apply(null,arguments)});var dynCall_viijii=Module[\"dynCall_viijii\"]=(function(){return Module[\"asm\"][\"dynCall_viijii\"].apply(null,arguments)});var dynCall_vij=Module[\"dynCall_vij\"]=(function(){return Module[\"asm\"][\"dynCall_vij\"].apply(null,arguments)});var dynCall_vji=Module[\"dynCall_vji\"]=(function(){return Module[\"asm\"][\"dynCall_vji\"].apply(null,arguments)});Module[\"asm\"]=asm;Module[\"then\"]=(function(func){if(Module[\"calledRun\"]){func(Module)}else{var old=Module[\"onRuntimeInitialized\"];Module[\"onRuntimeInitialized\"]=(function(){if(old)old();func(Module)})}return Module});function ExitStatus(status){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+status+\")\";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;dependenciesFulfilled=function runCaller(){if(!Module[\"calledRun\"])run();if(!Module[\"calledRun\"])dependenciesFulfilled=runCaller};function run(args){args=args||Module[\"arguments\"];if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module[\"calledRun\"])return;function doRun(){if(Module[\"calledRun\"])return;Module[\"calledRun\"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module[\"onRuntimeInitialized\"])Module[\"onRuntimeInitialized\"]();postRun()}if(Module[\"setStatus\"]){Module[\"setStatus\"](\"Running...\");setTimeout((function(){setTimeout((function(){Module[\"setStatus\"](\"\")}),1);doRun()}),1)}else{doRun()}}Module[\"run\"]=run;function exit(status,implicit){if(implicit&&Module[\"noExitRuntime\"]&&status===0){return}if(Module[\"noExitRuntime\"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module[\"onExit\"])Module[\"onExit\"](status)}if(ENVIRONMENT_IS_NODE){process[\"exit\"](status)}Module[\"quit\"](status,new ExitStatus(status))}Module[\"exit\"]=exit;function abort(what){if(Module[\"onAbort\"]){Module[\"onAbort\"](what)}if(what!==undefined){Module.print(what);Module.printErr(what);what=JSON.stringify(what)}else{what=\"\"}ABORT=true;EXITSTATUS=1;throw\"abort(\"+what+\"). Build with -s ASSERTIONS=1 for more info.\"}Module[\"abort\"]=abort;if(Module[\"preInit\"]){if(typeof Module[\"preInit\"]==\"function\")Module[\"preInit\"]=[Module[\"preInit\"]];while(Module[\"preInit\"].length>0){Module[\"preInit\"].pop()()}}Module[\"noExitRuntime\"]=true;run()\n\n\n\n\n\n  return Module;\n};\nif (typeof exports === 'object' && typeof module === 'object')\n    module.exports = Module;\n  else if (typeof define === 'function' && define['amd'])\n    define([], function() { return Module; });\n  else if (typeof exports === 'object')\n    exports[\"Module\"] = Module;\n  "
  },
  {
    "path": "docs/webgl.js",
    "content": "'use strict'\n\n//TODO port sdl example instead\n// TODO port types: SkTArray, SkRect, SkMatrix\n\nconst helpMessage = 'Click and drag to create rects.'\nconst state = {\n  fRects: [],\n  skiaModule: null,\n  canvas: null,\n  paint: null,\n  image: null,\n  width: window.innerWidth,\n  height: window.innerHeight,\n  rotation: 0\n}\n\nasync function loadFont () {\n  const {skiaModule, paint} = state\n\n  const request = new XMLHttpRequest()\n  request.open('GET', `${window.location}/LiberationMono-Regular-ttf`, true)\n  request.responseType = 'arraybuffer'\n\n  const fontData = await new Promise((resolve) => {\n    request.onload = () => {\n      resolve(new Uint8Array(request.response))\n    }\n    request.send()\n  })\n\n  const nativeData = skiaModule.SkData.MakeUninitialized(fontData.byteLength)\n  const nativeBuffer = skiaModule.getSkDataBytes(nativeData)\n  nativeBuffer.set(fontData)\n  const liberationMonoRegular = skiaModule.SkFontMgr.RefDefault().makeFromData(nativeData, 0)\n  paint.setTextSize(48.0)\n  paint.setColor(0xff4281A4)\n  paint.setTypeface(liberationMonoRegular)\n}\n\nfunction create_star () {\n  const {skiaModule} = state\n  const concavePath = new skiaModule.SkPath()\n  const points = [\n    skiaModule.SkPoint.Make(0, -50),\n    skiaModule.SkPoint.Make(0, 0),\n    skiaModule.SkPoint.Make(0, 0),\n    skiaModule.SkPoint.Make(0, 0),\n    skiaModule.SkPoint.Make(0, 0)\n  ]\n  const kNumPoints = points.length\n  const rot = new skiaModule.SkMatrix()\n  rot.setRotate(360 / kNumPoints)\n  for (let i = 1; i < kNumPoints; ++i) {\n    rot.mapPoints(points[i], points[i - 1], 1)\n  }\n  concavePath.moveToPoint(points[0])\n  for (let i = 0; i < kNumPoints; ++i) {\n    concavePath.lineToPoint(points[(2 * i) % kNumPoints])\n  }\n  concavePath.setFillType(skiaModule.SkPath.FillType.kEvenOdd_FillType)\n  concavePath.close()\n  return concavePath\n}\n\nasync function main (skiaModule) {\n  state.skiaModule = skiaModule\n\n  const canvasElement = document.createElement('canvas')\n  const {width, height} = state\n  canvasElement.id = 'somecanvas'\n  canvasElement.width = width\n  canvasElement.height = height\n  document.body.appendChild(canvasElement)\n\n  const surface = skiaModule.makeWebGLSurface(canvasElement.id, width, height)\n\n  // skia canvas\n  const canvas = surface.getCanvas()\n  state.canvas = canvas\n\n  const paint = new skiaModule.SkPaint()\n  state.paint = paint\n  paint.setAntiAlias(true)\n\n  await loadFont()\n\n  // create a surface for CPU rasterization\n  const cpuSurface = skiaModule.SkSurface.MakeRasterN32Premul(width, height, null)\n  const offscreen = cpuSurface.getCanvas()\n  offscreen.save()\n  offscreen.translate(501, 50)\n  offscreen.drawPath(create_star(), paint)\n  offscreen.restore()\n\n  state.image = cpuSurface.makeImageSnapshot()\n\n  canvasElement.addEventListener('mousemove', (event) => {\n    if (event.buttons !== 0) {\n      const rect = state.fRects[state.fRects.length - 1]\n      rect.fRight = event.clientX\n      rect.fBottom = event.clientY\n    }\n  })\n  canvasElement.addEventListener('mousedown', (event) => {\n    if (event.buttons !== 0) {\n      state.fRects.push(skiaModule.SkRect.MakeLTRB(event.clientX,\n        event.clientY,\n        event.clientX,\n        event.clientY))\n    }\n  })\n\n  scheduleAnimation()\n}\n\nfunction scheduleAnimation () {\n  const {skiaModule, canvas, paint, image, width, height} = state\n  window.requestAnimationFrame(() => {\n    const rand = new skiaModule.SkRandom()\n    canvas.clear(0xFFFFFFFF)//white\n\n    paint.setColor(0xff4281A4)\n    canvas.drawText(helpMessage, 50, 50, paint)\n\n    for (let i = 0; i < state.fRects.length; i++) {\n      paint.setColor((rand.nextU() & 0x7fffffff) | 0x44808080)\n      canvas.drawRect(state.fRects[i], paint)\n    }\n\n    // draw offscreen canvas\n    canvas.save()\n    canvas.translate(width / 2.0, height / 2.0)\n    canvas.rotate(state.rotation++)\n    canvas.drawImage(image, -50, -50, null)\n    canvas.restore()\n\n    canvas.flush()\n    scheduleAnimation()\n  })\n}\n\nfunction loadNativeModule (skiaModule) {\n  return new Promise((resolve) => {\n    if (skiaModule.calledRun) {\n      resolve()\n    } else {\n      skiaModule.onRuntimeInitialized = () => {\n        resolve()\n      }\n    }\n  })\n}\n\nwindow.onload = async () => {\n  // make sure the native modules is ready for use before we start our main flow\n  const skiaModule = Module()\n  await loadNativeModule(skiaModule)\n  try {\n    main(skiaModule)\n  } catch (error) {\n    console.error(error)\n  }\n}"
  },
  {
    "path": "example_gradient.js",
    "content": "const fs = require('fs')\nconst skia = require('./skia')\n\nfunction draw (skiaModule, canvas) {\n  canvas.clear(0xFFFFFFFF)//white\n\n  const paint = new skiaModule.SkPaint()\n\n  const points = new skiaModule.VectorSkPoint()\n  points.push_back(skiaModule.SkPoint.Make(0, 0))\n  points.push_back(skiaModule.SkPoint.Make(256, 256))\n\n  const colors = new skiaModule.VectorSkColor()\n  colors.push_back(0xFF00FF00)\n  colors.push_back(0xFFFF0000)\n\n  const pos = new skiaModule.VectorSkScalar()\n\n  paint.setShader(skiaModule.SkGradientShader.MakeLinear(points, colors, pos, 2, skiaModule.SkShader.TileMode.kClamp_TileMode))\n  canvas.drawPaint(paint)\n}\n\nfunction main (skiaModule) {\n  const width = 256\n  const height = 256\n  const path = 'out_gradient.png'\n  const rasterSurface = skiaModule.SkSurface.MakeRasterN32Premul(width, height, null)\n  const rasterCanvas = rasterSurface.getCanvas()\n  draw(skiaModule, rasterCanvas)\n\n  const img = rasterSurface.makeImageSnapshot()\n  if (!img) { return }\n  const png = img.encodeToData()\n  if (!png) { return }\n  const pngBytes = skiaModule.getSkDataBytes(png)\n  fs.appendFileSync(path, new Buffer(pngBytes))\n}\n\nfunction loadNativeModule (module) {\n  return new Promise((resolve) => {\n    if (module.calledRun) {\n      resolve()\n    } else {\n      module.onRuntimeInitialized = () => {\n        resolve()\n      }\n    }\n  })\n}\n\n// make sure the native modules is ready for use before we start our main flow\nconst skiaModule = skia()\nloadNativeModule(skiaModule).then(() => {\n  main(skiaModule)\n}).catch((error) => {\n  console.log(error)\n})\n\n\n"
  },
  {
    "path": "example_star.js",
    "content": "const fs = require('fs')\nconst skia = require('./skia')\n\nfunction draw (canvas) {\n  const scale = 256.0\n  const R = 0.45 * scale\n  const TAU = 6.2831853\n  const path = new skiaModule.SkPath()\n  for (let i = 0; i < 5; ++i) {\n    const theta = 2 * i * TAU / 5\n    if (i === 0) {\n      path.moveToXY(R * Math.cos(theta), R * Math.sin(theta))\n    } else {\n      path.lineToXY(R * Math.cos(theta), R * Math.sin(theta))\n    }\n  }\n  path.close()\n  const p = new skiaModule.SkPaint()\n  p.setAntiAlias(true)\n  canvas.clear(0xFFFFFFFF)//white\n  canvas.translate(0.5 * scale, 0.5 * scale)\n  canvas.drawPath(path, p)\n}\n\nfunction main (skiaModule) {\n  const width = 256\n  const height = 256\n  const path = 'out_star.png'\n  const rasterSurface = skiaModule.SkSurface.MakeRasterN32Premul(width, height, null)\n  const rasterCanvas = rasterSurface.getCanvas()\n  draw(rasterCanvas)\n\n  const img = rasterSurface.makeImageSnapshot()\n  if (!img) { return }\n  const png = img.encodeToData()\n  if (!png) { return }\n  const pngBytes = skiaModule.getSkDataBytes(png)\n  fs.appendFileSync(path, new Buffer(pngBytes));\n}\n\nfunction loadNativeModule (module) {\n  return new Promise((resolve) => {\n    if (module.calledRun) {\n      resolve()\n    } else {\n      module.onRuntimeInitialized = () => {\n        resolve()\n      }\n    }\n  })\n}\n\n// make sure the native modules is ready for use before we start our main flow\nconst skiaModule = skia()\nloadNativeModule(skiaModule).then(() => {\n  main(skiaModule)\n}).catch((error) => {\n  console.log(error)\n})\n\n\n"
  },
  {
    "path": "example_text.js",
    "content": "const fs = require('fs')\nconst path = require('path')\nconst skia = require('./skia')\n\nfunction draw (skiaModule, canvas) {\n  canvas.clear(0xFFFFFFFF) // white\n\n  // read data from file & copy it to wasm memory\n  const data = fs.readFileSync(path.join(__dirname, '.', 'fonts', 'liberation-fonts', 'LiberationMono-Regular.ttf'))\n  const nativeData = skiaModule.SkData.MakeUninitialized(data.byteLength)\n  const nativeBuffer = skiaModule.getSkDataBytes(nativeData)\n  nativeBuffer.set(data)\n  const liberationMonoRegular = skiaModule.SkFontMgr.RefDefault().makeFromData(nativeData, 0)\n  const paint = new skiaModule.SkPaint()\n  paint.setTextSize(48.0)\n  paint.setAntiAlias(true)\n  paint.setColor(0xff4281A4)\n  paint.setTypeface(liberationMonoRegular)\n\n  const data1 = fs.readFileSync(path.join(__dirname, '.', 'fonts', 'liberation-fonts', 'LiberationSerif-BoldItalic.ttf'))\n  const nativeData1 = skiaModule.SkData.MakeUninitialized(data1.byteLength)\n  const nativeBuffer1 = skiaModule.getSkDataBytes(nativeData1)\n  nativeBuffer1.set(data1)\n  const liberationSerifBoldItalic = skiaModule.SkFontMgr.RefDefault().makeFromData(nativeData1, 0)\n  const paint1 = new skiaModule.SkPaint()\n  paint1.setTextSize(48.0)\n  paint1.setAntiAlias(true)\n  paint1.setColor(0xff6291B4)\n  paint1.setTypeface(liberationSerifBoldItalic)\n\n  canvas.drawText('Liberation Mono Regular', 20, 64, paint)\n  canvas.drawText('Liberation Serif Bold Italic', 20, 128, paint1)\n}\n\nfunction main (skiaModule) {\n  const width = 768\n  const height = 192\n  const path = 'out_text.png'\n  const rasterSurface = skiaModule.SkSurface.MakeRasterN32Premul(width, height, null)\n  const rasterCanvas = rasterSurface.getCanvas()\n  draw(skiaModule, rasterCanvas)\n\n  const img = rasterSurface.makeImageSnapshot()\n  if (!img) { return }\n  const png = img.encodeToData()\n  if (!png) { return }\n  const pngBytes = skiaModule.getSkDataBytes(png)\n  fs.appendFileSync(path, new Buffer(pngBytes))\n}\n\nfunction loadNativeModule (module) {\n  return new Promise((resolve) => {\n    if (module.calledRun) {\n      resolve()\n    } else {\n      module.onRuntimeInitialized = () => {\n        resolve()\n      }\n    }\n  })\n}\n\n// make sure the native modules is ready for use before we start our main flow\nconst skiaModule = skia()\nloadNativeModule(skiaModule).then(() => {\n  main(skiaModule)\n}).catch((error) => {\n  console.log(error)\n})\n\n\n"
  },
  {
    "path": "include/android/SkAndroidFrameworkUtils.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAndroidFrameworkUtils_DEFINED\n#define SkAndroidFrameworkUtils_DEFINED\n\n#include \"SkTypes.h\"\n\n#ifdef SK_BUILD_FOR_ANDROID\n\nclass SkCanvas;\n\n/**\n *  SkAndroidFrameworkUtils expose private APIs used only by Android framework.\n */\nclass SkAndroidFrameworkUtils {\npublic:\n\n#if SK_SUPPORT_GPU\n    /**\n     *  clipWithStencil draws the current clip into a stencil buffer with reference value and mask\n     *  set to 0x1. This function works only on a GPU canvas.\n     *\n     *  @param  canvas A GPU canvas that has a non-empty clip.\n     *\n     *  @return true on success or false if clip is empty or not a GPU canvas.\n     */\n    static bool clipWithStencil(SkCanvas* canvas);\n#endif //SK_SUPPORT_GPU\n};\n\n#endif // SK_BUILD_FOR_ANDROID\n\n#endif // SkAndroidFrameworkUtils_DEFINED\n"
  },
  {
    "path": "include/android/SkAnimatedImage.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAnimatedImage_DEFINED\n#define SkAnimatedImage_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkCodecAnimation.h\"\n#include \"SkDrawable.h\"\n#include \"SkMatrix.h\"\n#include \"SkRect.h\"\n\nclass SkAndroidCodec;\nclass SkPicture;\n\n/**\n *  Thread unsafe drawable for drawing animated images (e.g. GIF).\n */\nclass SK_API SkAnimatedImage : public SkDrawable {\npublic:\n    /**\n     *  Create an SkAnimatedImage from the SkAndroidCodec.\n     *\n     *  Returns null on failure to allocate pixels. On success, this will\n     *  decode the first frame.\n     *\n     *  @param scaledSize Size to draw the image, possibly requiring scaling.\n     *  @param cropRect Rectangle to crop to after scaling.\n     *  @param postProcess Picture to apply after scaling and cropping.\n     */\n    static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,\n            SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess);\n\n    /**\n     *  Simpler version that uses the default size, no cropping, and no postProcess.\n     */\n    static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>);\n\n    ~SkAnimatedImage() override;\n\n    /**\n     *  Reset the animation to the beginning.\n     */\n    void reset();\n\n    /**\n     *  Whether the animation completed.\n     *\n     *  Returns true after all repetitions are complete, or an error stops the\n     *  animation. Gets reset to false if the animation is restarted.\n     */\n    bool isFinished() const { return fFinished; }\n\n    /**\n     * Returned by decodeNextFrame and currentFrameDuration if the animation\n     * is not running.\n     */\n    static constexpr int kFinished = -1;\n\n    /**\n     *  Decode the next frame.\n     *\n     *  If the animation is on the last frame or has hit an error, returns\n     *  kFinished.\n     */\n    int decodeNextFrame();\n\n    /**\n     *  How long to display the current frame.\n     *\n     *  Useful for the first frame, for which decodeNextFrame is called\n     *  internally.\n     */\n    int currentFrameDuration() {\n        return fCurrentFrameDuration;\n    }\n\n    /**\n     *  Change the repetition count.\n     *\n     *  By default, the image will repeat the number of times indicated in the\n     *  encoded data.\n     *\n     *  Use SkCodec::kRepetitionCountInfinite for infinite, and 0 to show all\n     *  frames once and then stop.\n     */\n    void setRepetitionCount(int count);\n\n    /**\n     *  Return the currently set repetition count.\n     */\n    int getRepetitionCount() const {\n        return fRepetitionCount;\n    }\n\nprotected:\n    SkRect onGetBounds() override;\n    void onDraw(SkCanvas*) override;\n\nprivate:\n    struct Frame {\n        SkBitmap fBitmap;\n        int      fIndex;\n        SkCodecAnimation::DisposalMethod fDisposalMethod;\n\n        // init() may have to create a new SkPixelRef, if the\n        // current one is already in use by another owner (e.g.\n        // an SkPicture). This determines whether to copy the\n        // existing one to the new one.\n        enum class OnInit {\n            // Restore the image from the old SkPixelRef to the\n            // new one.\n            kRestoreIfNecessary,\n            // No need to restore.\n            kNoRestore,\n        };\n\n        Frame();\n        bool init(const SkImageInfo& info, OnInit);\n        bool copyTo(Frame*) const;\n    };\n\n    std::unique_ptr<SkAndroidCodec> fCodec;\n    const SkISize                   fScaledSize;\n    const SkImageInfo               fDecodeInfo;\n    const SkIRect                   fCropRect;\n    const sk_sp<SkPicture>          fPostProcess;\n    const int                       fFrameCount;\n    const bool                      fSimple;     // no crop, scale, or postprocess\n    SkMatrix                        fMatrix;     // used only if !fSimple\n\n    bool                            fFinished;\n    int                             fCurrentFrameDuration;\n    Frame                           fDisplayFrame;\n    Frame                           fDecodingFrame;\n    Frame                           fRestoreFrame;\n    int                             fRepetitionCount;\n    int                             fRepetitionsCompleted;\n\n    SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, SkISize scaledSize,\n            SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess);\n    SkAnimatedImage(std::unique_ptr<SkAndroidCodec>);\n\n    int computeNextFrame(int current, bool* animationEnded);\n    double finish();\n\n    typedef SkDrawable INHERITED;\n};\n\n#endif // SkAnimatedImage_DEFINED\n"
  },
  {
    "path": "include/android/SkBRDAllocator.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBRDAllocator_DEFINED\n#define SkBRDAllocator_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkCodec.h\"\n\n/**\n *  Abstract subclass of SkBitmap's allocator.\n *  Allows the allocator to indicate if the memory it allocates\n *  is zero initialized.\n */\nclass SkBRDAllocator : public SkBitmap::Allocator {\npublic:\n\n    /**\n     *  Indicates if the memory allocated by this allocator is\n     *  zero initialized.\n     */\n    virtual SkCodec::ZeroInitialized zeroInit() const = 0;\n};\n\n#endif // SkBRDAllocator_DEFINED\n"
  },
  {
    "path": "include/android/SkBitmapRegionDecoder.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBitmapRegionDecoder_DEFINED\n#define SkBitmapRegionDecoder_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkBRDAllocator.h\"\n#include \"SkEncodedImageFormat.h\"\n#include \"SkStream.h\"\n\n/*\n * This class aims to provide an interface to test multiple implementations of\n * SkBitmapRegionDecoder.\n */\nclass SK_API SkBitmapRegionDecoder {\npublic:\n\n    enum Strategy {\n        kAndroidCodec_Strategy, // Uses SkAndroidCodec for scaling and subsetting\n    };\n\n    /*\n     * @param data     Refs the data while this object exists, unrefs on destruction\n     * @param strategy Strategy used for scaling and subsetting\n     * @return         Tries to create an SkBitmapRegionDecoder, returns NULL on failure\n     */\n    static SkBitmapRegionDecoder* Create(sk_sp<SkData>, Strategy strategy);\n\n    /*\n     * @param stream   Takes ownership of the stream\n     * @param strategy Strategy used for scaling and subsetting\n     * @return         Tries to create an SkBitmapRegionDecoder, returns NULL on failure\n     */\n    static SkBitmapRegionDecoder* Create(\n            SkStreamRewindable* stream, Strategy strategy);\n\n    /*\n     * Decode a scaled region of the encoded image stream\n     *\n     * @param bitmap          Container for decoded pixels.  It is assumed that the pixels\n     *                        are initially unallocated and will be allocated by this function.\n     * @param allocator       Allocator for the pixels.  If this is NULL, the default\n     *                        allocator (HeapAllocator) will be used.\n     * @param desiredSubset   Subset of the original image to decode.\n     * @param sampleSize      An integer downscaling factor for the decode.\n     * @param colorType       Preferred output colorType.\n     *                        New implementations should return NULL if they do not support\n     *                        decoding to this color type.\n     *                        The old kOriginal_Strategy will decode to a default color type\n     *                        if this color type is unsupported.\n     * @param requireUnpremul If the image is not opaque, we will use this to determine the\n     *                        alpha type to use.\n     * @param prefColorSpace  If non-null and supported, this is the color space that we will\n     *                        decode into.  Otherwise, we will choose a default.\n     *\n     */\n    virtual bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,\n                              const SkIRect& desiredSubset, int sampleSize,\n                              SkColorType colorType, bool requireUnpremul,\n                              sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;\n\n    virtual SkEncodedImageFormat getEncodedFormat() = 0;\n\n    virtual SkColorType computeOutputColorType(SkColorType requestedColorType) = 0;\n\n    virtual sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,\n            sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;\n\n\n    int width() const { return fWidth; }\n    int height() const { return fHeight; }\n\n    virtual ~SkBitmapRegionDecoder() {}\n\nprotected:\n\n    SkBitmapRegionDecoder(int width, int height)\n        : fWidth(width)\n        , fHeight(height)\n    {}\n\nprivate:\n    const int fWidth;\n    const int fHeight;\n};\n\n#endif\n"
  },
  {
    "path": "include/atlastext/SkAtlasTextContext.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAtlasTextContext_DEFINED\n#define SkAtlasTextContext_DEFINED\n\n#include \"SkRefCnt.h\"\n\nclass SkAtlasTextRenderer;\nclass SkInternalAtlasTextContext;\n\nSkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(class SkInternalAtlasTextContext&);\n\n/**\n * Class that Atlas Text client uses to register their SkAtlasTextRenderer implementation and\n * to create one or more SkAtlasTextTargets (destination surfaces for text rendering).\n */\nclass SK_API SkAtlasTextContext : public SkRefCnt {\npublic:\n    static sk_sp<SkAtlasTextContext> Make(sk_sp<SkAtlasTextRenderer>);\n\n    SkAtlasTextRenderer* renderer() const {\n        return SkGetAtlasTextRendererFromInternalContext(*fInternalContext);\n    }\n\n    SkInternalAtlasTextContext& internal() { return *fInternalContext; }\n\nprivate:\n    SkAtlasTextContext() = delete;\n    SkAtlasTextContext(const SkAtlasTextContext&) = delete;\n    SkAtlasTextContext& operator=(const SkAtlasTextContext&) = delete;\n\n    SkAtlasTextContext(sk_sp<SkAtlasTextRenderer>);\n\n    std::unique_ptr<SkInternalAtlasTextContext> fInternalContext;\n};\n\n#endif\n"
  },
  {
    "path": "include/atlastext/SkAtlasTextFont.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAtlasTextFont_DEFINED\n#define SkAtlasTextFont_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkTypeface.h\"\n\n/** Represents a font at a size. TODO: What else do we need here (skewX, scaleX, vertical, ...)? */\nclass SK_API SkAtlasTextFont : public SkRefCnt {\npublic:\n    static sk_sp<SkAtlasTextFont> Make(sk_sp<SkTypeface> typeface, SkScalar size) {\n        return sk_sp<SkAtlasTextFont>(new SkAtlasTextFont(std::move(typeface), size));\n    }\n\n    SkTypeface* typeface() const { return fTypeface.get(); }\n\n    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }\n\n    SkScalar size() const { return fSize; }\n\nprivate:\n    SkAtlasTextFont(sk_sp<SkTypeface> typeface, SkScalar size)\n            : fTypeface(std::move(typeface)), fSize(size) {}\n\n    sk_sp<SkTypeface> fTypeface;\n    SkScalar fSize;\n};\n\n#endif\n"
  },
  {
    "path": "include/atlastext/SkAtlasTextRenderer.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#include \"SkPoint3.h\"\n#include \"SkRefCnt.h\"\n\n#ifndef SkAtlasTextRenderer_DEFINED\n#define SkAtlasTextRenderer_DEFINED\n\n/**\n * This is the base class for a renderer implemented by the SkAtlasText client. The\n * SkAtlasTextContext issues texture creations, deletions, uploads, and vertex draws to the\n * renderer. The renderer must perform those actions in the order called to correctly render\n * the text drawn to SkAtlasTextTargets.\n */\nclass SK_API SkAtlasTextRenderer : public SkRefCnt {\npublic:\n    enum class AtlasFormat {\n        /** Unsigned normalized 8 bit single channel format. */\n        kA8\n    };\n\n    struct SDFVertex {\n        /** Position in device space (not normalized). The third component is w (not z). */\n        SkPoint3 fPosition;\n        /** Color, same value for all four corners of a glyph quad. */\n        uint32_t fColor;\n        /** Texture coordinate (in texel units, not normalized). */\n        int16_t fTextureCoordX;\n        int16_t fTextureCoordY;\n    };\n\n    virtual ~SkAtlasTextRenderer() = default;\n\n    /**\n     * Create a texture of the provided format with dimensions 'width' x 'height'\n     * and return a unique handle.\n     */\n    virtual void* createTexture(AtlasFormat, int width, int height) = 0;\n\n    /**\n     * Delete the texture with the passed handle.\n     */\n    virtual void deleteTexture(void* textureHandle) = 0;\n\n    /**\n     * Place the pixel data specified by 'data' in the texture with handle\n     * 'textureHandle' in the rectangle ['x', 'x' + 'width') x ['y', 'y' + 'height').\n     * 'rowBytes' specifies the byte offset between successive rows in 'data' and will always be\n     * a multiple of the number of bytes per pixel.\n     * The pixel format of data is the same as that of 'textureHandle'.\n     */\n    virtual void setTextureData(void* textureHandle, const void* data, int x, int y, int width,\n                                int height, size_t rowBytes) = 0;\n\n    /**\n     * Draws glyphs using SDFs. The SDF data resides in 'textureHandle'. The array\n     * 'vertices' provides interleaved device-space positions, colors, and\n     * texture coordinates. There are are 4 * 'quadCnt' entries in 'vertices'.\n     */\n    virtual void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],\n                               int quadCnt) = 0;\n\n    /** Called when a SkAtlasTextureTarget is destroyed. */\n    virtual void targetDeleted(void* targetHandle) = 0;\n};\n\n#endif\n"
  },
  {
    "path": "include/atlastext/SkAtlasTextTarget.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAtlasTextTarget_DEFINED\n#define SkAtlasTextTarget_DEFINED\n\n#include <memory>\n#include \"SkDeque.h\"\n#include \"SkRefCnt.h\"\n#include \"SkScalar.h\"\n\nclass SkAtlasTextContext;\nclass SkAtlasTextFont;\nclass SkMatrix;\nstruct SkPoint;\n\n/** Represents a client-created renderable surface and is used to draw text into the surface. */\nclass SK_API SkAtlasTextTarget {\npublic:\n    virtual ~SkAtlasTextTarget();\n\n    /**\n     * Creates a text drawing target. ‘handle’ is used to identify this rendering surface when\n     * draws are flushed to the SkAtlasTextContext's SkAtlasTextRenderer.\n     */\n    static std::unique_ptr<SkAtlasTextTarget> Make(sk_sp<SkAtlasTextContext>, int width, int height,\n                                                   void* handle);\n\n    /**\n     * Enqueues a text draw in the target. The caller provides an array of glyphs and their\n     * positions. The meaning of 'color' here is interpreted by the client's SkAtlasTextRenderer\n     * when it actually renders the text.\n     */\n    virtual void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,\n                          const SkAtlasTextFont&) = 0;\n\n    /** Issues all queued text draws to SkAtlasTextRenderer. */\n    virtual void flush() = 0;\n\n    int width() const { return fWidth; }\n    int height() const { return fHeight; }\n\n    void* handle() const { return fHandle; }\n\n    SkAtlasTextContext* context() const { return fContext.get(); }\n\n    /** Saves the current matrix in a stack. Returns the prior depth of the saved matrix stack. */\n    int save();\n    /** Pops the top matrix on the stack if the stack is not empty. */\n    void restore();\n    /**\n     * Pops the matrix stack until the stack depth is count. Does nothing if the depth is already\n     * less than count.\n     */\n    void restoreToCount(int count);\n\n    /** Pre-translates the current CTM. */\n    void translate(SkScalar dx, SkScalar dy);\n    /** Pre-scales the current CTM. */\n    void scale(SkScalar sx, SkScalar sy);\n    /** Pre-rotates the current CTM about the origin. */\n    void rotate(SkScalar degrees);\n    /** Pre-rotates the current CTM about the (px, py). */\n    void rotate(SkScalar degrees, SkScalar px, SkScalar py);\n    /** Pre-skews the current CTM. */\n    void skew(SkScalar sx, SkScalar sy);\n    /** Pre-concats the current CTM. */\n    void concat(const SkMatrix& matrix);\n\nprotected:\n    SkAtlasTextTarget(sk_sp<SkAtlasTextContext>, int width, int height, void* handle);\n\n    const SkMatrix& ctm() const { return *static_cast<const SkMatrix*>(fMatrixStack.back()); }\n\n    void* const fHandle;\n    const sk_sp<SkAtlasTextContext> fContext;\n    const int fWidth;\n    const int fHeight;\n\nprivate:\n    SkDeque fMatrixStack;\n    int fSaveCnt;\n\n    SkMatrix* accessCTM() const {\n        return static_cast<SkMatrix*>(const_cast<void*>(fMatrixStack.back()));\n    }\n\n    SkAtlasTextTarget() = delete;\n    SkAtlasTextTarget(const SkAtlasTextContext&) = delete;\n    SkAtlasTextTarget& operator=(const SkAtlasTextContext&) = delete;\n};\n\n#endif\n"
  },
  {
    "path": "include/c/sk_canvas.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_canvas_DEFINED\n#define sk_canvas_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Save the current matrix and clip on the canvas.  When the\n    balancing call to sk_canvas_restore() is made, the previous matrix\n    and clip are restored.\n*/\nSK_API void sk_canvas_save(sk_canvas_t*);\n/**\n    This behaves the same as sk_canvas_save(), but in addition it\n    allocates an offscreen surface. All drawing calls are directed\n    there, and only when the balancing call to sk_canvas_restore() is\n    made is that offscreen transfered to the canvas (or the previous\n    layer).\n\n    @param sk_rect_t* (may be null) This rect, if non-null, is used as\n                      a hint to limit the size of the offscreen, and\n                      thus drawing may be clipped to it, though that\n                      clipping is not guaranteed to happen. If exact\n                      clipping is desired, use sk_canvas_clip_rect().\n    @param sk_paint_t* (may be null) The paint is copied, and is applied\n                       to the offscreen when sk_canvas_restore() is\n                       called.\n*/\nSK_API void sk_canvas_save_layer(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);\n/**\n    This call balances a previous call to sk_canvas_save() or\n    sk_canvas_save_layer(), and is used to remove all modifications to\n    the matrix and clip state since the last save call.  It is an\n    error to call sk_canvas_restore() more times than save and\n    save_layer were called.\n*/\nSK_API void sk_canvas_restore(sk_canvas_t*);\n\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified translation.\n*/\nSK_API void sk_canvas_translate(sk_canvas_t*, float dx, float dy);\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified scale.\n*/\nSK_API void sk_canvas_scale(sk_canvas_t*, float sx, float sy);\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified rotation in degrees.\n*/\nSK_API void sk_canvas_rotate_degrees(sk_canvas_t*, float degrees);\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified rotation in radians.\n*/\nSK_API void sk_canvas_rotate_radians(sk_canvas_t*, float radians);\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified skew.\n*/\nSK_API void sk_canvas_skew(sk_canvas_t*, float sx, float sy);\n/**\n    Preconcat the current coordinate transformation matrix with the\n    specified matrix.\n*/\nSK_API void sk_canvas_concat(sk_canvas_t*, const sk_matrix_t*);\n\n/**\n    Modify the current clip with the specified rectangle.  The new\n    current clip will be the intersection of the old clip and the\n    rectange.\n*/\nSK_API void sk_canvas_clip_rect(sk_canvas_t*, const sk_rect_t*);\n/**\n    Modify the current clip with the specified path.  The new\n    current clip will be the intersection of the old clip and the\n    path.\n*/\nSK_API void sk_canvas_clip_path(sk_canvas_t*, const sk_path_t*);\n\n/**\n    Fill the entire canvas (restricted to the current clip) with the\n    specified paint.\n*/\nSK_API void sk_canvas_draw_paint(sk_canvas_t*, const sk_paint_t*);\n/**\n    Draw the specified rectangle using the specified paint. The\n    rectangle will be filled or stroked based on the style in the\n    paint.\n*/\nSK_API void sk_canvas_draw_rect(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);\n/**\n *  Draw the circle centered at (cx, cy) with radius rad using the specified paint.\n *  The circle will be filled or framed based on the style in the paint\n */\nSK_API void sk_canvas_draw_circle(sk_canvas_t*, float cx, float cy, float rad, const sk_paint_t*);\n/**\n    Draw the specified oval using the specified paint. The oval will be\n    filled or framed based on the style in the paint\n*/\nSK_API void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);\n/**\n    Draw the specified path using the specified paint. The path will be\n    filled or framed based on the style in the paint\n*/\nSK_API void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*);\n/**\n    Draw the specified image, with its top/left corner at (x,y), using\n    the specified paint, transformed by the current matrix.\n\n    @param sk_paint_t* (may be NULL) the paint used to draw the image.\n*/\nSK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*,\n                                 float x, float y, const sk_paint_t*);\n/**\n    Draw the specified image, scaling and translating so that it fills\n    the specified dst rect. If the src rect is non-null, only that\n    subset of the image is transformed and drawn.\n\n    @param sk_paint_t* (may be NULL) The paint used to draw the image.\n*/\nSK_API void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*,\n                                      const sk_rect_t* src,\n                                      const sk_rect_t* dst, const sk_paint_t*);\n\n/**\n    Draw the picture into this canvas (replay the pciture's drawing commands).\n\n    @param sk_matrix_t* If non-null, apply that matrix to the CTM when\n                        drawing this picture. This is logically\n                        equivalent to: save, concat, draw_picture,\n                        restore.\n\n    @param sk_paint_t* If non-null, draw the picture into a temporary\n                       buffer, and then apply the paint's alpha,\n                       colorfilter, imagefilter, and xfermode to that\n                       buffer as it is drawn to the canvas.  This is\n                       logically equivalent to save_layer(paint),\n                       draw_picture, restore.\n*/\nSK_API void sk_canvas_draw_picture(sk_canvas_t*, const sk_picture_t*,\n                                   const sk_matrix_t*, const sk_paint_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_data.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_data_DEFINED\n#define sk_data_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Returns a new empty sk_data_t.  This call must be balanced with a call to\n    sk_data_unref().\n*/\nSK_API sk_data_t* sk_data_new_empty(void);\n/**\n    Returns a new sk_data_t by copying the specified source data.\n    This call must be balanced with a call to sk_data_unref().\n*/\nSK_API sk_data_t* sk_data_new_with_copy(const void* src, size_t length);\n/**\n    Pass ownership of the given memory to a new sk_data_t, which will\n    call free() when the refernce count of the data goes to zero.  For\n    example:\n        size_t length = 1024;\n        void* buffer = malloc(length);\n        memset(buffer, 'X', length);\n        sk_data_t* data = sk_data_new_from_malloc(buffer, length);\n    This call must be balanced with a call to sk_data_unref().\n*/\nSK_API sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length);\n/**\n    Returns a new sk_data_t using a subset of the data in the\n    specified source sk_data_t.  This call must be balanced with a\n    call to sk_data_unref().\n*/\nSK_API sk_data_t* sk_data_new_subset(const sk_data_t* src, size_t offset, size_t length);\n\n/**\n    Increment the reference count on the given sk_data_t. Must be\n    balanced by a call to sk_data_unref().\n*/\nSK_API void sk_data_ref(const sk_data_t*);\n/**\n    Decrement the reference count. If the reference count is 1 before\n    the decrement, then release both the memory holding the sk_data_t\n    and the memory it is managing.  New sk_data_t are created with a\n    reference count of 1.\n*/\nSK_API void sk_data_unref(const sk_data_t*);\n\n/**\n    Returns the number of bytes stored.\n*/\nSK_API size_t sk_data_get_size(const sk_data_t*);\n/**\n    Returns the pointer to the data.\n */\nSK_API const void* sk_data_get_data(const sk_data_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_image.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_image_DEFINED\n#define sk_image_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n *  Return a new image that has made a copy of the provided pixels, or NULL on failure.\n *  Balance with a call to sk_image_unref().\n */\nSK_API sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes);\n\n/**\n *  If the specified data can be interpreted as a compressed image (e.g. PNG or JPEG) then this\n *  returns an image. If the encoded data is not supported, returns NULL.\n *\n *  On success, the encoded data may be processed immediately, or it may be ref()'d for later\n *  use.\n */\nSK_API sk_image_t* sk_image_new_from_encoded(const sk_data_t* encoded, const sk_irect_t* subset);\n\n/**\n *  Encode the image's pixels and return the result as a new PNG in a\n *  sk_data_t, which the caller must manage: call sk_data_unref() when\n *  they are done.\n *\n *  If the image type cannot be encoded, this will return NULL.\n */\nSK_API sk_data_t* sk_image_encode(const sk_image_t*);\n\n/**\n *  Increment the reference count on the given sk_image_t. Must be\n *  balanced by a call to sk_image_unref().\n*/\nSK_API void sk_image_ref(const sk_image_t*);\n/**\n *  Decrement the reference count. If the reference count is 1 before\n *  the decrement, then release both the memory holding the sk_image_t\n *  and the memory it is managing.  New sk_image_t are created with a\n    reference count of 1.\n*/\nSK_API void sk_image_unref(const sk_image_t*);\n\n/**\n *  Return the width of the sk_image_t/\n */\nSK_API int sk_image_get_width(const sk_image_t*);\n/**\n *  Return the height of the sk_image_t/\n */\nSK_API int sk_image_get_height(const sk_image_t*);\n\n/**\n *  Returns a non-zero value unique among all images.\n */\nSK_API uint32_t sk_image_get_unique_id(const sk_image_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_maskfilter.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_maskfilter_DEFINED\n#define sk_maskfilter_DEFINED\n\n#include \"sk_types.h\"\n\ntypedef enum {\n    NORMAL_SK_BLUR_STYLE,   //!< fuzzy inside and outside\n    SOLID_SK_BLUR_STYLE,    //!< solid inside, fuzzy outside\n    OUTER_SK_BLUR_STYLE,    //!< nothing inside, fuzzy outside\n    INNER_SK_BLUR_STYLE,    //!< fuzzy inside, nothing outside\n} sk_blurstyle_t;\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Increment the reference count on the given sk_maskfilter_t. Must be\n    balanced by a call to sk_maskfilter_unref().\n*/\nvoid sk_maskfilter_ref(sk_maskfilter_t*);\n/**\n    Decrement the reference count. If the reference count is 1 before\n    the decrement, then release both the memory holding the\n    sk_maskfilter_t and any other associated resources.  New\n    sk_maskfilter_t are created with a reference count of 1.\n*/\nvoid sk_maskfilter_unref(sk_maskfilter_t*);\n\n/**\n    Create a blur maskfilter.\n    @param sk_blurstyle_t The SkBlurStyle to use\n    @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.\n*/\nsk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_matrix.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_matrix_DEFINED\n#define sk_matrix_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/** Set the matrix to identity */\nvoid sk_matrix_set_identity(sk_matrix_t*);\n\n/** Set the matrix to translate by (tx, ty). */\nvoid sk_matrix_set_translate(sk_matrix_t*, float tx, float ty);\n/**\n    Preconcats the matrix with the specified translation.\n        M' = M * T(dx, dy)\n*/\nvoid sk_matrix_pre_translate(sk_matrix_t*, float tx, float ty);\n/**\n    Postconcats the matrix with the specified translation.\n        M' = T(dx, dy) * M\n*/\nvoid sk_matrix_post_translate(sk_matrix_t*, float tx, float ty);\n\n/** Set the matrix to scale by sx and sy. */\nvoid sk_matrix_set_scale(sk_matrix_t*, float sx, float sy);\n/**\n    Preconcats the matrix with the specified scale.\n        M' = M * S(sx, sy)\n*/\nvoid sk_matrix_pre_scale(sk_matrix_t*, float sx, float sy);\n/**\n    Postconcats the matrix with the specified scale.\n        M' = S(sx, sy) * M\n*/\nvoid sk_matrix_post_scale(sk_matrix_t*, float sx, float sy);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_paint.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_paint_DEFINED\n#define sk_paint_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Create a new paint with default settings:\n        antialias : false\n        stroke : false\n        stroke width : 0.0f (hairline)\n        stroke miter : 4.0f\n        stroke cap : BUTT_SK_STROKE_CAP\n        stroke join : MITER_SK_STROKE_JOIN\n        color : opaque black\n        shader : NULL\n        maskfilter : NULL\n        xfermode_mode : SRCOVER_SK_XFERMODE_MODE\n*/\nSK_API sk_paint_t* sk_paint_new(void);\n/**\n    Release the memory storing the sk_paint_t and unref() all\n    associated objects.\n*/\nSK_API void sk_paint_delete(sk_paint_t*);\n\n/**\n    Return true iff the paint has antialiasing enabled.\n*/\nSK_API bool sk_paint_is_antialias(const sk_paint_t*);\n/**\n    Set to true to enable antialiasing, false to disable it on this\n    sk_paint_t.\n*/\nSK_API void sk_paint_set_antialias(sk_paint_t*, bool);\n\n/**\n    Return the paint's curent drawing color.\n*/\nSK_API sk_color_t sk_paint_get_color(const sk_paint_t*);\n/**\n    Set the paint's curent drawing color.\n*/\nSK_API void sk_paint_set_color(sk_paint_t*, sk_color_t);\n\n/* stroke settings */\n\n/**\n    Return true iff stroking is enabled rather than filling on this\n    sk_paint_t.\n*/\nSK_API bool sk_paint_is_stroke(const sk_paint_t*);\n/**\n    Set to true to enable stroking rather than filling with this\n    sk_paint_t.\n*/\nSK_API void sk_paint_set_stroke(sk_paint_t*, bool);\n\n/**\n    Return the width for stroking.  A value of 0 strokes in hairline mode.\n */\nSK_API float sk_paint_get_stroke_width(const sk_paint_t*);\n/**\n   Set the width for stroking.  A value of 0 strokes in hairline mode\n   (always draw 1-pixel wide, regardless of the matrix).\n */\nSK_API void sk_paint_set_stroke_width(sk_paint_t*, float width);\n\n/**\n    Return the paint's stroke miter value. This is used to control the\n    behavior of miter joins when the joins angle is sharp.\n*/\nSK_API float sk_paint_get_stroke_miter(const sk_paint_t*);\n/**\n   Set the paint's stroke miter value. This is used to control the\n   behavior of miter joins when the joins angle is sharp. This value\n   must be >= 0.\n*/\nSK_API void sk_paint_set_stroke_miter(sk_paint_t*, float miter);\n\ntypedef enum {\n    BUTT_SK_STROKE_CAP,\n    ROUND_SK_STROKE_CAP,\n    SQUARE_SK_STROKE_CAP\n} sk_stroke_cap_t;\n\n/**\n    Return the paint's stroke cap type, controlling how the start and\n    end of stroked lines and paths are treated.\n*/\nSK_API sk_stroke_cap_t sk_paint_get_stroke_cap(const sk_paint_t*);\n/**\n    Set the paint's stroke cap type, controlling how the start and\n    end of stroked lines and paths are treated.\n*/\nSK_API void sk_paint_set_stroke_cap(sk_paint_t*, sk_stroke_cap_t);\n\ntypedef enum {\n    MITER_SK_STROKE_JOIN,\n    ROUND_SK_STROKE_JOIN,\n    BEVEL_SK_STROKE_JOIN\n} sk_stroke_join_t;\n\n/**\n    Return the paint's stroke join type, specifies the treatment that\n    is applied to corners in paths and rectangles\n */\nSK_API sk_stroke_join_t sk_paint_get_stroke_join(const sk_paint_t*);\n/**\n    Set the paint's stroke join type, specifies the treatment that\n    is applied to corners in paths and rectangles\n */\nSK_API void sk_paint_set_stroke_join(sk_paint_t*, sk_stroke_join_t);\n\n/**\n *  Set the paint's shader to the specified parameter. This will automatically call unref() on\n *  any previous value, and call ref() on the new value.\n */\nSK_API void sk_paint_set_shader(sk_paint_t*, sk_shader_t*);\n\n/**\n *  Set the paint's maskfilter to the specified parameter. This will automatically call unref() on\n *  any previous value, and call ref() on the new value.\n */\nSK_API void sk_paint_set_maskfilter(sk_paint_t*, sk_maskfilter_t*);\n\n/**\n *  Set the paint's xfermode to the specified parameter.\n */\nSK_API void sk_paint_set_xfermode_mode(sk_paint_t*, sk_xfermode_mode_t);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_path.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_path_DEFINED\n#define sk_path_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\ntypedef enum {\n    CW_SK_PATH_DIRECTION,\n    CCW_SK_PATH_DIRECTION,\n} sk_path_direction_t;\n\n/** Create a new, empty path. */\nSK_API sk_path_t* sk_path_new(void);\n/** Release the memory used by a sk_path_t. */\nSK_API void sk_path_delete(sk_path_t*);\n\n/** Set the beginning of the next contour to the point (x,y). */\nSK_API void sk_path_move_to(sk_path_t*, float x, float y);\n/**\n    Add a line from the last point to the specified point (x,y). If no\n    sk_path_move_to() call has been made for this contour, the first\n    point is automatically set to (0,0).\n*/\nSK_API void sk_path_line_to(sk_path_t*, float x, float y);\n/**\n    Add a quadratic bezier from the last point, approaching control\n    point (x0,y0), and ending at (x1,y1). If no sk_path_move_to() call\n    has been made for this contour, the first point is automatically\n    set to (0,0).\n*/\nSK_API void sk_path_quad_to(sk_path_t*, float x0, float y0, float x1, float y1);\n/**\n    Add a conic curve from the last point, approaching control point\n    (x0,y01), and ending at (x1,y1) with weight w.  If no\n    sk_path_move_to() call has been made for this contour, the first\n    point is automatically set to (0,0).\n*/\nSK_API void sk_path_conic_to(sk_path_t*, float x0, float y0, float x1, float y1, float w);\n/**\n    Add a cubic bezier from the last point, approaching control points\n    (x0,y0) and (x1,y1), and ending at (x2,y2). If no\n    sk_path_move_to() call has been made for this contour, the first\n    point is automatically set to (0,0).\n*/\nSK_API void sk_path_cubic_to(sk_path_t*,\n                             float x0, float y0,\n                             float x1, float y1,\n                             float x2, float y2);\n/**\n   Close the current contour. If the current point is not equal to the\n   first point of the contour, a line segment is automatically added.\n*/\nSK_API void sk_path_close(sk_path_t*);\n\n/**\n    Add a closed rectangle contour to the path.\n*/\nSK_API void sk_path_add_rect(sk_path_t*, const sk_rect_t*, sk_path_direction_t);\n/**\n    Add a closed oval contour to the path\n*/\nSK_API void sk_path_add_oval(sk_path_t*, const sk_rect_t*, sk_path_direction_t);\n\n/**\n *  If the path is empty, return false and set the rect parameter to [0, 0, 0, 0].\n *  else return true and set the rect parameter to the bounds of the control-points\n *  of the path.\n */\nSK_API bool sk_path_get_bounds(const sk_path_t*, sk_rect_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_picture.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_picture_DEFINED\n#define sk_picture_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Create a new sk_picture_recorder_t.  Its resources should be\n    released with a call to sk_picture_recorder_delete().\n*/\nsk_picture_recorder_t* sk_picture_recorder_new(void);\n/**\n    Release the memory and other resources used by this\n    sk_picture_recorder_t.\n*/\nvoid sk_picture_recorder_delete(sk_picture_recorder_t*);\n\n/**\n   Returns the canvas that records the drawing commands\n\n   @param sk_rect_t* the cull rect used when recording this\n                     picture. Any drawing the falls outside of this\n                     rect is undefined, and may be drawn or it may not.\n*/\nsk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t*, const sk_rect_t*);\n/**\n    Signal that the caller is done recording. This invalidates the\n    canvas returned by begin_recording. Ownership of the sk_picture_t\n    is passed to the caller, who must call sk_picture_unref() when\n    they are done using it.  The returned picture is immutable.\n*/\nsk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t*);\n\n/**\n    Increment the reference count on the given sk_picture_t. Must be\n    balanced by a call to sk_picture_unref().\n*/\nvoid sk_picture_ref(sk_picture_t*);\n/**\n    Decrement the reference count. If the reference count is 1 before\n    the decrement, then release both the memory holding the\n    sk_picture_t and any resouces it may be managing.  New\n    sk_picture_t are created with a reference count of 1.\n*/\nvoid sk_picture_unref(sk_picture_t*);\n\n/**\n    Returns a non-zero value unique among all pictures.\n */\nuint32_t sk_picture_get_unique_id(sk_picture_t*);\n\n/**\n    Return the cull rect specified when this picture was recorded.\n*/\nsk_rect_t sk_picture_get_bounds(sk_picture_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_shader.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_shader_DEFINED\n#define sk_shader_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\nvoid sk_shader_ref(sk_shader_t*);\nvoid sk_shader_unref(sk_shader_t*);\n\ntypedef enum {\n    CLAMP_SK_SHADER_TILEMODE,\n    REPEAT_SK_SHADER_TILEMODE,\n    MIRROR_SK_SHADER_TILEMODE,\n} sk_shader_tilemode_t;\n\n/**\n    Returns a shader that generates a linear gradient between the two\n    specified points.\n\n    @param points The start and end points for the gradient.\n    @param colors The array[count] of colors, to be distributed between\n                  the two points\n    @param colorPos May be NULL. array[count] of SkScalars, or NULL, of\n                    the relative position of each corresponding color\n                    in the colors array. If this is NULL, the the\n                    colors are distributed evenly between the start\n                    and end point.  If this is not null, the values\n                    must begin with 0, end with 1.0, and intermediate\n                    values must be strictly increasing.\n    @param colorCount Must be >=2. The number of colors (and pos if not\n                      NULL) entries.\n    @param mode The tiling mode\n*/\nsk_shader_t* sk_shader_new_linear_gradient(const sk_point_t points[2],\n                                           const sk_color_t colors[],\n                                           const float colorPos[],\n                                           int colorCount,\n                                           sk_shader_tilemode_t tileMode,\n                                           const sk_matrix_t* localMatrix);\n\n\n/**\n    Returns a shader that generates a radial gradient given the center\n    and radius.\n\n    @param center The center of the circle for this gradient\n    @param radius Must be positive. The radius of the circle for this\n                  gradient\n    @param colors The array[count] of colors, to be distributed\n                  between the center and edge of the circle\n    @param colorPos May be NULL. The array[count] of the relative\n                    position of each corresponding color in the colors\n                    array. If this is NULL, the the colors are\n                    distributed evenly between the center and edge of\n                    the circle.  If this is not null, the values must\n                    begin with 0, end with 1.0, and intermediate\n                    values must be strictly increasing.\n    @param count Must be >= 2. The number of colors (and pos if not\n                 NULL) entries\n    @param tileMode The tiling mode\n    @param localMatrix May be NULL\n*/\nsk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center,\n                                           float radius,\n                                           const sk_color_t colors[],\n                                           const float colorPos[],\n                                           int colorCount,\n                                           sk_shader_tilemode_t tileMode,\n                                           const sk_matrix_t* localMatrix);\n\n/**\n    Returns a shader that generates a sweep gradient given a center.\n\n    @param center The coordinates of the center of the sweep\n    @param colors The array[count] of colors, to be distributed around\n                  the center.\n    @param colorPos May be NULL. The array[count] of the relative\n                    position of each corresponding color in the colors\n                    array. If this is NULL, the the colors are\n                    distributed evenly between the center and edge of\n                    the circle.  If this is not null, the values must\n                    begin with 0, end with 1.0, and intermediate\n                    values must be strictly increasing.\n    @param colorCount Must be >= 2. The number of colors (and pos if\n                      not NULL) entries\n    @param localMatrix May be NULL\n*/\nsk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center,\n                                          const sk_color_t colors[],\n                                          const float colorPos[],\n                                          int colorCount,\n                                          const sk_matrix_t* localMatrix);\n\n/**\n    Returns a shader that generates a conical gradient given two circles, or\n    returns NULL if the inputs are invalid. The gradient interprets the\n    two circles according to the following HTML spec.\n    http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient\n\n    Returns a shader that generates a sweep gradient given a center.\n\n    @param start, startRadius Defines the first circle.\n    @param end, endRadius Defines the first circle.\n    @param colors The array[count] of colors, to be distributed between\n                  the two circles.\n    @param colorPos May be NULL. The array[count] of the relative\n                    position of each corresponding color in the colors\n                    array. If this is NULL, the the colors are\n                    distributed evenly between the two circles.  If\n                    this is not null, the values must begin with 0,\n                    end with 1.0, and intermediate values must be\n                    strictly increasing.\n    @param colorCount Must be >= 2. The number of colors (and pos if\n                      not NULL) entries\n    @param tileMode The tiling mode\n    @param localMatrix May be NULL\n\n*/\nsk_shader_t* sk_shader_new_two_point_conical_gradient(\n        const sk_point_t* start,\n        float startRadius,\n        const sk_point_t* end,\n        float endRadius,\n        const sk_color_t colors[],\n        const float colorPos[],\n        int colorCount,\n        sk_shader_tilemode_t tileMode,\n        const sk_matrix_t* localMatrix);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_surface.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_surface_DEFINED\n#define sk_surface_DEFINED\n\n#include \"sk_types.h\"\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\n/**\n    Return a new surface, with the memory for the pixels automatically\n    allocated.  If the requested surface cannot be created, or the\n    request is not a supported configuration, NULL will be returned.\n\n    @param sk_imageinfo_t* Specify the width, height, color type, and\n                           alpha type for the surface.\n\n    @param sk_surfaceprops_t* If not NULL, specify additional non-default\n                              properties of the surface.\n*/\nSK_API sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*, const sk_surfaceprops_t*);\n\n/**\n    Create a new surface which will draw into the specified pixels\n    with the specified rowbytes.  If the requested surface cannot be\n    created, or the request is not a supported configuration, NULL\n    will be returned.\n\n    @param sk_imageinfo_t* Specify the width, height, color type, and\n                           alpha type for the surface.\n    @param void* pixels Specify the location in memory where the\n                        destination pixels are.  This memory must\n                        outlast this surface.\n     @param size_t rowBytes Specify the difference, in bytes, between\n                           each adjacent row.  Should be at least\n                           (width * sizeof(one pixel)).\n    @param sk_surfaceprops_t* If not NULL, specify additional non-default\n                              properties of the surface.\n*/\nSK_API sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*,\n                                                  void* pixels, size_t rowBytes,\n                                                  const sk_surfaceprops_t* props);\n\n/**\n    Decrement the reference count. If the reference count is 1 before\n    the decrement, then release both the memory holding the\n    sk_surface_t and any pixel memory it may be managing.  New\n    sk_surface_t are created with a reference count of 1.\n*/\nSK_API void sk_surface_unref(sk_surface_t*);\n\n/**\n *  Return the canvas associated with this surface. Note: the canvas is owned by the surface,\n *  so the returned object is only valid while the owning surface is valid.\n */\nSK_API sk_canvas_t* sk_surface_get_canvas(sk_surface_t*);\n\n/**\n *  Call sk_image_unref() when the returned image is no longer used.\n */\nSK_API sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*);\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/c/sk_types.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL\n// DO NOT USE -- FOR INTERNAL TESTING ONLY\n\n#ifndef sk_types_DEFINED\n#define sk_types_DEFINED\n\n#include <stdint.h>\n#include <stddef.h>\n\n#ifdef __cplusplus\n    #define SK_C_PLUS_PLUS_BEGIN_GUARD    extern \"C\" {\n    #define SK_C_PLUS_PLUS_END_GUARD      }\n#else\n    #include <stdbool.h>\n    #define SK_C_PLUS_PLUS_BEGIN_GUARD\n    #define SK_C_PLUS_PLUS_END_GUARD\n#endif\n\n#if !defined(SK_API)\n    #if defined(SKIA_DLL)\n        #if defined(_MSC_VER)\n            #if SKIA_IMPLEMENTATION\n                #define SK_API __declspec(dllexport)\n            #else\n                #define SK_API __declspec(dllimport)\n            #endif\n        #else\n            #define SK_API __attribute__((visibility(\"default\")))\n        #endif\n    #else\n        #define SK_API\n    #endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////////////\n\nSK_C_PLUS_PLUS_BEGIN_GUARD\n\ntypedef uint32_t sk_color_t;\n\n/* This macro assumes all arguments are >=0 and <=255. */\n#define sk_color_set_argb(a, r, g, b)   (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))\n#define sk_color_get_a(c)               (((c) >> 24) & 0xFF)\n#define sk_color_get_r(c)               (((c) >> 16) & 0xFF)\n#define sk_color_get_g(c)               (((c) >>  8) & 0xFF)\n#define sk_color_get_b(c)               (((c) >>  0) & 0xFF)\n\ntypedef enum {\n    UNKNOWN_SK_COLORTYPE,\n    RGBA_8888_SK_COLORTYPE,\n    BGRA_8888_SK_COLORTYPE,\n    ALPHA_8_SK_COLORTYPE,\n} sk_colortype_t;\n\ntypedef enum {\n    OPAQUE_SK_ALPHATYPE,\n    PREMUL_SK_ALPHATYPE,\n    UNPREMUL_SK_ALPHATYPE,\n} sk_alphatype_t;\n\ntypedef enum {\n    INTERSECT_SK_CLIPTYPE,\n    DIFFERENCE_SK_CLIPTYPE,\n} sk_cliptype_t;\n\ntypedef enum {\n    UNKNOWN_SK_PIXELGEOMETRY,\n    RGB_H_SK_PIXELGEOMETRY,\n    BGR_H_SK_PIXELGEOMETRY,\n    RGB_V_SK_PIXELGEOMETRY,\n    BGR_V_SK_PIXELGEOMETRY,\n} sk_pixelgeometry_t;\n\n/**\n    Return the default sk_colortype_t; this is operating-system dependent.\n*/\nSK_API sk_colortype_t sk_colortype_get_default_8888(void);\n\ntypedef struct {\n    int32_t         width;\n    int32_t         height;\n    sk_colortype_t  colorType;\n    sk_alphatype_t  alphaType;\n} sk_imageinfo_t;\n\ntypedef struct {\n    sk_pixelgeometry_t pixelGeometry;\n} sk_surfaceprops_t;\n\ntypedef struct {\n    float   x;\n    float   y;\n} sk_point_t;\n\ntypedef struct {\n    int32_t left;\n    int32_t top;\n    int32_t right;\n    int32_t bottom;\n} sk_irect_t;\n\ntypedef struct {\n    float   left;\n    float   top;\n    float   right;\n    float   bottom;\n} sk_rect_t;\n\n/**\n    The sk_matrix_t struct holds a 3x3 perspective matrix for\n    transforming coordinates:\n\n        (X,Y) = T[M]((x,y))\n        X = (M[0] * x + M[1] * y + M[2]) / (M[6] * x + M[7] * y + M[8]);\n        Y = (M[3] * x + M[4] * y + M[5]) / (M[6] * x + M[7] * y + M[8]);\n\n    Therefore, the identity matrix is\n\n        sk_matrix_t identity = {{1, 0, 0,\n                                 0, 1, 0,\n                                 0, 0, 1}};\n\n    A matrix that scales by sx and sy is:\n\n        sk_matrix_t scale = {{sx, 0,  0,\n                              0,  sy, 0,\n                              0,  0,  1}};\n\n    A matrix that translates by tx and ty is:\n\n        sk_matrix_t translate = {{1, 0, tx,\n                                  0, 1, ty,\n                                  0, 0, 1}};\n\n    A matrix that rotates around the origin by A radians:\n\n        sk_matrix_t rotate = {{cos(A), -sin(A), 0,\n                               sin(A),  cos(A), 0,\n                               0,       0,      1}};\n\n    Two matrixes can be concatinated by:\n\n         void concat_matrices(sk_matrix_t* dst,\n                             const sk_matrix_t* matrixU,\n                             const sk_matrix_t* matrixV) {\n            const float* u = matrixU->mat;\n            const float* v = matrixV->mat;\n            sk_matrix_t result = {{\n                    u[0] * v[0] + u[1] * v[3] + u[2] * v[6],\n                    u[0] * v[1] + u[1] * v[4] + u[2] * v[7],\n                    u[0] * v[2] + u[1] * v[5] + u[2] * v[8],\n                    u[3] * v[0] + u[4] * v[3] + u[5] * v[6],\n                    u[3] * v[1] + u[4] * v[4] + u[5] * v[7],\n                    u[3] * v[2] + u[4] * v[5] + u[5] * v[8],\n                    u[6] * v[0] + u[7] * v[3] + u[8] * v[6],\n                    u[6] * v[1] + u[7] * v[4] + u[8] * v[7],\n                    u[6] * v[2] + u[7] * v[5] + u[8] * v[8]\n            }};\n            *dst = result;\n        }\n*/\ntypedef struct {\n    float   mat[9];\n} sk_matrix_t;\n\n/**\n    A sk_canvas_t encapsulates all of the state about drawing into a\n    destination This includes a reference to the destination itself,\n    and a stack of matrix/clip values.\n*/\ntypedef struct sk_canvas_t sk_canvas_t;\n/**\n    A sk_data_ holds an immutable data buffer.\n*/\ntypedef struct sk_data_t sk_data_t;\n/**\n    A sk_image_t is an abstraction for drawing a rectagle of pixels.\n    The content of the image is always immutable, though the actual\n    storage may change, if for example that image can be re-created via\n    encoded data or other means.\n*/\ntypedef struct sk_image_t sk_image_t;\n/**\n    A sk_maskfilter_t is an object that perform transformations on an\n    alpha-channel mask before drawing it; it may be installed into a\n    sk_paint_t.  Each time a primitive is drawn, it is first\n    scan-converted into a alpha mask, which os handed to the\n    maskfilter, which may create a new mask is to render into the\n    destination.\n */\ntypedef struct sk_maskfilter_t sk_maskfilter_t;\n/**\n    A sk_paint_t holds the style and color information about how to\n    draw geometries, text and bitmaps.\n*/\ntypedef struct sk_paint_t sk_paint_t;\n/**\n    A sk_path_t encapsulates compound (multiple contour) geometric\n    paths consisting of straight line segments, quadratic curves, and\n    cubic curves.\n*/\ntypedef struct sk_path_t sk_path_t;\n/**\n    A sk_picture_t holds recorded canvas drawing commands to be played\n    back at a later time.\n*/\ntypedef struct sk_picture_t sk_picture_t;\n/**\n    A sk_picture_recorder_t holds a sk_canvas_t that records commands\n    to create a sk_picture_t.\n*/\ntypedef struct sk_picture_recorder_t sk_picture_recorder_t;\n/**\n    A sk_shader_t specifies the source color(s) for what is being drawn. If a\n    paint has no shader, then the paint's color is used. If the paint\n    has a shader, then the shader's color(s) are use instead, but they\n    are modulated by the paint's alpha.\n*/\ntypedef struct sk_shader_t sk_shader_t;\n/**\n    A sk_surface_t holds the destination for drawing to a canvas. For\n    raster drawing, the destination is an array of pixels in memory.\n    For GPU drawing, the destination is a texture or a framebuffer.\n*/\ntypedef struct sk_surface_t sk_surface_t;\n\ntypedef enum {\n    CLEAR_SK_XFERMODE_MODE,\n    SRC_SK_XFERMODE_MODE,\n    DST_SK_XFERMODE_MODE,\n    SRCOVER_SK_XFERMODE_MODE,\n    DSTOVER_SK_XFERMODE_MODE,\n    SRCIN_SK_XFERMODE_MODE,\n    DSTIN_SK_XFERMODE_MODE,\n    SRCOUT_SK_XFERMODE_MODE,\n    DSTOUT_SK_XFERMODE_MODE,\n    SRCATOP_SK_XFERMODE_MODE,\n    DSTATOP_SK_XFERMODE_MODE,\n    XOR_SK_XFERMODE_MODE,\n    PLUS_SK_XFERMODE_MODE,\n    MODULATE_SK_XFERMODE_MODE,\n    SCREEN_SK_XFERMODE_MODE,\n    OVERLAY_SK_XFERMODE_MODE,\n    DARKEN_SK_XFERMODE_MODE,\n    LIGHTEN_SK_XFERMODE_MODE,\n    COLORDODGE_SK_XFERMODE_MODE,\n    COLORBURN_SK_XFERMODE_MODE,\n    HARDLIGHT_SK_XFERMODE_MODE,\n    SOFTLIGHT_SK_XFERMODE_MODE,\n    DIFFERENCE_SK_XFERMODE_MODE,\n    EXCLUSION_SK_XFERMODE_MODE,\n    MULTIPLY_SK_XFERMODE_MODE,\n    HUE_SK_XFERMODE_MODE,\n    SATURATION_SK_XFERMODE_MODE,\n    COLOR_SK_XFERMODE_MODE,\n    LUMINOSITY_SK_XFERMODE_MODE,\n} sk_xfermode_mode_t;\n\n//////////////////////////////////////////////////////////////////////////////////////////\n\nSK_C_PLUS_PLUS_END_GUARD\n\n#endif\n"
  },
  {
    "path": "include/codec/SkAndroidCodec.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAndroidCodec_DEFINED\n#define SkAndroidCodec_DEFINED\n\n#include \"SkCodec.h\"\n#include \"SkEncodedImageFormat.h\"\n#include \"SkStream.h\"\n#include \"SkTypes.h\"\n\n/**\n *  Abstract interface defining image codec functionality that is necessary for\n *  Android.\n */\nclass SK_API SkAndroidCodec : SkNoncopyable {\npublic:\n    enum class ExifOrientationBehavior {\n        /**\n         *  Ignore any exif orientation markers in the data.\n         *\n         *  getInfo's width and height will match the header of the image, and\n         *  no processing will be done to match the marker.\n         */\n        kIgnore,\n\n        /**\n         *  Respect the exif orientation marker.\n         *\n         *  getInfo's width and height will represent what they should be after\n         *  applying the orientation. For example, if the marker specifies a\n         *  rotation by 90 degrees, they will be swapped relative to the header.\n         *  getAndroidPixels will apply the orientation as well.\n         */\n        kRespect,\n    };\n\n    /**\n     *  Pass ownership of an SkCodec to a newly-created SkAndroidCodec.\n     */\n    static std::unique_ptr<SkAndroidCodec> MakeFromCodec(std::unique_ptr<SkCodec>,\n            ExifOrientationBehavior = ExifOrientationBehavior::kIgnore);\n\n    /**\n     *  If this stream represents an encoded image that we know how to decode,\n     *  return an SkAndroidCodec that can decode it. Otherwise return NULL.\n     *\n     *  The SkPngChunkReader handles unknown chunks in PNGs.\n     *  See SkCodec.h for more details.\n     *\n     *  If NULL is returned, the stream is deleted immediately. Otherwise, the\n     *  SkCodec takes ownership of it, and will delete it when done with it.\n     *\n     *  ExifOrientationBehavior is set to kIgnore.\n     */\n    static std::unique_ptr<SkAndroidCodec> MakeFromStream(std::unique_ptr<SkStream>,\n                                                          SkPngChunkReader* = nullptr);\n\n    /**\n     *  If this data represents an encoded image that we know how to decode,\n     *  return an SkAndroidCodec that can decode it. Otherwise return NULL.\n     *\n     *  The SkPngChunkReader handles unknown chunks in PNGs.\n     *  See SkCodec.h for more details.\n     *\n     *  ExifOrientationBehavior is set to kIgnore.\n     */\n    static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);\n\n    virtual ~SkAndroidCodec();\n\n    const SkImageInfo& getInfo() const { return fInfo; }\n\n    /**\n     *  Format of the encoded data.\n     */\n    SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }\n\n    /**\n     *  @param requestedColorType Color type requested by the client\n     *\n     *  |requestedColorType| may be overriden.  We will default to kF16\n     *  for high precision images.\n     *\n     *  In the general case, if it is possible to decode to\n     *  |requestedColorType|, this returns |requestedColorType|.\n     *  Otherwise, this returns a color type that is an appropriate\n     *  match for the the encoded data.\n     */\n    SkColorType computeOutputColorType(SkColorType requestedColorType);\n\n    /**\n     *  @param requestedUnpremul  Indicates if the client requested\n     *                            unpremultiplied output\n     *\n     *  Returns the appropriate alpha type to decode to.  If the image\n     *  has alpha, the value of requestedUnpremul will be honored.\n     */\n    SkAlphaType computeOutputAlphaType(bool requestedUnpremul);\n\n    /**\n     *  @param outputColorType Color type that the client will decode to.\n     *  @param prefColorSpace  Preferred color space to decode to.\n     *                         This may not return |prefColorSpace| for a couple reasons.\n     *                         (1) Android Principles: 565 must be sRGB, F16 must be\n     *                             linear sRGB, transfer function must be parametric.\n     *                         (2) Codec Limitations: F16 requires a linear color space.\n     *\n     *  Returns the appropriate color space to decode to.\n     */\n    sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,\n                                                sk_sp<SkColorSpace> prefColorSpace = nullptr);\n\n    /**\n     *  Compute the appropriate sample size to get to |size|.\n     *\n     *  @param size As an input parameter, the desired output size of\n     *      the decode. As an output parameter, the smallest sampled size\n     *      larger than the input.\n     *  @return the sample size to set AndroidOptions::fSampleSize to decode\n     *      to the output |size|.\n     */\n    int computeSampleSize(SkISize* size) const;\n\n    /**\n     *  Returns the dimensions of the scaled output image, for an input\n     *  sampleSize.\n     *\n     *  When the sample size divides evenly into the original dimensions, the\n     *  scaled output dimensions will simply be equal to the original\n     *  dimensions divided by the sample size.\n     *\n     *  When the sample size does not divide even into the original\n     *  dimensions, the codec may round up or down, depending on what is most\n     *  efficient to decode.\n     *\n     *  Finally, the codec will always recommend a non-zero output, so the output\n     *  dimension will always be one if the sampleSize is greater than the\n     *  original dimension.\n     */\n    SkISize getSampledDimensions(int sampleSize) const;\n\n    /**\n     *  Return (via desiredSubset) a subset which can decoded from this codec,\n     *  or false if the input subset is invalid.\n     *\n     *  @param desiredSubset in/out parameter\n     *                       As input, a desired subset of the original bounds\n     *                       (as specified by getInfo).\n     *                       As output, if true is returned, desiredSubset may\n     *                       have been modified to a subset which is\n     *                       supported. Although a particular change may have\n     *                       been made to desiredSubset to create something\n     *                       supported, it is possible other changes could\n     *                       result in a valid subset.  If false is returned,\n     *                       desiredSubset's value is undefined.\n     *  @return true         If the input desiredSubset is valid.\n     *                       desiredSubset may be modified to a subset\n     *                       supported by the codec.\n     *          false        If desiredSubset is invalid (NULL or not fully\n     *                       contained within the image).\n     */\n    bool getSupportedSubset(SkIRect* desiredSubset) const;\n    // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()\n\n    /**\n     *  Returns the dimensions of the scaled, partial output image, for an\n     *  input sampleSize and subset.\n     *\n     *  @param sampleSize Factor to scale down by.\n     *  @param subset     Must be a valid subset of the original image\n     *                    dimensions and a subset supported by SkAndroidCodec.\n     *                    getSubset() can be used to obtain a subset supported\n     *                    by SkAndroidCodec.\n     *  @return           Size of the scaled partial image.  Or zero size\n     *                    if either of the inputs is invalid.\n     */\n    SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;\n\n    /**\n     *  Additional options to pass to getAndroidPixels().\n     */\n    // FIXME: It's a bit redundant to name these AndroidOptions when this class is already\n    //        called SkAndroidCodec.  On the other hand, it's may be a bit confusing to call\n    //        these Options when SkCodec has a slightly different set of Options.  Maybe these\n    //        should be DecodeOptions or SamplingOptions?\n    struct AndroidOptions {\n        AndroidOptions()\n            : fZeroInitialized(SkCodec::kNo_ZeroInitialized)\n            , fSubset(nullptr)\n            , fSampleSize(1)\n        {}\n\n        /**\n         *  Indicates is destination pixel memory is zero initialized.\n         *\n         *  The default is SkCodec::kNo_ZeroInitialized.\n         */\n        SkCodec::ZeroInitialized fZeroInitialized;\n\n        /**\n         *  If not NULL, represents a subset of the original image to decode.\n         *\n         *  Must be within the bounds returned by getInfo().\n         *\n         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP, the top and left\n         *  values must be even.\n         *\n         *  The default is NULL, meaning a decode of the entire image.\n         */\n        SkIRect* fSubset;\n\n        /**\n         *  The client may provide an integer downscale factor for the decode.\n         *  The codec may implement this downscaling by sampling or another\n         *  method if it is more efficient.\n         *\n         *  The default is 1, representing no downscaling.\n         */\n        int fSampleSize;\n    };\n\n    /**\n     *  Decode into the given pixels, a block of memory of size at\n     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *\n     *  bytesPerPixel)\n     *\n     *  Repeated calls to this function should give the same results,\n     *  allowing the PixelRef to be immutable.\n     *\n     *  @param info A description of the format (config, size)\n     *         expected by the caller.  This can simply be identical\n     *         to the info returned by getInfo().\n     *\n     *         This contract also allows the caller to specify\n     *         different output-configs, which the implementation can\n     *         decide to support or not.\n     *\n     *         A size that does not match getInfo() implies a request\n     *         to scale or subset. If the codec cannot perform this\n     *         scaling or subsetting, it will return an error code.\n     *\n     *  The AndroidOptions object is also used to specify any requested scaling or subsetting\n     *  using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above\n     *  for AndroidOptions) are used.\n     *\n     *  @return Result kSuccess, or another value explaining the type of failure.\n     */\n    // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already\n    //        called SkAndroidCodec.  On the other hand, it's may be a bit confusing to call\n    //        this getPixels() when it is a slightly different API than SkCodec's getPixels().\n    //        Maybe this should be decode() or decodeSubset()?\n    SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,\n            const AndroidOptions* options);\n\n    /**\n     *  Simplified version of getAndroidPixels() where we supply the default AndroidOptions as\n     *  specified above for AndroidOptions. It will not perform any scaling or subsetting.\n     */\n    SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);\n\n    SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {\n        return this->getAndroidPixels(info, pixels, rowBytes);\n    }\n\n    SkCodec* codec() const { return fCodec.get(); }\n\nprotected:\n    SkAndroidCodec(SkCodec*, ExifOrientationBehavior = ExifOrientationBehavior::kIgnore);\n\n    virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;\n\n    virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;\n\n    virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,\n            size_t rowBytes, const AndroidOptions& options) = 0;\n\nprivate:\n    const SkImageInfo               fInfo;\n    const ExifOrientationBehavior   fOrientationBehavior;\n    std::unique_ptr<SkCodec>        fCodec;\n};\n#endif // SkAndroidCodec_DEFINED\n"
  },
  {
    "path": "include/codec/SkCodec.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCodec_DEFINED\n#define SkCodec_DEFINED\n\n#include \"../private/SkTemplates.h\"\n#include \"../private/SkEncodedInfo.h\"\n#include \"SkCodecAnimation.h\"\n#include \"SkColor.h\"\n#include \"SkColorSpaceXform.h\"\n#include \"SkEncodedImageFormat.h\"\n#include \"SkEncodedOrigin.h\"\n#include \"SkImageInfo.h\"\n#include \"SkPixmap.h\"\n#include \"SkSize.h\"\n#include \"SkStream.h\"\n#include \"SkTypes.h\"\n#include \"SkYUVSizeInfo.h\"\n\n#include <vector>\n\nclass SkColorSpace;\nclass SkData;\nclass SkFrameHolder;\nclass SkPngChunkReader;\nclass SkSampler;\n\nnamespace DM {\nclass CodecSrc;\nclass ColorCodecSrc;\n}\n\n/**\n *  Abstraction layer directly on top of an image codec.\n */\nclass SK_API SkCodec : SkNoncopyable {\npublic:\n    /**\n     *  Minimum number of bytes that must be buffered in SkStream input.\n     *\n     *  An SkStream passed to NewFromStream must be able to use this many\n     *  bytes to determine the image type. Then the same SkStream must be\n     *  passed to the correct decoder to read from the beginning.\n     *\n     *  This can be accomplished by implementing peek() to support peeking\n     *  this many bytes, or by implementing rewind() to be able to rewind()\n     *  after reading this many bytes.\n     */\n    static constexpr size_t MinBufferedBytesNeeded() { return 32; }\n\n    /**\n     *  Error codes for various SkCodec methods.\n     */\n    enum Result {\n        /**\n         *  General return value for success.\n         */\n        kSuccess,\n        /**\n         *  The input is incomplete. A partial image was generated.\n         */\n        kIncompleteInput,\n        /**\n         *  Like kIncompleteInput, except the input had an error.\n         *\n         *  If returned from an incremental decode, decoding cannot continue,\n         *  even with more data.\n         */\n        kErrorInInput,\n        /**\n         *  The generator cannot convert to match the request, ignoring\n         *  dimensions.\n         */\n        kInvalidConversion,\n        /**\n         *  The generator cannot scale to requested size.\n         */\n        kInvalidScale,\n        /**\n         *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes\n         *  too small, etc.\n         */\n        kInvalidParameters,\n        /**\n         *  The input did not contain a valid image.\n         */\n        kInvalidInput,\n        /**\n         *  Fulfilling this request requires rewinding the input, which is not\n         *  supported for this input.\n         */\n        kCouldNotRewind,\n        /**\n         *  An internal error, such as OOM.\n         */\n        kInternalError,\n        /**\n         *  This method is not implemented by this codec.\n         *  FIXME: Perhaps this should be kUnsupported?\n         */\n        kUnimplemented,\n    };\n\n    /**\n     *  Readable string representing the error code.\n     */\n    static const char* ResultToString(Result);\n\n    /**\n     *  If this stream represents an encoded image that we know how to decode,\n     *  return an SkCodec that can decode it. Otherwise return NULL.\n     *\n     *  As stated above, this call must be able to peek or read\n     *  MinBufferedBytesNeeded to determine the correct format, and then start\n     *  reading from the beginning. First it will attempt to peek, and it\n     *  assumes that if less than MinBufferedBytesNeeded bytes (but more than\n     *  zero) are returned, this is because the stream is shorter than this,\n     *  so falling back to reading would not provide more data. If peek()\n     *  returns zero bytes, this call will instead attempt to read(). This\n     *  will require that the stream can be rewind()ed.\n     *\n     *  If Result is not NULL, it will be set to either kSuccess if an SkCodec\n     *  is returned or a reason for the failure if NULL is returned.\n     *\n     *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if\n     *  the image is a png.\n     *\n     *  If the SkPngChunkReader is not NULL then:\n     *      If the image is not a PNG, the SkPngChunkReader will be ignored.\n     *      If the image is a PNG, the SkPngChunkReader will be reffed.\n     *      If the PNG has unknown chunks, the SkPngChunkReader will be used\n     *      to handle these chunks.  SkPngChunkReader will be called to read\n     *      any unknown chunk at any point during the creation of the codec\n     *      or the decode.  Note that if SkPngChunkReader fails to read a\n     *      chunk, this could result in a failure to create the codec or a\n     *      failure to decode the image.\n     *      If the PNG does not contain unknown chunks, the SkPngChunkReader\n     *      will not be used or modified.\n     *\n     *  If NULL is returned, the stream is deleted immediately. Otherwise, the\n     *  SkCodec takes ownership of it, and will delete it when done with it.\n     */\n    static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result* = nullptr,\n                                                   SkPngChunkReader* = nullptr);\n\n    /**\n     *  If this data represents an encoded image that we know how to decode,\n     *  return an SkCodec that can decode it. Otherwise return NULL.\n     *\n     *  If the SkPngChunkReader is not NULL then:\n     *      If the image is not a PNG, the SkPngChunkReader will be ignored.\n     *      If the image is a PNG, the SkPngChunkReader will be reffed.\n     *      If the PNG has unknown chunks, the SkPngChunkReader will be used\n     *      to handle these chunks.  SkPngChunkReader will be called to read\n     *      any unknown chunk at any point during the creation of the codec\n     *      or the decode.  Note that if SkPngChunkReader fails to read a\n     *      chunk, this could result in a failure to create the codec or a\n     *      failure to decode the image.\n     *      If the PNG does not contain unknown chunks, the SkPngChunkReader\n     *      will not be used or modified.\n     */\n    static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);\n\n    virtual ~SkCodec();\n\n    /**\n     *  Return the ImageInfo associated with this codec.\n     */\n    const SkImageInfo& getInfo() const { return fSrcInfo; }\n\n    /**\n     *  Returns the image orientation stored in the EXIF data.\n     *  If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.\n     */\n    SkEncodedOrigin getOrigin() const { return fOrigin; }\n\n    /**\n     *  Return a size that approximately supports the desired scale factor.\n     *  The codec may not be able to scale efficiently to the exact scale\n     *  factor requested, so return a size that approximates that scale.\n     *  The returned value is the codec's suggestion for the closest valid\n     *  scale that it can natively support\n     */\n    SkISize getScaledDimensions(float desiredScale) const {\n        // Negative and zero scales are errors.\n        SkASSERT(desiredScale > 0.0f);\n        if (desiredScale <= 0.0f) {\n            return SkISize::Make(0, 0);\n        }\n\n        // Upscaling is not supported. Return the original size if the client\n        // requests an upscale.\n        if (desiredScale >= 1.0f) {\n            return this->getInfo().dimensions();\n        }\n        return this->onGetScaledDimensions(desiredScale);\n    }\n\n    /**\n     *  Return (via desiredSubset) a subset which can decoded from this codec,\n     *  or false if this codec cannot decode subsets or anything similar to\n     *  desiredSubset.\n     *\n     *  @param desiredSubset In/out parameter. As input, a desired subset of\n     *      the original bounds (as specified by getInfo). If true is returned,\n     *      desiredSubset may have been modified to a subset which is\n     *      supported. Although a particular change may have been made to\n     *      desiredSubset to create something supported, it is possible other\n     *      changes could result in a valid subset.\n     *      If false is returned, desiredSubset's value is undefined.\n     *  @return true if this codec supports decoding desiredSubset (as\n     *      returned, potentially modified)\n     */\n    bool getValidSubset(SkIRect* desiredSubset) const {\n        return this->onGetValidSubset(desiredSubset);\n    }\n\n    /**\n     *  Format of the encoded data.\n     */\n    SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }\n\n    /**\n     *  Whether or not the memory passed to getPixels is zero initialized.\n     */\n    enum ZeroInitialized {\n        /**\n         *  The memory passed to getPixels is zero initialized. The SkCodec\n         *  may take advantage of this by skipping writing zeroes.\n         */\n        kYes_ZeroInitialized,\n        /**\n         *  The memory passed to getPixels has not been initialized to zero,\n         *  so the SkCodec must write all zeroes to memory.\n         *\n         *  This is the default. It will be used if no Options struct is used.\n         */\n        kNo_ZeroInitialized,\n    };\n\n    /**\n     *  Additional options to pass to getPixels.\n     */\n    struct Options {\n        Options()\n            : fZeroInitialized(kNo_ZeroInitialized)\n            , fSubset(nullptr)\n            , fFrameIndex(0)\n            , fPriorFrame(kNone)\n            , fPremulBehavior(SkTransferFunctionBehavior::kRespect)\n        {}\n\n        ZeroInitialized            fZeroInitialized;\n        /**\n         *  If not NULL, represents a subset of the original image to decode.\n         *  Must be within the bounds returned by getInfo().\n         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which\n         *  currently supports subsets), the top and left values must be even.\n         *\n         *  In getPixels and incremental decode, we will attempt to decode the\n         *  exact rectangular subset specified by fSubset.\n         *\n         *  In a scanline decode, it does not make sense to specify a subset\n         *  top or subset height, since the client already controls which rows\n         *  to get and which rows to skip.  During scanline decodes, we will\n         *  require that the subset top be zero and the subset height be equal\n         *  to the full height.  We will, however, use the values of\n         *  subset left and subset width to decode partial scanlines on calls\n         *  to getScanlines().\n         */\n        const SkIRect*             fSubset;\n\n        /**\n         *  The frame to decode.\n         *\n         *  Only meaningful for multi-frame images.\n         */\n        int                        fFrameIndex;\n\n        /**\n         *  If not kNone, the dst already contains the prior frame at this index.\n         *\n         *  Only meaningful for multi-frame images.\n         *\n         *  If fFrameIndex needs to be blended with a prior frame (as reported by\n         *  getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to\n         *  any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to\n         *  indicate that that frame is already in the dst. Options.fZeroInitialized\n         *  is ignored in this case.\n         *\n         *  If set to kNone, the codec will decode any necessary required frame(s) first.\n         */\n        int                        fPriorFrame;\n\n        /**\n         *  Indicates whether we should do a linear premultiply or a legacy premultiply.\n         *\n         *  In the case where the dst SkColorSpace is nullptr, this flag is ignored and\n         *  we will always do a legacy premultiply.\n         */\n        SkTransferFunctionBehavior fPremulBehavior;\n    };\n\n    /**\n     *  Decode into the given pixels, a block of memory of size at\n     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *\n     *  bytesPerPixel)\n     *\n     *  Repeated calls to this function should give the same results,\n     *  allowing the PixelRef to be immutable.\n     *\n     *  @param info A description of the format (config, size)\n     *         expected by the caller.  This can simply be identical\n     *         to the info returned by getInfo().\n     *\n     *         This contract also allows the caller to specify\n     *         different output-configs, which the implementation can\n     *         decide to support or not.\n     *\n     *         A size that does not match getInfo() implies a request\n     *         to scale. If the generator cannot perform this scale,\n     *         it will return kInvalidScale.\n     *\n     *         If the info contains a non-null SkColorSpace, the codec\n     *         will perform the appropriate color space transformation.\n     *         If the caller passes in the same color space that was\n     *         reported by the codec, the color space transformation is\n     *         a no-op.\n     *\n     *  If a scanline decode is in progress, scanline mode will end, requiring the client to call\n     *  startScanlineDecode() in order to return to decoding scanlines.\n     *\n     *  @return Result kSuccess, or another value explaining the type of failure.\n     */\n    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*);\n\n    /**\n     *  Simplified version of getPixels() that uses the default Options.\n     */\n    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {\n        return this->getPixels(info, pixels, rowBytes, nullptr);\n    }\n\n    Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {\n        return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);\n    }\n\n    /**\n     *  If decoding to YUV is supported, this returns true.  Otherwise, this\n     *  returns false and does not modify any of the parameters.\n     *\n     *  @param sizeInfo   Output parameter indicating the sizes and required\n     *                    allocation widths of the Y, U, and V planes.\n     *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,\n     *                    otherwise this is ignored.\n     */\n    bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {\n        if (nullptr == sizeInfo) {\n            return false;\n        }\n\n        return this->onQueryYUV8(sizeInfo, colorSpace);\n    }\n\n    /**\n     *  Returns kSuccess, or another value explaining the type of failure.\n     *  This always attempts to perform a full decode.  If the client only\n     *  wants size, it should call queryYUV8().\n     *\n     *  @param sizeInfo   Needs to exactly match the values returned by the\n     *                    query, except the WidthBytes may be larger than the\n     *                    recommendation (but not smaller).\n     *  @param planes     Memory for each of the Y, U, and V planes.\n     */\n    Result getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {\n        if (nullptr == planes || nullptr == planes[0] || nullptr == planes[1] ||\n                nullptr == planes[2]) {\n            return kInvalidInput;\n        }\n\n        if (!this->rewindIfNeeded()) {\n            return kCouldNotRewind;\n        }\n\n        return this->onGetYUV8Planes(sizeInfo, planes);\n    }\n\n    /**\n     *  Prepare for an incremental decode with the specified options.\n     *\n     *  This may require a rewind.\n     *\n     *  @param dstInfo Info of the destination. If the dimensions do not match\n     *      those of getInfo, this implies a scale.\n     *  @param dst Memory to write to. Needs to be large enough to hold the subset,\n     *      if present, or the full image as described in dstInfo.\n     *  @param options Contains decoding options, including if memory is zero\n     *      initialized and whether to decode a subset.\n     *  @return Enum representing success or reason for failure.\n     */\n    Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,\n            const Options*);\n\n    Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {\n        return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);\n    }\n\n    /**\n     *  Start/continue the incremental decode.\n     *\n     *  Not valid to call before calling startIncrementalDecode().\n     *\n     *  After the first call, should only be called again if more data has been\n     *  provided to the source SkStream.\n     *\n     *  Unlike getPixels and getScanlines, this does not do any filling. This is\n     *  left up to the caller, since they may be skipping lines or continuing the\n     *  decode later. In the latter case, they may choose to initialize all lines\n     *  first, or only initialize the remaining lines after the first call.\n     *\n     *  @param rowsDecoded Optional output variable returning the total number of\n     *      lines initialized. Only meaningful if this method returns kIncompleteInput.\n     *      Otherwise the implementation may not set it.\n     *      Note that some implementations may have initialized this many rows, but\n     *      not necessarily finished those rows (e.g. interlaced PNG). This may be\n     *      useful for determining what rows the client needs to initialize.\n     *  @return kSuccess if all lines requested in startIncrementalDecode have\n     *      been completely decoded. kIncompleteInput otherwise.\n     */\n    Result incrementalDecode(int* rowsDecoded = nullptr) {\n        if (!fStartedIncrementalDecode) {\n            return kInvalidParameters;\n        }\n        return this->onIncrementalDecode(rowsDecoded);\n    }\n\n    /**\n     * The remaining functions revolve around decoding scanlines.\n     */\n\n    /**\n     *  Prepare for a scanline decode with the specified options.\n     *\n     *  After this call, this class will be ready to decode the first scanline.\n     *\n     *  This must be called in order to call getScanlines or skipScanlines.\n     *\n     *  This may require rewinding the stream.\n     *\n     *  Not all SkCodecs support this.\n     *\n     *  @param dstInfo Info of the destination. If the dimensions do not match\n     *      those of getInfo, this implies a scale.\n     *  @param options Contains decoding options, including if memory is zero\n     *      initialized.\n     *  @return Enum representing success or reason for failure.\n     */\n    Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options);\n\n    /**\n     *  Simplified version of startScanlineDecode() that uses the default Options.\n     */\n    Result startScanlineDecode(const SkImageInfo& dstInfo) {\n        return this->startScanlineDecode(dstInfo, nullptr);\n    }\n\n    /**\n     *  Write the next countLines scanlines into dst.\n     *\n     *  Not valid to call before calling startScanlineDecode().\n     *\n     *  @param dst Must be non-null, and large enough to hold countLines\n     *      scanlines of size rowBytes.\n     *  @param countLines Number of lines to write.\n     *  @param rowBytes Number of bytes per row. Must be large enough to hold\n     *      a scanline based on the SkImageInfo used to create this object.\n     *  @return the number of lines successfully decoded.  If this value is\n     *      less than countLines, this will fill the remaining lines with a\n     *      default value.\n     */\n    int getScanlines(void* dst, int countLines, size_t rowBytes);\n\n    /**\n     *  Skip count scanlines.\n     *\n     *  Not valid to call before calling startScanlineDecode().\n     *\n     *  The default version just calls onGetScanlines and discards the dst.\n     *  NOTE: If skipped lines are the only lines with alpha, this default\n     *  will make reallyHasAlpha return true, when it could have returned\n     *  false.\n     *\n     *  @return true if the scanlines were successfully skipped\n     *          false on failure, possible reasons for failure include:\n     *              An incomplete input image stream.\n     *              Calling this function before calling startScanlineDecode().\n     *              If countLines is less than zero or so large that it moves\n     *                  the current scanline past the end of the image.\n     */\n    bool skipScanlines(int countLines);\n\n    /**\n     *  The order in which rows are output from the scanline decoder is not the\n     *  same for all variations of all image types.  This explains the possible\n     *  output row orderings.\n     */\n    enum SkScanlineOrder {\n        /*\n         * By far the most common, this indicates that the image can be decoded\n         * reliably using the scanline decoder, and that rows will be output in\n         * the logical order.\n         */\n        kTopDown_SkScanlineOrder,\n\n        /*\n         * This indicates that the scanline decoder reliably outputs rows, but\n         * they will be returned in reverse order.  If the scanline format is\n         * kBottomUp, the nextScanline() API can be used to determine the actual\n         * y-coordinate of the next output row, but the client is not forced\n         * to take advantage of this, given that it's not too tough to keep\n         * track independently.\n         *\n         * For full image decodes, it is safe to get all of the scanlines at\n         * once, since the decoder will handle inverting the rows as it\n         * decodes.\n         *\n         * For subset decodes and sampling, it is simplest to get and skip\n         * scanlines one at a time, using the nextScanline() API.  It is\n         * possible to ask for larger chunks at a time, but this should be used\n         * with caution.  As with full image decodes, the decoder will handle\n         * inverting the requested rows, but rows will still be delivered\n         * starting from the bottom of the image.\n         *\n         * Upside down bmps are an example.\n         */\n        kBottomUp_SkScanlineOrder,\n    };\n\n    /**\n     *  An enum representing the order in which scanlines will be returned by\n     *  the scanline decoder.\n     *\n     *  This is undefined before startScanlineDecode() is called.\n     */\n    SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }\n\n    /**\n     *  Returns the y-coordinate of the next row to be returned by the scanline\n     *  decoder.\n     *\n     *  This will equal fCurrScanline, except in the case of strangely\n     *  encoded image types (bottom-up bmps).\n     *\n     *  Results are undefined when not in scanline decoding mode.\n     */\n    int nextScanline() const { return this->outputScanline(fCurrScanline); }\n\n    /**\n     *  Returns the output y-coordinate of the row that corresponds to an input\n     *  y-coordinate.  The input y-coordinate represents where the scanline\n     *  is located in the encoded data.\n     *\n     *  This will equal inputScanline, except in the case of strangely\n     *  encoded image types (bottom-up bmps, interlaced gifs).\n     */\n    int outputScanline(int inputScanline) const;\n\n    /**\n     *  Return the number of frames in the image.\n     *\n     *  May require reading through the stream.\n     */\n    int getFrameCount() {\n        return this->onGetFrameCount();\n    }\n\n    // The required frame for an independent frame is marked as\n    // kNone.\n    static constexpr int kNone = -1;\n\n    /**\n     *  Information about individual frames in a multi-framed image.\n     */\n    struct FrameInfo {\n        /**\n         *  The frame that this frame needs to be blended with, or\n         *  kNone if this frame is independent.\n         *\n         *  Note that this is the *earliest* frame that can be used\n         *  for blending. Any frame from [fRequiredFrame, i) can be\n         *  used, unless its fDisposalMethod is kRestorePrevious.\n         */\n        int fRequiredFrame;\n\n        /**\n         *  Number of milliseconds to show this frame.\n         */\n        int fDuration;\n\n        /**\n         *  Whether the end marker for this frame is contained in the stream.\n         *\n         *  Note: this does not guarantee that an attempt to decode will be complete.\n         *  There could be an error in the stream.\n         */\n        bool fFullyReceived;\n\n        /**\n         *  This is conservative; it will still return non-opaque if e.g. a\n         *  color index-based frame has a color with alpha but does not use it.\n         */\n        SkAlphaType fAlphaType;\n\n        /**\n         *  How this frame should be modified before decoding the next one.\n         */\n        SkCodecAnimation::DisposalMethod fDisposalMethod;\n    };\n\n    /**\n     *  Return info about a single frame.\n     *\n     *  Only supported by multi-frame images. Does not read through the stream,\n     *  so it should be called after getFrameCount() to parse any frames that\n     *  have not already been parsed.\n     */\n    bool getFrameInfo(int index, FrameInfo* info) const {\n        if (index < 0) {\n            return false;\n        }\n        return this->onGetFrameInfo(index, info);\n    }\n\n    /**\n     *  Return info about all the frames in the image.\n     *\n     *  May require reading through the stream to determine info about the\n     *  frames (including the count).\n     *\n     *  As such, future decoding calls may require a rewind.\n     *\n     *  For single-frame images, this will return an empty vector.\n     */\n    std::vector<FrameInfo> getFrameInfo();\n\n    static constexpr int kRepetitionCountInfinite = -1;\n\n    /**\n     *  Return the number of times to repeat, if this image is animated.\n     *\n     *  May require reading the stream to find the repetition count.\n     *\n     *  As such, future decoding calls may require a rewind.\n     *\n     *  For single-frame images, this will return 0.\n     */\n    int getRepetitionCount() {\n        return this->onGetRepetitionCount();\n    }\n\nprotected:\n    const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }\n\n    using XformFormat = SkColorSpaceXform::ColorFormat;\n\n    SkCodec(int width,\n            int height,\n            const SkEncodedInfo&,\n            XformFormat srcFormat,\n            std::unique_ptr<SkStream>,\n            sk_sp<SkColorSpace>,\n            SkEncodedOrigin = kTopLeft_SkEncodedOrigin);\n\n    /**\n     *  Allows the subclass to set the recommended SkImageInfo\n     */\n    SkCodec(const SkEncodedInfo&,\n            const SkImageInfo&,\n            XformFormat srcFormat,\n            std::unique_ptr<SkStream>,\n            SkEncodedOrigin = kTopLeft_SkEncodedOrigin);\n\n    virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {\n        // By default, scaling is not supported.\n        return this->getInfo().dimensions();\n    }\n\n    // FIXME: What to do about subsets??\n    /**\n     *  Subclasses should override if they support dimensions other than the\n     *  srcInfo's.\n     */\n    virtual bool onDimensionsSupported(const SkISize&) {\n        return false;\n    }\n\n    virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;\n\n    /**\n     * @param rowsDecoded When the encoded image stream is incomplete, this function\n     *                    will return kIncompleteInput and rowsDecoded will be set to\n     *                    the number of scanlines that were successfully decoded.\n     *                    This will allow getPixels() to fill the uninitialized memory.\n     */\n    virtual Result onGetPixels(const SkImageInfo& info,\n                               void* pixels, size_t rowBytes, const Options&,\n                               int* rowsDecoded) = 0;\n\n    virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const {\n        return false;\n    }\n\n    virtual Result onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) {\n        return kUnimplemented;\n    }\n\n    virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {\n        // By default, subsets are not supported.\n        return false;\n    }\n\n    /**\n     *  If the stream was previously read, attempt to rewind.\n     *\n     *  If the stream needed to be rewound, call onRewind.\n     *  @returns true if the codec is at the right position and can be used.\n     *      false if there was a failure to rewind.\n     *\n     *  This is called by getPixels() and start(). Subclasses may call if they\n     *  need to rewind at another time.\n     */\n    bool SK_WARN_UNUSED_RESULT rewindIfNeeded();\n\n    /**\n     *  Called by rewindIfNeeded, if the stream needed to be rewound.\n     *\n     *  Subclasses should do any set up needed after a rewind.\n     */\n    virtual bool onRewind() {\n        return true;\n    }\n\n    /**\n     * On an incomplete input, getPixels() and getScanlines() will fill any uninitialized\n     * scanlines.  This allows the subclass to indicate what value to fill with.\n     *\n     * @param dstInfo   Describes the destination.\n     * @return          The value with which to fill uninitialized pixels.\n     *\n     * Note that we can interpret the return value as a 64-bit Float16 color, a SkPMColor,\n     * a 16-bit 565 color, an 8-bit gray color, or an 8-bit index into a color table,\n     * depending on the color type.\n     */\n    uint64_t getFillValue(const SkImageInfo& dstInfo) const {\n        return this->onGetFillValue(dstInfo);\n    }\n\n    /**\n     * Some subclasses will override this function, but this is a useful default for the color\n     * types that we support.  Note that for color types that do not use the full 64-bits,\n     * we will simply take the low bits of the fill value.\n     *\n     * The defaults are:\n     * kRGBA_F16_SkColorType: Transparent or Black, depending on the src alpha type\n     * kN32_SkColorType: Transparent or Black, depending on the src alpha type\n     * kRGB_565_SkColorType: Black\n     * kGray_8_SkColorType: Black\n     */\n    virtual uint64_t onGetFillValue(const SkImageInfo& dstInfo) const;\n\n    /**\n     * Get method for the input stream\n     */\n    SkStream* stream() {\n        return fStream.get();\n    }\n\n    /**\n     *  The remaining functions revolve around decoding scanlines.\n     */\n\n    /**\n     *  Most images types will be kTopDown and will not need to override this function.\n     */\n    virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }\n\n    const SkImageInfo& dstInfo() const { return fDstInfo; }\n\n    const Options& options() const { return fOptions; }\n\n    /**\n     *  Returns the number of scanlines that have been decoded so far.\n     *  This is unaffected by the SkScanlineOrder.\n     *\n     *  Returns -1 if we have not started a scanline decode.\n     */\n    int currScanline() const { return fCurrScanline; }\n\n    virtual int onOutputScanline(int inputScanline) const;\n\n    bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha,\n                              SkTransferFunctionBehavior premulBehavior);\n    // Some classes never need a colorXform e.g.\n    // - ICO uses its embedded codec's colorXform\n    // - WBMP is just Black/White\n    virtual bool usesColorXform() const { return true; }\n    void applyColorXform(void* dst, const void* src, int count, SkAlphaType) const;\n    void applyColorXform(void* dst, const void* src, int count) const;\n\n    SkColorSpaceXform* colorXform() const { return fColorXform.get(); }\n    bool xformOnDecode() const { return fXformOnDecode; }\n\n    virtual int onGetFrameCount() {\n        return 1;\n    }\n\n    virtual bool onGetFrameInfo(int, FrameInfo*) const {\n        return false;\n    }\n\n    virtual int onGetRepetitionCount() {\n        return 0;\n    }\n\nprivate:\n    const SkEncodedInfo                fEncodedInfo;\n    const SkImageInfo                  fSrcInfo;\n    const XformFormat                  fSrcXformFormat;\n    std::unique_ptr<SkStream>          fStream;\n    bool                               fNeedsRewind;\n    const SkEncodedOrigin              fOrigin;\n\n    SkImageInfo                        fDstInfo;\n    Options                            fOptions;\n    XformFormat                        fDstXformFormat; // Based on fDstInfo.\n    std::unique_ptr<SkColorSpaceXform> fColorXform;\n    bool                               fXformOnDecode;\n\n    // Only meaningful during scanline decodes.\n    int                                fCurrScanline;\n\n    bool                               fStartedIncrementalDecode;\n\n    /**\n     *  Return whether {srcColor, srcIsOpaque, srcCS} can convert to dst.\n     *\n     *  Will be called for the appropriate frame, prior to initializing the colorXform.\n     */\n    virtual bool conversionSupported(const SkImageInfo& dst, SkColorType srcColor,\n                                     bool srcIsOpaque, const SkColorSpace* srcCS) const;\n    /**\n     *  Return whether these dimensions are supported as a scale.\n     *\n     *  The codec may choose to cache the information about scale and subset.\n     *  Either way, the same information will be passed to onGetPixels/onStart\n     *  on success.\n     *\n     *  This must return true for a size returned from getScaledDimensions.\n     */\n    bool dimensionsSupported(const SkISize& dim) {\n        return dim == fSrcInfo.dimensions() || this->onDimensionsSupported(dim);\n    }\n\n    /**\n     *  For multi-framed images, return the object with information about the frames.\n     */\n    virtual const SkFrameHolder* getFrameHolder() const {\n        return nullptr;\n    }\n\n    /**\n     *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.\n     */\n    Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&);\n\n    // Methods for scanline decoding.\n    virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,\n            const Options& /*options*/) {\n        return kUnimplemented;\n    }\n\n    virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,\n            const Options&) {\n        return kUnimplemented;\n    }\n\n    virtual Result onIncrementalDecode(int*) {\n        return kUnimplemented;\n    }\n\n\n    virtual bool onSkipScanlines(int /*countLines*/) { return false; }\n\n    virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }\n\n    /**\n     * On an incomplete decode, getPixels() and getScanlines() will call this function\n     * to fill any uinitialized memory.\n     *\n     * @param dstInfo        Contains the destination color type\n     *                       Contains the destination alpha type\n     *                       Contains the destination width\n     *                       The height stored in this info is unused\n     * @param dst            Pointer to the start of destination pixel memory\n     * @param rowBytes       Stride length in destination pixel memory\n     * @param zeroInit       Indicates if memory is zero initialized\n     * @param linesRequested Number of lines that the client requested\n     * @param linesDecoded   Number of lines that were successfully decoded\n     */\n    void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,\n            ZeroInitialized zeroInit, int linesRequested, int linesDecoded);\n\n    /**\n     *  Return an object which will allow forcing scanline decodes to sample in X.\n     *\n     *  May create a sampler, if one is not currently being used. Otherwise, does\n     *  not affect ownership.\n     *\n     *  Only valid during scanline decoding or incremental decoding.\n     */\n    virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }\n\n    friend class DM::CodecSrc;  // for fillIncompleteImage\n    friend class SkSampledCodec;\n    friend class SkIcoCodec;\n    friend class SkAndroidCodec; // for fEncodedInfo\n};\n#endif // SkCodec_DEFINED\n"
  },
  {
    "path": "include/codec/SkCodecAnimation.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCodecAnimation_DEFINED\n#define SkCodecAnimation_DEFINED\n\nnamespace SkCodecAnimation {\n    /**\n     *  This specifies how the next frame is based on this frame.\n     *\n     *  Names are based on the GIF 89a spec.\n     *\n     *  The numbers correspond to values in a GIF.\n     */\n    enum class DisposalMethod {\n        /**\n         *  The next frame should be drawn on top of this one.\n         *\n         *  In a GIF, a value of 0 (not specified) is also treated as Keep.\n         */\n        kKeep               = 1,\n\n        /**\n         *  Similar to Keep, except the area inside this frame's rectangle\n         *  should be cleared to the BackGround color (transparent) before\n         *  drawing the next frame.\n         */\n        kRestoreBGColor     = 2,\n\n        /**\n         *  The next frame should be drawn on top of the previous frame - i.e.\n         *  disregarding this one.\n         *\n         *  In a GIF, a value of 4 is also treated as RestorePrevious.\n         */\n        kRestorePrevious    = 3,\n    };\n};\n#endif // SkCodecAnimation_DEFINED\n"
  },
  {
    "path": "include/codec/SkEncodedOrigin.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEncodedOrigin_DEFINED\n#define SkEncodedOrigin_DEFINED\n// These values match the orientation www.exif.org/Exif2-2.PDF.\nenum SkEncodedOrigin {\n    kTopLeft_SkEncodedOrigin     = 1, // Default\n    kTopRight_SkEncodedOrigin    = 2, // Reflected across y-axis\n    kBottomRight_SkEncodedOrigin = 3, // Rotated 180\n    kBottomLeft_SkEncodedOrigin  = 4, // Reflected across x-axis\n    kLeftTop_SkEncodedOrigin     = 5, // Reflected across x-axis, Rotated 90 CCW\n    kRightTop_SkEncodedOrigin    = 6, // Rotated 90 CW\n    kRightBottom_SkEncodedOrigin = 7, // Reflected across x-axis, Rotated 90 CW\n    kLeftBottom_SkEncodedOrigin  = 8, // Rotated 90 CCW\n    kDefault_SkEncodedOrigin     = kTopLeft_SkEncodedOrigin,\n    kLast_SkEncodedOrigin        = kLeftBottom_SkEncodedOrigin,\n};\n#endif // SkEncodedOrigin_DEFINED\n"
  },
  {
    "path": "include/config/SkUserConfig.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkUserConfig_DEFINED\n#define SkUserConfig_DEFINED\n\n/*  SkTypes.h, the root of the public header files, does the following trick:\n\n    #include \"SkPreConfig.h\"\n    #include \"SkUserConfig.h\"\n    #include \"SkPostConfig.h\"\n\n    SkPreConfig.h runs first, and it is responsible for initializing certain\n    skia defines.\n\n    SkPostConfig.h runs last, and its job is to just check that the final\n    defines are consistent (i.e. that we don't have mutually conflicting\n    defines).\n\n    SkUserConfig.h (this file) runs in the middle. It gets to change or augment\n    the list of flags initially set in preconfig, and then postconfig checks\n    that everything still makes sense.\n\n    Below are optional defines that add, subtract, or change default behavior\n    in Skia. Your port can locally edit this file to enable/disable flags as\n    you choose, or these can be delared on your command line (i.e. -Dfoo).\n\n    By default, this include file will always default to having all of the flags\n    commented out, so including it will have no effect.\n*/\n\n///////////////////////////////////////////////////////////////////////////////\n\n/*  Skia has lots of debug-only code. Often this is just null checks or other\n    parameter checking, but sometimes it can be quite intrusive (e.g. check that\n    each 32bit pixel is in premultiplied form). This code can be very useful\n    during development, but will slow things down in a shipping product.\n\n    By default, these mutually exclusive flags are defined in SkPreConfig.h,\n    based on the presence or absence of NDEBUG, but that decision can be changed\n    here.\n */\n//#define SK_DEBUG\n//#define SK_RELEASE\n\n/*  Skia has certain debug-only code that is extremely intensive even for debug\n    builds.  This code is useful for diagnosing specific issues, but is not\n    generally applicable, therefore it must be explicitly enabled to avoid\n    the performance impact. By default these flags are undefined, but can be\n    enabled by uncommenting them below.\n */\n//#define SK_DEBUG_GLYPH_CACHE\n//#define SK_DEBUG_PATH\n\n/*  preconfig will have attempted to determine the endianness of the system,\n    but you can change these mutually exclusive flags here.\n */\n//#define SK_CPU_BENDIAN\n//#define SK_CPU_LENDIAN\n\n/*  Most compilers use the same bit endianness for bit flags in a byte as the\n    system byte endianness, and this is the default. If for some reason this\n    needs to be overridden, specify which of the mutually exclusive flags to\n    use. For example, some atom processors in certain configurations have big\n    endian byte order but little endian bit orders.\n*/\n//#define SK_UINT8_BITFIELD_BENDIAN\n//#define SK_UINT8_BITFIELD_LENDIAN\n\n\n/*  To write debug messages to a console, skia will call SkDebugf(...) following\n    printf conventions (e.g. const char* format, ...). If you want to redirect\n    this to something other than printf, define yours here\n */\n//#define SkDebugf(...)  MyFunction(__VA_ARGS__)\n\n/*\n *  To specify a different default font cache limit, define this. If this is\n *  undefined, skia will use a built-in value.\n */\n//#define SK_DEFAULT_FONT_CACHE_LIMIT   (1024 * 1024)\n\n/*\n *  To specify the default size of the image cache, undefine this and set it to\n *  the desired value (in bytes). SkGraphics.h as a runtime API to set this\n *  value as well. If this is undefined, a built-in value will be used.\n */\n//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)\n\n/*  Define this to set the upper limit for text to support LCD. Values that\n    are very large increase the cost in the font cache and draw slower, without\n    improving readability. If this is undefined, Skia will use its default\n    value (e.g. 48)\n */\n//#define SK_MAX_SIZE_FOR_LCDTEXT     48\n\n/*  If SK_DEBUG is defined, then you can optionally define SK_SUPPORT_UNITTEST\n    which will run additional self-tests at startup. These can take a long time,\n    so this flag is optional.\n */\n#ifdef SK_DEBUG\n//#define SK_SUPPORT_UNITTEST\n#endif\n\n/*  Change the ordering to work in X windows.\n */\n#ifdef SK_SAMPLES_FOR_X\n        #define SK_R32_SHIFT    16\n        #define SK_G32_SHIFT    8\n        #define SK_B32_SHIFT    0\n        #define SK_A32_SHIFT    24\n#endif\n\n\n/* Determines whether to build code that supports the GPU backend. Some classes\n   that are not GPU-specific, such as SkShader subclasses, have optional code\n   that is used allows them to interact with the GPU backend. If you'd like to\n   omit this code set SK_SUPPORT_GPU to 0. This also allows you to omit the gpu\n   directories from your include search path when you're not building the GPU\n   backend. Defaults to 1 (build the GPU code).\n */\n//#define SK_SUPPORT_GPU 1\n\n/* Skia makes use of histogram logging macros to trace the frequency of\n * events. By default, Skia provides no-op versions of these macros.\n * Skia consumers can provide their own definitions of these macros to\n * integrate with their histogram collection backend.\n */\n//#define SK_HISTOGRAM_BOOLEAN(name, value)\n//#define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)\n\n#endif\n"
  },
  {
    "path": "include/core/SkAnnotation.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAnnotation_DEFINED\n#define SkAnnotation_DEFINED\n\n#include \"SkTypes.h\"\n\nclass SkData;\nstruct SkPoint;\nstruct SkRect;\nclass SkCanvas;\n\n/**\n *  Annotate the canvas by associating the specified URL with the\n *  specified rectangle (in local coordinates, just like drawRect).\n *\n *  If the backend of this canvas does not support annotations, this call is\n *  safely ignored.\n *\n *  The caller is responsible for managing its ownership of the SkData.\n */\nSK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);\n\n/**\n *  Annotate the canvas by associating a name with the specified point.\n *\n *  If the backend of this canvas does not support annotations, this call is\n *  safely ignored.\n *\n *  The caller is responsible for managing its ownership of the SkData.\n */\nSK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*);\n\n/**\n *  Annotate the canvas by making the specified rectangle link to a named\n *  destination.\n *\n *  If the backend of this canvas does not support annotations, this call is\n *  safely ignored.\n *\n *  The caller is responsible for managing its ownership of the SkData.\n */\nSK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*);\n\n#endif\n"
  },
  {
    "path": "include/core/SkBBHFactory.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBBHFactory_DEFINED\n#define SkBBHFactory_DEFINED\n\n#include \"SkTypes.h\"\nclass SkBBoxHierarchy;\nstruct SkRect;\n\nclass SK_API SkBBHFactory {\npublic:\n    /**\n     *  Allocate a new SkBBoxHierarchy. Return NULL on failure.\n     */\n    virtual SkBBoxHierarchy* operator()(const SkRect& bounds) const = 0;\n    virtual ~SkBBHFactory() {}\n};\n\nclass SK_API SkRTreeFactory : public SkBBHFactory {\npublic:\n    SkBBoxHierarchy* operator()(const SkRect& bounds) const override;\nprivate:\n    typedef SkBBHFactory INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkBitmap.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBitmap_DEFINED\n#define SkBitmap_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkImageInfo.h\"\n#include \"SkPixmap.h\"\n#include \"SkPoint.h\"\n#include \"SkRefCnt.h\"\n\nstruct SkMask;\nstruct SkIRect;\nstruct SkRect;\nclass SkPaint;\nclass SkPixelRef;\nclass SkString;\n\n/** \\class SkBitmap\n    SkBitmap describes a two-dimensional raster pixel array. SkBitmap is built on\n    SkImageInfo, containing integer width and height, SkColorType and SkAlphaType\n    describing the pixel format, and SkColorSpace describing the range of colors.\n    SkBitmap points to SkPixelRef, which describes the physical array of pixels.\n    SkImageInfo bounds may be located anywhere fully inside SkPixelRef bounds.\n\n    SkBitmap can be drawn using SkCanvas. SkBitmap can be a drawing destination for SkCanvas\n    draw member functions. SkBitmap flexibility as a pixel container limits some\n    optimizations available to the target platform.\n\n    If pixel array is primarily read-only, use SkImage for better performance.\n    If pixel array is primarily written to, use SkSurface for better performance.\n\n    Declaring SkBitmap const prevents altering SkImageInfo: the SkBitmap height, width,\n    and so on cannot change. It does not affect SkPixelRef: a caller may write its\n    pixels. Declaring SkBitmap const affects SkBitmap configuration, not its contents.\n\n    SkBitmap is not thread safe. Each thread must have its own copy of SkBitmap fields,\n    although threads may share the underlying pixel array.\n*/\nclass SK_API SkBitmap {\npublic:\n    class SK_API Allocator;\n\n    /** Creates an empty SkBitmap without pixels, with kUnknown_SkColorType,\n        kUnknown_SkAlphaType, and with a width and height of zero. SkPixelRef origin is\n        set to (0, 0). SkBitmap is not volatile.\n\n        Use setInfo() to associate SkColorType, SkAlphaType, width, and height\n        after SkBitmap has been created.\n\n        @return  empty SkBitmap\n    */\n    SkBitmap();\n\n    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels\n        allocated, so both bitmaps reference the same pixels.\n\n        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef\n        @return     copy of src\n    */\n    SkBitmap(const SkBitmap& src);\n\n    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to\n        SkBitmap.\n\n        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef\n        @return     copy of src\n    */\n    SkBitmap(SkBitmap&& src);\n\n    /** Decrements SkPixelRef reference count, if SkPixelRef is not nullptr.\n    */\n    ~SkBitmap();\n\n    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels\n        allocated, so both bitmaps reference the same pixels.\n\n        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef\n        @return     copy of src\n    */\n    SkBitmap& operator=(const SkBitmap& src);\n\n    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to\n        SkBitmap.\n\n        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef\n        @return     copy of src\n    */\n    SkBitmap& operator=(SkBitmap&& src);\n\n    /** Swaps the fields of the two bitmaps.\n\n        @param other  SkBitmap exchanged with original\n    */\n    void swap(SkBitmap& other);\n\n    /** Returns a constant reference to the SkPixmap holding the SkBitmap pixel\n        address, row bytes, and SkImageInfo.\n\n        @return  reference to SkPixmap describing this SkBitmap\n    */\n    const SkPixmap& pixmap() const { return fPixmap; }\n\n    /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.\n\n        @return  reference to SkImageInfo\n    */\n    const SkImageInfo& info() const { return fPixmap.info(); }\n\n    /** Returns pixel count in each row. Should be equal or less than:\n        rowBytes() / info().bytesPerPixel().\n\n        Maybe be less than pixelRef().width(). Will not exceed pixelRef().width() less\n        pixelRefOrigin().fX.\n\n        @return  pixel width in SkImageInfo\n    */\n    int width() const { return fPixmap.width(); }\n\n    /** Returns pixel row count.\n\n        Maybe be less than pixelRef().height(). Will not exceed pixelRef().height() less\n        pixelRefOrigin().fY.\n\n        @return  pixel height in SkImageInfo\n    */\n    int height() const { return fPixmap.height(); }\n\n    /** Returns SkColorType, one of:\n        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n        kGray_8_SkColorType, kRGBA_F16_SkColorType.\n\n        @return  SkColorType in SkImageInfo\n    */\n    SkColorType colorType() const { return fPixmap.colorType(); }\n\n    /** Returns SkAlphaType, one of:\n        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n        kUnpremul_SkAlphaType.\n\n        @return  SkAlphaType in SkImageInfo\n    */\n    SkAlphaType alphaType() const { return fPixmap.alphaType(); }\n\n    /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The\n        reference count of SkColorSpace is unchanged. The returned SkColorSpace is\n        immutable.\n\n        @return  SkColorSpace in SkImageInfo, or nullptr\n    */\n    SkColorSpace* colorSpace() const { return fPixmap.colorSpace(); }\n\n    /** Returns smart pointer to SkColorSpace, the range of colors, associated with\n        SkImageInfo. The smart pointer tracks the number of objects sharing this\n        SkColorSpace reference so the memory is released when the owners destruct.\n\n        The returned SkColorSpace is immutable.\n\n        @return  SkColorSpace in SkImageInfo wrapped in a smart pointer\n    */\n    sk_sp<SkColorSpace> refColorSpace() const { return fPixmap.info().refColorSpace(); }\n\n    /** Returns number of bytes per pixel required by SkColorType.\n        Returns zero if colorType( is kUnknown_SkColorType.\n\n        @return  bytes in pixel\n    */\n    int bytesPerPixel() const { return fPixmap.info().bytesPerPixel(); }\n\n    /** Returns number of pixels that fit on row. Should be greater than or equal to\n        width().\n\n        @return  maximum pixels per row\n    */\n    int rowBytesAsPixels() const { return fPixmap.rowBytesAsPixels(); }\n\n    /** Returns bit shift converting row bytes to row pixels.\n        Returns zero for kUnknown_SkColorType.\n\n        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes\n    */\n    int shiftPerPixel() const { return fPixmap.shiftPerPixel(); }\n\n    /** Returns true if either width() or height() are zero.\n\n        Does not check if SkPixelRef is nullptr; call drawsNothing() to check width(),\n        height(), and SkPixelRef.\n\n        @return  true if dimensions do not enclose area\n    */\n    bool empty() const { return fPixmap.info().isEmpty(); }\n\n    /** Return true if SkPixelRef is nullptr.\n\n        Does not check if width() or height() are zero; call drawsNothing() to check\n        width(), height(), and SkPixelRef.\n\n        @return  true if no SkPixelRef is associated\n    */\n    bool isNull() const { return nullptr == fPixelRef; }\n\n    /** Return true if width() or height() are zero, or if SkPixelRef is nullptr.\n        If true, SkBitmap has no effect when drawn or drawn into.\n\n        @return  true if drawing has no effect\n    */\n    bool drawsNothing() const {\n        return this->empty() || this->isNull();\n    }\n\n    /** Returns row bytes, the interval from one pixel row to the next. Row bytes\n        is at least as large as width() * info().bytesPerPixel().\n\n        Returns zero if colorType() is kUnknown_SkColorType, or if row bytes supplied to\n        setInfo() is not large enough to hold a row of pixels.\n\n        @return  byte length of pixel row\n    */\n    size_t rowBytes() const { return fPixmap.rowBytes(); }\n\n    /** Sets SkAlphaType, if alphaType is compatible with SkColorType.\n        Returns true unless alphaType is kUnknown_SkAlphaType and current SkAlphaType\n        is not kUnknown_SkAlphaType.\n\n        Returns true if SkColorType is kUnknown_SkColorType. alphaType is ignored, and\n        SkAlphaType remains kUnknown_SkAlphaType.\n\n        Returns true if SkColorType is kRGB_565_SkColorType or kGray_8_SkColorType.\n        alphaType is ignored, and SkAlphaType remains kOpaque_SkAlphaType.\n\n        If SkColorType is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,\n        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: returns true unless\n        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.\n        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored.\n\n        If SkColorType is kAlpha_8_SkColorType, returns true unless\n        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.\n        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored. If alphaType is\n        kUnpremul_SkAlphaType, it is treated as kPremul_SkAlphaType.\n\n        This changes SkAlphaType in SkPixelRef; all bitmaps sharing SkPixelRef\n        are affected.\n\n        @param alphaType  one of:\n                          kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                          kUnpremul_SkAlphaType\n        @return           true if SkAlphaType is set\n    */\n    bool setAlphaType(SkAlphaType alphaType);\n\n    /** Returns pixel address, the base address corresponding to the pixel origin.\n\n        @return  pixel address\n    */\n    void* getPixels() const { return fPixmap.writable_addr(); }\n\n    /** Returns minimum memory required for pixel storage.\n        Does not include unused memory on last row when rowBytesAsPixels() exceeds width().\n        Returns zero if result does not fit in size_t.\n        Returns zero if height() or width() is 0.\n        Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.\n\n        @return  size in bytes of image buffer\n    */\n    size_t computeByteSize() const { return fPixmap.computeByteSize(); }\n\n    /** Returns true if pixels can not change.\n\n        Most immutable SkBitmap checks trigger an assert only on debug builds.\n\n        @return  true if pixels are immutable\n    */\n    bool isImmutable() const;\n\n    /** Sets internal flag to mark SkBitmap as immutable. Once set, pixels can not change.\n        Any other bitmap sharing the same SkPixelRef are also marked as immutable.\n        Once SkPixelRef is marked immutable, the setting cannot be cleared.\n\n        Writing to immutable SkBitmap pixels triggers an assert on debug builds.\n    */\n    void setImmutable();\n\n    /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their\n        alpha value is implicitly or explicitly 1.0. If true, and all pixels are\n        not opaque, Skia may draw incorrectly.\n\n        Does not check if SkColorType allows alpha, or if any pixel value has\n        transparency.\n\n        @return  true if SkImageInfo SkAlphaType is kOpaque_SkAlphaType\n    */\n    bool isOpaque() const {\n        return SkAlphaTypeIsOpaque(this->alphaType());\n    }\n\n    /** If true, provides a hint to caller that pixels should not\n        be cached. Only true if setIsVolatile() has been called to mark as volatile.\n\n        Volatile state is not shared by other bitmaps sharing the same SkPixelRef.\n\n        @return  true if marked volatile\n    */\n    bool isVolatile() const;\n\n    /** Sets if pixels should be read from SkPixelRef on every access. SkBitmap are not\n        volatile by default; a GPU back end may upload pixel values expecting them to be\n        accessed repeatedly. Marking temporary SkBitmap as volatile provides a hint to\n        SkBaseDevice that the SkBitmap pixels should not be cached. This can\n        improve performance by avoiding overhead and reducing resource\n        consumption on SkBaseDevice.\n\n        @param isVolatile  true if backing pixels are temporary\n    */\n    void setIsVolatile(bool isVolatile);\n\n    /** Resets to its initial state; all fields are set to zero, as if SkBitmap had\n        been initialized by SkBitmap().\n\n        Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to\n        kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.\n\n        If SkPixelRef is allocated, its reference count is decreased by one, releasing\n        its memory if SkBitmap is the sole owner.\n    */\n    void reset();\n\n    /** Returns true if all pixels are opaque. SkColorType determines how pixels\n        are encoded, and whether pixel describes alpha. Returns true for SkColorType\n        without alpha in each pixel; for other SkColorType, returns true if all\n        pixels have alpha values equivalent to 1.0 or greater.\n\n        For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always\n        returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,\n        kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.\n        For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.\n        For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or\n        greater.\n\n        Returns false for kUnknown_SkColorType.\n\n        @param bm  SkBitmap to check\n        @return    true if all pixels have opaque values or SkColorType is opaque\n    */\n    static bool ComputeIsOpaque(const SkBitmap& bm) {\n        return bm.pixmap().computeIsOpaque();\n    }\n\n    /** Returns SkRect { 0, 0, width(), height() }.\n\n        @param bounds  container for floating point rectangle\n    */\n    void getBounds(SkRect* bounds) const;\n\n    /** Returns SkIRect { 0, 0, width(), height() }.\n\n        @param bounds  container for integral rectangle\n    */\n    void getBounds(SkIRect* bounds) const;\n\n    /** Returns SkIRect { 0, 0, width(), height() }.\n\n        @return  integral rectangle from origin to width() and height()\n    */\n    SkIRect bounds() const { return fPixmap.info().bounds(); }\n\n    /** Returns SkISize { width(), height() }.\n\n        @return  integral size of width() and height()\n    */\n    SkISize dimensions() const { return fPixmap.info().dimensions(); }\n\n    /** Returns the bounds of this bitmap, offset by its SkPixelRef origin.\n\n        @return  bounds within SkPixelRef bounds\n    */\n    SkIRect getSubset() const {\n        SkIPoint origin = this->pixelRefOrigin();\n        return SkIRect::MakeXYWH(origin.x(), origin.y(), this->width(), this->height());\n    }\n\n    /** Sets width, height, SkAlphaType, SkColorType, SkColorSpace, and optional\n        rowBytes. Frees pixels, and returns true if successful.\n\n        imageInfo.alphaType() may be altered to a value permitted by imageInfo.colorSpace().\n        If imageInfo.colorType() is kUnknown_SkColorType, imageInfo.alphaType() is\n        set to kUnknown_SkAlphaType.\n        If imageInfo.colorType() is kAlpha_8_SkColorType and imageInfo.alphaType() is\n        kUnpremul_SkAlphaType, imageInfo.alphaType() is replaced by kPremul_SkAlphaType.\n        If imageInfo.colorType() is kRGB_565_SkColorType or kGray_8_SkColorType,\n        imageInfo.alphaType() is set to kOpaque_SkAlphaType.\n        If imageInfo.colorType() is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,\n        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: imageInfo.alphaType() remains\n        unchanged.\n\n        rowBytes must equal or exceed imageInfo.minRowBytes(). If imageInfo.colorSpace() is\n        kUnknown_SkColorType, rowBytes is ignored and treated as zero; for all other\n        SkColorSpace values, rowBytes of zero is treated as imageInfo.minRowBytes().\n\n        Calls reset() and returns false if:\n        - rowBytes exceeds 31 bits\n        - imageInfo.width() is negative\n        - imageInfo.height() is negative\n        - rowBytes is positive and less than imageInfo.width() times imageInfo.bytesPerPixel()\n\n        @param imageInfo  contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param rowBytes   imageInfo.minRowBytes or larger; or zero\n        @return           true if SkImageInfo set successfully\n    */\n    bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);\n\n    /** \\enum SkBitmap::AllocFlags\n        AllocFlags provides the option to zero pixel memory when allocated.\n    */\n    enum AllocFlags {\n        kZeroPixels_AllocFlag = 1 << 0, //!< zero pixel memory\n    };\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory. If flags is kZeroPixels_AllocFlag, memory is zeroed.\n\n        Returns false and calls reset() if SkImageInfo could not be set, or memory could\n        not be allocated, or memory could not optionally be zeroed.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc(), if flags is zero, and calloc(), if flags is\n        kZeroPixels_AllocFlag.\n\n        flags set to kZeroPixels_AllocFlag offers equal or better performance than\n        subsequently calling eraseColor() with SK_ColorTRANSPARENT.\n\n        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param flags  kZeroPixels_AllocFlag, or zero\n        @return       true if pixels allocation is successful\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory. If flags is kZeroPixels_AllocFlag, memory is zeroed.\n\n        Aborts execution if SkImageInfo could not be set, or memory could\n        not be allocated, or memory could not optionally\n        be zeroed. Abort steps may be provided by the user at compile time by defining\n        SK_ABORT.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc(), if flags is zero, and calloc(), if flags is\n        kZeroPixels_AllocFlag.\n\n        flags set to kZeroPixels_AllocFlag offers equal or better performance than\n        subsequently calling eraseColor() with SK_ColorTRANSPARENT.\n\n        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param flags  kZeroPixels_AllocFlag, or zero\n    */\n    void allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {\n        SkASSERT_RELEASE(this->tryAllocPixelsFlags(info, flags));\n    }\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),\n        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.\n\n        Returns false and calls reset() if SkImageInfo could not be set, or memory could\n        not be allocated.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc().\n\n        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param rowBytes  size of pixel row or larger; may be zero\n        @return          true if pixel storage is allocated\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes);\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),\n        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.\n\n        Aborts execution if SkImageInfo could not be set, or memory could\n        not be allocated. Abort steps may be provided by\n        the user at compile time by defining SK_ABORT.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc().\n\n        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param rowBytes  size of pixel row or larger; may be zero\n    */\n    void allocPixels(const SkImageInfo& info, size_t rowBytes) {\n        SkASSERT_RELEASE(this->tryAllocPixels(info, rowBytes));\n    }\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory.\n\n        Returns false and calls reset() if SkImageInfo could not be set, or memory could\n        not be allocated.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc().\n\n        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @return      true if pixel storage is allocated\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info) {\n        return this->tryAllocPixels(info, info.minRowBytes());\n    }\n\n    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel\n        memory.\n\n        Aborts execution if SkImageInfo could not be set, or memory could\n        not be allocated. Abort steps may be provided by\n        the user at compile time by defining SK_ABORT.\n\n        On most platforms, allocating pixel memory may succeed even though there is\n        not sufficient memory to hold pixels; allocation does not take place\n        until the pixels are written to. The actual behavior depends on the platform\n        implementation of malloc().\n\n        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace\n    */\n    void allocPixels(const SkImageInfo& info) {\n        this->allocPixels(info, info.minRowBytes());\n    }\n\n    /** Sets SkImageInfo to width, height, and native color type; and allocates\n        pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;\n        otherwise, sets to kPremul_SkAlphaType.\n\n        Calls reset() and returns false if width exceeds 29 bits or is negative,\n        or height is negative.\n\n        Returns false if allocation fails.\n\n        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on\n        the platform. SkBitmap drawn to output device skips converting its pixel format.\n\n        @param width     pixel column count; must be zero or greater\n        @param height    pixel row count; must be zero or greater\n        @param isOpaque  true if pixels do not have transparency\n        @return          true if pixel storage is allocated\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false) {\n        SkImageInfo info = SkImageInfo::MakeN32(width, height,\n                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);\n        return this->tryAllocPixels(info);\n    }\n\n    /** Sets SkImageInfo to width, height, and the native color type; and allocates\n        pixel memory. If isOpaque is true, sets SkImageInfo to kPremul_SkAlphaType;\n        otherwise, sets to kOpaque_SkAlphaType.\n\n        Aborts if width exceeds 29 bits or is negative, or height is negative, or\n        allocation fails. Abort steps may be provided by the user at compile time by\n        defining SK_ABORT.\n\n        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on\n        the platform. SkBitmap drawn to output device skips converting its pixel format.\n\n        @param width     pixel column count; must be zero or greater\n        @param height    pixel row count; must be zero or greater\n        @param isOpaque  true if pixels do not have transparency\n    */\n    void allocN32Pixels(int width, int height, bool isOpaque = false) {\n        SkImageInfo info = SkImageInfo::MakeN32(width, height,\n                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);\n        this->allocPixels(info);\n    }\n\n    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef\n        containing pixels and rowBytes. releaseProc, if not nullptr, is called\n        immediately on failure or when pixels are no longer referenced. context may be\n        nullptr.\n\n        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():\n        calls releaseProc if present, calls reset(), and returns false.\n\n        Otherwise, if pixels equals nullptr: sets SkImageInfo, calls releaseProc if\n        present, returns true.\n\n        If SkImageInfo is set, pixels is not nullptr, and releaseProc is not nullptr:\n        when pixels are no longer referenced, calls releaseProc with pixels and context\n        as parameters.\n\n        @param info         contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param pixels       address or pixel storage; may be nullptr\n        @param rowBytes     size of pixel row or larger\n        @param releaseProc  function called when pixels can be deleted; may be nullptr\n        @param context      caller state passed to releaseProc; may be nullptr\n        @return             true if SkImageInfo is set to info\n    */\n    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,\n                       void (*releaseProc)(void* addr, void* context), void* context);\n\n    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef\n        containing pixels and rowBytes.\n\n        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():\n        calls reset(), and returns false.\n\n        Otherwise, if pixels equals nullptr: sets SkImageInfo, returns true.\n\n        Caller must ensure that pixels are valid for the lifetime of SkBitmap and SkPixelRef.\n\n        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param pixels    address or pixel storage; may be nullptr\n        @param rowBytes  size of pixel row or larger\n        @return          true if SkImageInfo is set to info\n    */\n    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {\n        return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);\n    }\n\n    /** Sets SkImageInfo to pixmap.info() following the rules in setInfo(), and creates\n        SkPixelRef containing pixmap.addr() and pixmap.rowBytes().\n\n        If SkImageInfo could not be set, or pixmap.rowBytes() is less than\n        SkImageInfo::minRowBytes: calls reset(), and returns false.\n\n        Otherwise, if pixmap.addr() equals nullptr: sets SkImageInfo, returns true.\n\n        Caller must ensure that pixmap is valid for the lifetime of SkBitmap and SkPixelRef.\n\n        @param pixmap  SkImageInfo, pixel address, and rowBytes()\n        @return        true if SkImageInfo was set to pixmap.info()\n    */\n    bool installPixels(const SkPixmap& pixmap);\n\n    /** To be deprecated soon.\n    */\n    bool installMaskPixels(const SkMask& mask);\n\n    /** Replaces SkPixelRef with pixels, preserving SkImageInfo and rowBytes().\n        Sets SkPixelRef origin to (0, 0).\n\n        If pixels is nullptr, or if info().colorType equals kUnknown_SkColorType;\n        release reference to SkPixelRef, and set SkPixelRef to nullptr.\n\n        Caller is responsible for handling ownership pixel memory for the lifetime\n        of SkBitmap and SkPixelRef.\n\n        @param pixels  address of pixel storage, managed by caller\n    */\n    void setPixels(void* pixels);\n\n    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.\n        The allocation size is determined by SkImageInfo width, height, and SkColorType.\n\n        Returns false if info().colorType is kUnknown_SkColorType, or allocation fails.\n\n        @return  true if the allocation succeeds\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocPixels() {\n        return this->tryAllocPixels((Allocator*)nullptr);\n    }\n\n    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.\n        The allocation size is determined by SkImageInfo width, height, and SkColorType.\n\n        Aborts if info().colorType is kUnknown_SkColorType, or allocation fails.\n        Abort steps may be provided by the user at compile\n        time by defining SK_ABORT.\n    */\n    void allocPixels() {\n        this->allocPixels((Allocator*)nullptr);\n    }\n\n    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.\n        The allocation size is determined by SkImageInfo width, height, and SkColorType.\n        If allocator is nullptr, use HeapAllocator instead.\n\n        Returns false if Allocator::allocPixelRef return false.\n\n        @param allocator  instance of SkBitmap::Allocator instantiation\n        @return           true if custom allocator reports success\n    */\n    bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator);\n\n    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.\n        The allocation size is determined by SkImageInfo width, height, and SkColorType.\n        If allocator is nullptr, use HeapAllocator instead.\n\n        Aborts if Allocator::allocPixelRef return false. Abort steps may be provided by\n        the user at compile time by defining SK_ABORT.\n\n        @param allocator  instance of SkBitmap::Allocator instantiation\n    */\n    void allocPixels(Allocator* allocator) {\n        SkASSERT_RELEASE(this->tryAllocPixels(allocator));\n    }\n\n    /** Returns SkPixelRef, which contains: pixel base address; its dimensions; and\n        rowBytes(), the interval from one row to the next. Does not change SkPixelRef\n        reference count. SkPixelRef may be shared by multiple bitmaps.\n        If SkPixelRef has not been set, returns nullptr.\n\n        @return  SkPixelRef, or nullptr\n    */\n    SkPixelRef* pixelRef() const { return fPixelRef.get(); }\n\n    /** Returns origin of pixels within SkPixelRef. SkBitmap bounds is always contained\n        by SkPixelRef bounds, which may be the same size or larger. Multiple SkBitmap\n        can share the same SkPixelRef, where each SkBitmap has different bounds.\n\n        The returned origin added to SkBitmap dimensions equals or is smaller than the\n        SkPixelRef dimensions.\n\n        Returns (0, 0) if SkPixelRef is nullptr.\n\n        @return  pixel origin within SkPixelRef\n    */\n    SkIPoint pixelRefOrigin() const;\n\n    /** Replaces pixelRef and origin in SkBitmap.  dx and dy specify the offset\n        within the SkPixelRef pixels for the top-left corner of the bitmap.\n\n        Asserts in debug builds if dx or dy are out of range. Pins dx and dy\n        to legal range in release builds.\n\n        The caller is responsible for ensuring that the pixels match the\n        SkColorType and SkAlphaType in SkImageInfo.\n\n        @param pixelRef  SkPixelRef describing pixel address and rowBytes()\n        @param dx        column offset in SkPixelRef for bitmap origin\n        @param dy        row offset in SkPixelRef for bitmap origin\n    */\n    void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);\n\n    /** Returns true if SkBitmap is can be drawn.\n\n        @return  true if getPixels() is not nullptr\n    */\n    bool readyToDraw() const {\n        return this->getPixels() != nullptr;\n    }\n\n    /** Returns a unique value corresponding to the pixels in SkPixelRef.\n        Returns a different value after notifyPixelsChanged() has been called.\n        Returns zero if SkPixelRef is nullptr.\n\n        Determines if pixels have changed since last examined.\n\n        @return  unique value for pixels in SkPixelRef\n    */\n    uint32_t getGenerationID() const;\n\n    /** Marks that pixels in SkPixelRef have changed. Subsequent calls to\n        getGenerationID() return a different value.\n    */\n    void notifyPixelsChanged() const;\n\n    /** Replaces pixel values with c. All pixels contained by bounds() are affected.\n        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then alpha\n        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,\n        then RGB is ignored.\n\n        @param c  unpremultiplied color\n    */\n    void eraseColor(SkColor c) const;\n\n    /** Replaces pixel values with unpremultiplied color built from a, r, g, and b.\n        All pixels contained by bounds() are affected.\n        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then a\n        is ignored; r, g, and b are treated as opaque. If colorType() is kAlpha_8_SkColorType,\n        then r, g, and b are ignored.\n\n        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)\n        @param r  amount of red, from no red (0) to full red (255)\n        @param g  amount of green, from no green (0) to full green (255)\n        @param b  amount of blue, from no blue (0) to full blue (255)\n    */\n    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {\n        this->eraseColor(SkColorSetARGB(a, r, g, b));\n    }\n\n    /** Deprecated.\n    */\n    SK_ATTR_DEPRECATED(\"use eraseARGB or eraseColor\")\n    void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {\n        this->eraseARGB(0xFF, r, g, b);\n    }\n\n    /** Replaces pixel values inside area with c. If area does not intersect bounds(),\n        call has no effect.\n\n        If the colorType() is kGray_8_SkColorType or k565_SkColorType, then alpha\n        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,\n        then RGB is ignored.\n\n        @param c     unpremultiplied color\n        @param area  rectangle to fill\n    */\n    void erase(SkColor c, const SkIRect& area) const;\n\n    /** Deprecated.\n    */\n    void eraseArea(const SkIRect& area, SkColor c) const {\n        this->erase(c, area);\n    }\n\n    /** Returns pixel at (x, y) as unpremultiplied color.\n        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined; and returns undefined values or may crash if\n        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or\n        pixel address is nullptr.\n\n        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the\n        conversion to unpremultiplied color; original pixel data may have additional\n        precision.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   pixel converted to unpremultiplied color\n    */\n    SkColor getColor(int x, int y) const {\n        return this->pixmap().getColor(x, y);\n    }\n\n    /** Returns pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y, or kUnknown_SkColorType,\n        trigger an assert() if built with SK_DEBUG defined. Returns nullptr if\n        SkColorType is kUnknown_SkColorType, or SkPixelRef is nullptr.\n\n        Performs a lookup of pixel size; for better performance, call\n        one of: getAddr8(), getAddr16(), or getAddr32().\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   generic pointer to pixel\n    */\n    void* getAddr(int x, int y) const;\n\n    /** Returns address at (x, y).\n\n        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:\n        - SkPixelRef is nullptr\n        - bytesPerPixel() is not four\n        - x is negative, or not less than width()\n        - y is negative, or not less than height()\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   unsigned 32-bit pointer to pixel at (x, y)\n    */\n    inline uint32_t* getAddr32(int x, int y) const;\n\n    /** Returns address at (x, y).\n\n        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:\n        - SkPixelRef is nullptr\n        - bytesPerPixel() is not two\n        - x is negative, or not less than width()\n        - y is negative, or not less than height()\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   unsigned 16-bit pointer to pixel at (x, y)\n    */\n    inline uint16_t* getAddr16(int x, int y) const;\n\n    /** Returns address at (x, y).\n\n        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:\n        - SkPixelRef is nullptr\n        - bytesPerPixel() is not one\n        - x is negative, or not less than width()\n        - y is negative, or not less than height()\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   unsigned 8-bit pointer to pixel at (x, y)\n    */\n    inline uint8_t* getAddr8(int x, int y) const;\n\n    /** Shares SkPixelRef with dst. Pixels are not copied; SkBitmap and dst point\n        to the same pixels; dst bounds() are set to the intersection of subset\n        and the original bounds().\n\n        subset may be larger than bounds(). Any area outside of bounds() is ignored.\n\n        Any contents of dst are discarded. isVolatile() setting is copied to dst.\n        dst is set to colorType(), alphaType(), and colorSpace().\n\n        Return false if:\n        - dst is nullptr\n        - SkPixelRef is nullptr\n        - subset does not intersect bounds()\n\n        @param dst     SkBitmap set to subset\n        @param subset  rectangle of pixels to reference\n        @return        true if dst is replaced by subset\n    */\n    bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;\n\n    /** Copies SkRect of pixels from SkBitmap pixels to dstPixels. Copy starts at (srcX, srcY),\n        and does not exceed SkBitmap (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and\n        SkColorSpace of destination. dstRowBytes specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - dstInfo.addr() equals nullptr\n        - dstRowBytes is less than dstInfo.minRowBytes()\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().\n\n        If behavior is SkTransferFunctionBehavior::kRespect: converts source\n        pixels to a linear space before converting to dstInfo.\n        If behavior is SkTransferFunctionBehavior::kIgnore: source\n        pixels are treated as if they are linear, regardless of how they are encoded.\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @param behavior     one of: SkTransferFunctionBehavior::kRespect,\n                            SkTransferFunctionBehavior::kIgnore\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY, SkTransferFunctionBehavior behavior) const;\n\n    /** Copies a SkRect of pixels from SkBitmap to dstPixels. Copy starts at (srcX, srcY),\n        and does not exceed SkBitmap (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of\n        destination. dstRowBytes specifics the gap from one destination row to the next.\n        Returns true if pixels are copied. Returns false if:\n        - dstInfo.addr() equals nullptr\n        - dstRowBytes is less than dstInfo.minRowBytes()\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY) const {\n        return this->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY,\n                SkTransferFunctionBehavior::kRespect);\n    }\n\n    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (srcX, srcY), and\n        does not exceed SkBitmap (width(), height()).\n\n        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of destination. dst.rowBytes() specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - dst pixel storage equals nullptr\n        - dst.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must\n        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().\n\n        @param dst   destination SkPixmap: SkImageInfo, pixels, row bytes\n        @param srcX  column index whose absolute value is less than width()\n        @param srcY  row index whose absolute value is less than height()\n        @return      true if pixels are copied to dst\n    */\n    bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;\n\n    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (0, 0), and\n        does not exceed SkBitmap (width(), height()).\n\n        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of destination. dst.rowBytes() specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - dst pixel storage equals nullptr\n        - dst.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must\n        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        @param dst  destination SkPixmap: SkImageInfo, pixels, row bytes\n        @return     true if pixels are copied to dst\n    */\n    bool readPixels(const SkPixmap& dst) const {\n        return this->readPixels(dst, 0, 0);\n    }\n\n    /** Copies a SkRect of pixels from src. Copy starts at (dstX, dstY), and does not exceed\n        (src.width(), src.height()).\n\n        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of source. src.rowBytes() specifics the gap from one source\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - src pixel storage equals nullptr\n        - src.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must\n        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        dstX and dstY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(dstX) >= Bitmap width(), or if abs(dstY) >= Bitmap height().\n\n        @param src   source SkPixmap: SkImageInfo, pixels, row bytes\n        @param dstX  column index whose absolute value is less than width()\n        @param dstY  row index whose absolute value is less than height()\n        @return      true if src pixels are copied to SkBitmap\n    */\n    bool writePixels(const SkPixmap& src, int dstX, int dstY) {\n        return this->writePixels(src, dstX, dstY, SkTransferFunctionBehavior::kRespect);\n    }\n\n    /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed\n        (src.width(), src.height()).\n\n        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of source. src.rowBytes() specifics the gap from one source\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - src pixel storage equals nullptr\n        - src.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must\n        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        @param src  source SkPixmap: SkImageInfo, pixels, row bytes\n        @return     true if src pixels are copied to SkBitmap\n    */\n    bool writePixels(const SkPixmap& src) {\n        return this->writePixels(src, 0, 0);\n    }\n\n    /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed\n        (src.width(), src.height()).\n\n        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of source. src.rowBytes() specifics the gap from one source\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - src pixel storage equals nullptr\n        - src.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.\n        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.\n        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must\n        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns\n        false if pixel conversion is not possible. Returns false if width() or height()\n        is zero or negative.\n\n        If behavior is SkTransferFunctionBehavior::kRespect: converts src\n        pixels to a linear space before converting to SkImageInfo.\n        If behavior is SkTransferFunctionBehavior::kIgnore: src\n        pixels are treated as if they are linear, regardless of how they are encoded.\n\n        @param src       source SkPixmap: SkImageInfo, pixels, row bytes\n        @param x         column index whose absolute value is less than width()\n        @param y         row index whose absolute value is less than height()\n        @param behavior  one of: SkTransferFunctionBehavior::kRespect,\n                         SkTransferFunctionBehavior::kIgnore\n        @return          true if src pixels are copied to SkBitmap\n    */\n    bool writePixels(const SkPixmap& src, int x, int y, SkTransferFunctionBehavior behavior);\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    /** Android framework only.\n\n        @return  true if setHasHardwareMipMap() has been called with true\n    */\n    bool hasHardwareMipMap() const {\n        return (fFlags & kHasHardwareMipMap_Flag) != 0;\n    }\n\n    /** Android framework only.\n\n        @param hasHardwareMipMap  sets state\n    */\n    void setHasHardwareMipMap(bool hasHardwareMipMap) {\n        if (hasHardwareMipMap) {\n            fFlags |= kHasHardwareMipMap_Flag;\n        } else {\n            fFlags &= ~kHasHardwareMipMap_Flag;\n        }\n    }\n#endif\n\n    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to\n        or dst pixels cannot be allocated.\n\n        Uses HeapAllocator to reserve memory for dst SkPixelRef.\n\n        @param dst  holds SkPixelRef to fill with alpha layer\n        @return     true if alpha layer was constructed in dst SkPixelRef\n    */\n    bool extractAlpha(SkBitmap* dst) const {\n        return this->extractAlpha(dst, nullptr, nullptr, nullptr);\n    }\n\n    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to\n        or dst pixels cannot be allocated.\n\n        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter\n        generates mask alpha from SkBitmap. Uses HeapAllocator to reserve memory for dst\n        SkPixelRef. Sets offset to top-left position for dst for alignment with SkBitmap;\n        (0, 0) unless SkMaskFilter generates mask.\n\n        @param dst     holds SkPixelRef to fill with alpha layer\n        @param paint   holds optional SkMaskFilter; may be nullptr\n        @param offset  top-left position for dst; may be nullptr\n        @return        true if alpha layer was constructed in dst SkPixelRef\n    */\n    bool extractAlpha(SkBitmap* dst, const SkPaint* paint,\n                      SkIPoint* offset) const {\n        return this->extractAlpha(dst, paint, nullptr, offset);\n    }\n\n    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to\n        or dst pixels cannot be allocated.\n\n        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter\n        generates mask alpha from SkBitmap. allocator may reference a custom allocation\n        class or be set to nullptr to use HeapAllocator. Sets offset to top-left\n        position for dst for alignment with SkBitmap; (0, 0) unless SkMaskFilter generates\n        mask.\n\n        @param dst        holds SkPixelRef to fill with alpha layer\n        @param paint      holds optional SkMaskFilter; may be nullptr\n        @param allocator  function to reserve memory for SkPixelRef; may be nullptr\n        @param offset     top-left position for dst; may be nullptr\n        @return           true if alpha layer was constructed in dst SkPixelRef\n    */\n    bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,\n                      SkIPoint* offset) const;\n\n    /** Copies SkBitmap pixel address, row bytes, and SkImageInfo to pixmap, if address\n        is available, and returns true. If pixel address is not available, return\n        false and leave pixmap unchanged.\n\n        pixmap contents become invalid on any future change to SkBitmap.\n\n        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored\n        @return        true if SkBitmap has direct access to pixels\n    */\n    bool peekPixels(SkPixmap* pixmap) const;\n\n    /** Asserts if internal values are illegal or inconsistent. Only available if\n        SK_DEBUG is defined at compile time.\n    */\n    SkDEBUGCODE(void validate() const;)\n\n    /** \\class SkBitmap::Allocator\n        Abstract subclass of HeapAllocator.\n    */\n    class Allocator : public SkRefCnt {\n    public:\n\n        /** Allocates the pixel memory for the bitmap, given its dimensions and\n            SkColorType. Returns true on success, where success means either setPixels()\n            or setPixelRef() was called.\n\n            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output\n            @return        true if SkPixelRef was allocated\n        */\n        virtual bool allocPixelRef(SkBitmap* bitmap) = 0;\n    private:\n        typedef SkRefCnt INHERITED;\n    };\n\n    /** \\class SkBitmap::HeapAllocator\n        Subclass of SkBitmap::Allocator that returns a SkPixelRef that allocates its pixel\n        memory from the heap. This is the default SkBitmap::Allocator invoked by\n        allocPixels().\n    */\n    class HeapAllocator : public Allocator {\n    public:\n\n        /** Allocates the pixel memory for the bitmap, given its dimensions and\n            SkColorType. Returns true on success, where success means either setPixels()\n            or setPixelRef() was called.\n\n            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output\n            @return        true if pixels are allocated\n        */\n        bool allocPixelRef(SkBitmap* bitmap) override;\n    };\n\n    /** Creates string representation of SkBitmap. The representation is read by\n        internal debugging tools.\n\n        @param str  storage for string representation\n    */\n    void toString(SkString* str) const;\n\nprivate:\n    enum Flags {\n        kImageIsVolatile_Flag   = 0x02,\n#ifdef SK_BUILD_FOR_ANDROID\n        /* A hint for the renderer responsible for drawing this bitmap\n         * indicating that it should attempt to use mipmaps when this bitmap\n         * is drawn scaled down.\n         */\n        kHasHardwareMipMap_Flag = 0x08,\n#endif\n    };\n\n    sk_sp<SkPixelRef>   fPixelRef;\n    SkPixmap            fPixmap;\n    uint8_t             fFlags;\n\n    friend class SkReadBuffer;        // unflatten\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\ninline uint32_t* SkBitmap::getAddr32(int x, int y) const {\n    SkASSERT(fPixmap.addr());\n    return fPixmap.writable_addr32(x, y);\n}\n\ninline uint16_t* SkBitmap::getAddr16(int x, int y) const {\n    SkASSERT(fPixmap.addr());\n    return fPixmap.writable_addr16(x, y);\n}\n\ninline uint8_t* SkBitmap::getAddr8(int x, int y) const {\n    SkASSERT(fPixmap.addr());\n    return fPixmap.writable_addr8(x, y);\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkBlendMode.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBlendMode_DEFINED\n#define SkBlendMode_DEFINED\n\n#include \"SkTypes.h\"\n\nenum class SkBlendMode {\n    kClear,    //!< [0, 0]\n    kSrc,      //!< [Sa, Sc]\n    kDst,      //!< [Da, Dc]\n    kSrcOver,  //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]\n    kDstOver,  //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]\n    kSrcIn,    //!< [Sa * Da, Sc * Da]\n    kDstIn,    //!< [Da * Sa, Dc * Sa]\n    kSrcOut,   //!< [Sa * (1 - Da), Sc * (1 - Da)]\n    kDstOut,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]\n    kSrcATop,  //!< [Da, Sc * Da + Dc * (1 - Sa)]\n    kDstATop,  //!< [Sa, Dc * Sa + Sc * (1 - Da)]\n    kXor,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]\n    kPlus,     //!< [Sa + Da, Sc + Dc]\n    kModulate, // multiplies all components (= alpha and color)\n\n    // Following blend modes are defined in the CSS Compositing standard:\n    // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending\n    kScreen,\n    kLastCoeffMode = kScreen,\n\n    kOverlay,\n    kDarken,\n    kLighten,\n    kColorDodge,\n    kColorBurn,\n    kHardLight,\n    kSoftLight,\n    kDifference,\n    kExclusion,\n    kMultiply,\n    kLastSeparableMode = kMultiply,\n\n    kHue,\n    kSaturation,\n    kColor,\n    kLuminosity,\n    kLastMode = kLuminosity,\n};\n\n/**\n *  Return the (c-string) name of the blendmode.\n */\nSK_API const char* SkBlendMode_Name(SkBlendMode);\n\n#endif\n"
  },
  {
    "path": "include/core/SkBlurTypes.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBlurTypes_DEFINED\n#define SkBlurTypes_DEFINED\n\n#include \"SkTypes.h\"\n\nenum SkBlurStyle {\n    kNormal_SkBlurStyle,  //!< fuzzy inside and outside\n    kSolid_SkBlurStyle,   //!< solid inside, fuzzy outside\n    kOuter_SkBlurStyle,   //!< nothing inside, fuzzy outside\n    kInner_SkBlurStyle,   //!< fuzzy inside, nothing outside\n\n    kLastEnum_SkBlurStyle = kInner_SkBlurStyle,\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkCanvas.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCanvas_DEFINED\n#define SkCanvas_DEFINED\n\n#include \"SkBlendMode.h\"\n#include \"SkClipOp.h\"\n#include \"SkDeque.h\"\n#include \"SkPaint.h\"\n#include \"SkRasterHandleAllocator.h\"\n#include \"SkSurfaceProps.h\"\n\nclass GrContext;\nclass GrRenderTargetContext;\nclass SkAndroidFrameworkUtils;\nclass SkBaseDevice;\nclass SkBitmap;\nclass SkClipStack;\nclass SkData;\nclass SkDraw;\nclass SkDrawable;\nclass SkDrawFilter;\nstruct SkDrawShadowRec;\nclass SkImage;\nclass SkImageFilter;\nclass SkMetaData;\nclass SkPath;\nclass SkPicture;\nclass SkPixmap;\nclass SkRasterClip;\nclass SkRegion;\nclass SkRRect;\nstruct SkRSXform;\nclass SkSurface;\nclass SkSurface_Base;\nclass SkTextBlob;\nclass SkVertices;\n\n/** \\class SkCanvas\n    SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed.\n    SkCanvas contains a stack of SkMatrix and clip values.\n\n    SkCanvas and SkPaint together provide the state to draw into SkSurface or SkBaseDevice.\n    Each SkCanvas draw call transforms the geometry of the object by the concatenation of all\n    SkMatrix values in the stack. The transformed geometry is clipped by the intersection\n    of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing\n    state such as color, SkTypeface, text size, stroke width, SkShader and so on.\n\n    To draw to a pixel-based destination, create raster surface or GPU surface.\n    Request SkCanvas from SkSurface to obtain the interface to draw.\n    SkCanvas generated by raster surface draws to memory visible to the CPU.\n    SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.\n\n    To draw to a document, obtain SkCanvas from svg canvas, document pdf, or SkPictureRecorder.\n    SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the\n    destination.\n\n    SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.\n    This approach may be deprecated in the future.\n*/\nclass SK_API SkCanvas : SkNoncopyable {\n    enum PrivateSaveLayerFlags {\n        kDontClipToLayer_PrivateSaveLayerFlag   = 1U << 31,\n    };\n\npublic:\n\n    /** Allocates raster SkCanvas that will draw directly into pixels.\n\n        SkCanvas is returned if all parameters are valid.\n        Valid parameters include:\n        info dimensions are zero or positive;\n        info contains SkColorType and SkAlphaType supported by raster surface;\n        pixels is not nullptr;\n        rowBytes is zero or large enough to contain info width pixels of SkColorType.\n\n        Pass zero for rowBytes to compute rowBytes from info width and size of pixel.\n        If rowBytes is greater than zero, it must be equal to or greater than\n        info width times bytes required for SkColorType.\n\n        Pixel buffer size should be info height times computed rowBytes.\n        Pixels are not initialized.\n        To access pixels after drawing, call flush() or peekPixels().\n\n        @param info      width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface;\n                         width, or height, or both, may be zero\n        @param pixels    pointer to destination pixels buffer\n        @param rowBytes  interval from one SkSurface row to the next, or zero\n        @param props     LCD striping orientation and setting for device independent fonts;\n                         may be nullptr\n        @return          SkCanvas if all parameters are valid; otherwise, nullptr\n    */\n    static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,\n                                                      size_t rowBytes,\n                                                      const SkSurfaceProps* props = nullptr);\n\n    /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas\n        calls draw into pixels.\n        SkColorType is set to kN32_SkColorType.\n        SkAlphaType is set to kPremul_SkAlphaType.\n        To access pixels after drawing, call flush() or peekPixels().\n\n        SkCanvas is returned if all parameters are valid.\n        Valid parameters include:\n        width and height are zero or positive;\n        pixels is not nullptr;\n        rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.\n\n        Pass zero for rowBytes to compute rowBytes from width and size of pixel.\n        If rowBytes is greater than zero, it must be equal to or greater than\n        width times bytes required for SkColorType.\n\n        Pixel buffer size should be height times rowBytes.\n\n        @param width     pixel column count on raster surface created; must be zero or greater\n        @param height    pixel row count on raster surface created; must be zero or greater\n        @param pixels    pointer to destination pixels buffer; buffer size should be height\n                         times rowBytes\n        @param rowBytes  interval from one SkSurface row to the next, or zero\n        @return          SkCanvas if all parameters are valid; otherwise, nullptr\n    */\n    static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,\n                                                         size_t rowBytes) {\n        return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);\n    }\n\n    /** Creates an empty SkCanvas with no backing device or pixels, with\n        a width and height of zero.\n\n        @return  empty SkCanvas\n    */\n    SkCanvas();\n\n    /** Creates SkCanvas of the specified dimensions without a SkSurface.\n        Used by subclasses with custom implementations for draw member functions.\n\n        If props equals nullptr, SkSurfaceProps are created with\n        SkSurfaceProps::InitType settings, which choose the pixel striping\n        direction and order. Since a platform may dynamically change its direction when\n        the device is rotated, and since a platform may have multiple monitors with\n        different characteristics, it is best not to rely on this legacy behavior.\n\n        @param width   zero or greater\n        @param height  zero or greater\n        @param props   LCD striping orientation and setting for device independent fonts;\n                       may be nullptr\n        @return        SkCanvas placeholder with dimensions\n    */\n    SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);\n\n    /** To be deprecated soon.\n    */\n    explicit SkCanvas(sk_sp<SkBaseDevice> device);\n\n    /** Construct a canvas that draws into bitmap.\n        Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed SkSurface.\n\n        SkBitmap is copied so that subsequently editing bitmap will not affect\n        constructed SkCanvas.\n\n        May be deprecated in the future.\n\n        @param bitmap  width, height, SkColorType, SkAlphaType, and pixel\n                       storage of raster surface\n        @return        SkCanvas that can be used to draw into bitmap\n    */\n    explicit SkCanvas(const SkBitmap& bitmap);\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    enum class ColorBehavior {\n        kLegacy, //!< placeholder\n    };\n\n    /** Android framework only.\n\n        @param bitmap    specifies a bitmap for the canvas to draw into\n        @param behavior  specializes this constructor; value is unused\n        @return          SkCanvas that can be used to draw into bitmap\n    */\n    SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);\n#endif\n\n    /** Construct a canvas that draws into bitmap.\n        Use props to match the device characteristics, like LCD striping.\n\n        bitmap is copied so that subsequently editing bitmap will not affect\n        constructed SkCanvas.\n\n        @param bitmap  width, height, SkColorType, SkAlphaType,\n                       and pixel storage of raster surface\n        @param props   order and orientation of RGB striping; and whether to use\n                       device independent fonts\n        @return        SkCanvas that can be used to draw into bitmap\n    */\n    SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);\n\n    /** Draws saved layers, if any.\n        Frees up resources used by SkCanvas.\n    */\n    virtual ~SkCanvas();\n\n    /** Returns storage to associate additional data with the canvas.\n        The storage is freed when SkCanvas is deleted.\n\n        @return  storage that can be read from and written to\n    */\n    SkMetaData& getMetaData();\n\n    /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or\n        GPU surface, returned SkColorType is set to kUnknown_SkColorType.\n\n        @return  dimensions and SkColorType of SkCanvas\n    */\n    SkImageInfo imageInfo() const;\n\n    /** If SkCanvas is associated with raster surface or\n        GPU surface, copies SkSurfaceProps and returns true. Otherwise,\n        return false and leave props unchanged.\n\n        @param props  storage for writable SkSurfaceProps\n        @return       true if SkSurfaceProps was copied\n    */\n    bool getProps(SkSurfaceProps* props) const;\n\n    /** Triggers the immediate execution of all pending draw operations.\n        If SkCanvas is associated with GPU surface, resolves all pending GPU operations.\n        If SkCanvas is associated with raster surface, has no effect; raster draw\n        operations are never deferred.\n    */\n    void flush();\n\n    /** Gets the size of the base or root layer in global canvas coordinates. The\n        origin of the base layer is always (0,0). The area available for drawing may be\n        smaller (due to clipping or saveLayer).\n\n        @return  integral width and height of base layer\n    */\n    virtual SkISize getBaseLayerSize() const;\n\n    /** Creates SkSurface matching info and props, and associates it with SkCanvas.\n        Returns nullptr if no match found.\n\n        If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas\n        does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps.\n\n        @param info   width, height, SkColorType, SkAlphaType, and SkColorSpace\n        @param props  SkSurfaceProps to match; may be nullptr to match SkCanvas\n        @return       SkSurface matching info and props, or nullptr if no match is available\n    */\n    sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);\n\n    /** Returns GPU context of the GPU surface associated with SkCanvas.\n\n        @return  GPU context, if available; nullptr otherwise\n    */\n    virtual GrContext* getGrContext();\n\n    /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels\n        can be read directly. The returned address is only valid\n        while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call\n        may invalidate the returned address and other returned values.\n\n        If pixels are inaccessible, info, rowBytes, and origin are unchanged.\n\n        @param info      storage for writable pixels' SkImageInfo; may be nullptr\n        @param rowBytes  storage for writable pixels' row bytes; may be nullptr\n        @param origin    storage for SkCanvas top layer origin, its top-left corner;\n                         may be nullptr\n        @return          address of pixels, or nullptr if inaccessible\n    */\n    void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);\n\n    /** Returns custom context that tracks the SkMatrix and clip.\n\n        Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed\n        by the host platform user interface. The custom context returned is generated by\n        SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for\n        the drawing destination.\n\n        @return  context of custom allocation\n    */\n    SkRasterHandleAllocator::Handle accessTopRasterHandle() const;\n\n    /** Returns true if SkCanvas has direct access to its pixels.\n\n        Pixels are readable when SkBaseDevice is raster. Pixels are not readable when SkCanvas\n        is returned from GPU surface, returned by SkDocument::beginPage, returned by\n        SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class\n        like SkDebugCanvas.\n\n        pixmap is valid only while SkCanvas is in scope and unchanged. Any\n        SkCanvas or SkSurface call may invalidate the pixmap values.\n\n        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored\n        @return        true if SkCanvas has direct access to pixels\n    */\n    bool peekPixels(SkPixmap* pixmap);\n\n    /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are\n        ignored.\n\n        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).\n        Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to dstInfo.colorType() and dstInfo.alphaType() if required.\n\n        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.\n        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,\n        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility\n        class like SkDebugCanvas.\n\n        The destination pixel storage must be allocated by the caller.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. dstPixels contents outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down destination.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().\n        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.\n        - dstRowBytes is too small to contain one row of pixels.\n\n        @param dstInfo      width, height, SkColorType, and SkAlphaType of dstPixels\n        @param dstPixels    storage for pixels; dstInfo.height() times dstRowBytes, or larger\n        @param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger\n        @param srcX         offset into readable pixels in x; may be negative\n        @param srcY         offset into readable pixels in y; may be negative\n        @return             true if pixels were copied\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY);\n\n    /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are\n        ignored.\n\n        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).\n        Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to pixmap.colorType() and pixmap.alphaType() if required.\n\n        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.\n        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,\n        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility\n        class like SkDebugCanvas.\n\n        Caller must allocate pixel storage in pixmap if needed.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination SkRect\n        are copied. pixmap pixels contents outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down pixmap.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType().\n        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.\n        - SkPixmap pixels could not be allocated.\n        - pixmap.rowBytes() is too small to contain one row of pixels.\n\n        @param pixmap  storage for pixels copied from SkCanvas\n        @param srcX    offset into readable pixels in x; may be negative\n        @param srcY    offset into readable pixels in y; may be negative\n        @return        true if pixels were copied\n    */\n    bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);\n\n    /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are\n        ignored.\n\n        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).\n        Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to bitmap.colorType() and bitmap.alphaType() if required.\n\n        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.\n        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,\n        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility\n        class like SkDebugCanvas.\n\n        Caller must allocate pixel storage in bitmap if needed.\n\n        SkBitmap values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. SkBitmap pixels outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down bitmap.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType().\n        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.\n        - bitmap pixels could not be allocated.\n        - bitmap.rowBytes() is too small to contain one row of pixels.\n\n        @param bitmap  storage for pixels copied from SkCanvas\n        @param srcX    offset into readable pixels in x; may be negative\n        @param srcY    offset into readable pixels in y; may be negative\n        @return        true if pixels were copied\n    */\n    bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);\n\n    /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.\n        Source SkRect corners are (0, 0) and (info.width(), info.height()).\n        Destination SkRect corners are (x, y) and\n        (imageInfo().width(), imageInfo().height()).\n\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to imageInfo().colorType() and imageInfo().alphaType() if required.\n\n        Pixels are writable when SkBaseDevice is raster, or backed by a GPU.\n        Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,\n        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility\n        class like SkDebugCanvas.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. SkCanvas pixels outside SkRect intersection are unchanged.\n\n        Pass negative values for x or y to offset pixels to the left or\n        above SkCanvas pixels.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - pixels could not be converted to SkCanvas imageInfo().colorType() or\n        imageInfo().alphaType().\n        - SkCanvas pixels are not writable; for instance, SkCanvas is document-based.\n        - rowBytes is too small to contain one row of pixels.\n\n        @param info      width, height, SkColorType, and SkAlphaType of pixels\n        @param pixels    pixels to copy, of size info.height() times rowBytes, or larger\n        @param rowBytes  size of one row of pixels; info.width() times pixel size, or larger\n        @param x         offset into SkCanvas writable pixels in x; may be negative\n        @param y         offset into SkCanvas writable pixels in y; may be negative\n        @return          true if pixels were written to SkCanvas\n    */\n    bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);\n\n    /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.\n        Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).\n\n        Destination SkRect corners are (x, y) and\n        (imageInfo().width(), imageInfo().height()).\n\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to imageInfo().colorType() and imageInfo().alphaType() if required.\n\n        Pixels are writable when SkBaseDevice is raster, or backed by a GPU.\n        Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,\n        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility\n        class like SkDebugCanvas.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. SkCanvas pixels outside SkRect intersection are unchanged.\n\n        Pass negative values for x or y to offset pixels to the left or\n        above SkCanvas pixels.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - bitmap does not have allocated pixels.\n        - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or\n        imageInfo().alphaType().\n        - SkCanvas pixels are not writable; for instance, SkCanvas is document based.\n        - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.\n\n        @param bitmap  contains pixels copied to SkCanvas\n        @param x       offset into SkCanvas writable pixels in x; may be negative\n        @param y       offset into SkCanvas writable pixels in y; may be negative\n        @return        true if pixels were written to SkCanvas\n    */\n    bool writePixels(const SkBitmap& bitmap, int x, int y);\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms).\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        restoring the SkMatrix, clip, and SkDrawFilter to their state when save() was called.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(),\n        and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion().\n\n        Saved SkCanvas state is put on a stack; multiple calls to save() should be balance\n        by an equal number of calls to restore().\n\n        Call restoreToCount() with result to restore this and subsequent saves.\n\n        @return  depth of saved stack\n    */\n    int save();\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms),\n        and allocates a SkBitmap for subsequent drawing.\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        and draws the SkBitmap.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),\n        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),\n        clipPath(), clipRegion().\n\n        SkRect bounds suggests but does not define the SkBitmap size. To clip drawing to\n        a specific rectangle, use clipRect().\n\n        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and\n        SkBlendMode when restore() is called.\n\n        Call restoreToCount() with returned value to restore this and subsequent saves.\n\n        @param bounds  hint to limit the size of the layer; may be nullptr\n        @param paint   graphics state for layer; may be nullptr\n        @return        depth of saved stack\n    */\n    int saveLayer(const SkRect* bounds, const SkPaint* paint);\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms),\n        and allocates a SkBitmap for subsequent drawing.\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        and draws the SkBitmap.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),\n        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),\n        clipPath(), clipRegion().\n\n        SkRect bounds suggests but does not define the layer size. To clip drawing to\n        a specific rectangle, use clipRect().\n\n        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and\n        SkBlendMode when restore() is called.\n\n        Call restoreToCount() with returned value to restore this and subsequent saves.\n\n        @param bounds  hint to limit the size of layer; may be nullptr\n        @param paint   graphics state for layer; may be nullptr\n        @return        depth of saved stack\n    */\n    int saveLayer(const SkRect& bounds, const SkPaint* paint) {\n        return this->saveLayer(&bounds, paint);\n    }\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms),\n        and allocates a SkBitmap for subsequent drawing.\n        LCD text is preserved when the layer is drawn to the prior layer.\n\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        and draws layer.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),\n        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),\n        clipPath(), clipRegion().\n\n        SkRect bounds suggests but does not define the layer size. To clip drawing to\n        a specific rectangle, use clipRect().\n\n        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and\n        SkBlendMode when restore() is called.\n\n        Call restoreToCount() with returned value to restore this and subsequent saves.\n\n        Draw text on an opaque background so that LCD text blends correctly with the\n        prior layer. LCD text drawn on a background with transparency may result in\n        incorrect blending.\n\n        @param bounds  hint to limit the size of layer; may be nullptr\n        @param paint   graphics state for layer; may be nullptr\n        @return        depth of saved stack\n    */\n    int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms),\n        and allocates SkBitmap for subsequent drawing.\n\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        and blends layer with alpha opacity onto prior layer.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),\n        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),\n        clipPath(), clipRegion().\n\n        SkRect bounds suggests but does not define layer size. To clip drawing to\n        a specific rectangle, use clipRect().\n\n        alpha of zero is fully transparent, 255 is fully opaque.\n\n        Call restoreToCount() with returned value to restore this and subsequent saves.\n\n        @param bounds  hint to limit the size of layer; may be nullptr\n        @param alpha   opacity of layer\n        @return        depth of saved stack\n    */\n    int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);\n\n    /** \\enum SkCanvas::SaveLayerFlagsSet\n        SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,\n        defining how layer allocated by saveLayer() operates. It may be set to zero,\n        kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.\n    */\n    enum SaveLayerFlagsSet {\n        kPreserveLCDText_SaveLayerFlag  = 1 << 1, //!< creates layer for LCD text\n        kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents\n        kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag =\n                                          1 << 3, //!< experimental: do not use\n\n#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG\n        kDontClipToLayer_Legacy_SaveLayerFlag =\n           kDontClipToLayer_PrivateSaveLayerFlag, //!< to be deprecated soon\n#endif\n    };\n\n    typedef uint32_t SaveLayerFlags;\n\n    /** \\struct SkCanvas::SaveLayerRec\n        SaveLayerRec contains the state used to create the layer.\n    */\n    struct SaveLayerRec {\n\n        /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.\n\n            @return  empty SaveLayerRec\n        */\n        SaveLayerRec() {}\n\n        /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.\n\n            @param bounds          layer dimensions; may be nullptr\n            @param paint           applied to layer when overlaying prior layer; may be nullptr\n            @param saveLayerFlags  SaveLayerRec options to modify layer\n            @return                SaveLayerRec with empty backdrop\n        */\n        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)\n            : fBounds(bounds)\n            , fPaint(paint)\n            , fSaveLayerFlags(saveLayerFlags)\n        {}\n\n        /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.\n\n            @param bounds          layer dimensions; may be nullptr\n            @param paint           applied to layer when overlaying prior layer;\n                                   may be nullptr\n            @param backdrop        prior layer copied with SkImageFilter; may be nullptr\n            @param saveLayerFlags  SaveLayerRec options to modify layer\n            @return                SaveLayerRec fully specified\n        */\n        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,\n                     SaveLayerFlags saveLayerFlags)\n            : fBounds(bounds)\n            , fPaint(paint)\n            , fBackdrop(backdrop)\n            , fSaveLayerFlags(saveLayerFlags)\n        {}\n\n        /** Experimental. Not ready for general use.\n            Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.\n            clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip\n            layer when drawn to SkCanvas.\n\n            Implementation is not complete; has no effect if SkBaseDevice is GPU-backed.\n\n            @param bounds          layer dimensions; may be nullptr\n            @param paint           graphics state applied to layer when overlaying prior\n                                   layer; may be nullptr\n            @param backdrop        prior layer copied with SkImageFilter;\n                                   may be nullptr\n            @param clipMask        clip applied to layer; may be nullptr\n            @param clipMatrix      matrix applied to clipMask; may be nullptr to use\n                                   identity matrix\n            @param saveLayerFlags  SaveLayerRec options to modify layer\n            @return                SaveLayerRec fully specified\n        */\n        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,\n                     const SkImage* clipMask, const SkMatrix* clipMatrix,\n                     SaveLayerFlags saveLayerFlags)\n            : fBounds(bounds)\n            , fPaint(paint)\n            , fBackdrop(backdrop)\n            , fClipMask(clipMask)\n            , fClipMatrix(clipMatrix)\n            , fSaveLayerFlags(saveLayerFlags)\n        {}\n\n        /** hints at layer size limit */\n        const SkRect*        fBounds         = nullptr;\n\n        /** modifies overlay */\n        const SkPaint*       fPaint          = nullptr;\n\n        /** applies SkImageFilter to prior layer */\n        const SkImageFilter* fBackdrop       = nullptr;\n\n        /** clips layer with mask alpha */\n        const SkImage*       fClipMask       = nullptr;\n\n        /** transforms mask alpha used to clip */\n        const SkMatrix*      fClipMatrix     = nullptr;\n\n        /** preserves LCD text, creates with prior layer contents */\n        SaveLayerFlags       fSaveLayerFlags = 0;\n    };\n\n    /** Saves SkMatrix, clip, and SkDrawFilter (SkDrawFilter deprecated on most platforms),\n        and allocates SkBitmap for subsequent drawing.\n\n        Calling restore() discards changes to SkMatrix, clip, and SkDrawFilter,\n        and blends SkBitmap with alpha opacity onto the prior layer.\n\n        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),\n        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),\n        clipPath(), clipRegion().\n\n        SaveLayerRec contains the state used to create the layer.\n\n        Call restoreToCount() with returned value to restore this and subsequent saves.\n\n        @param layerRec  layer state\n        @return          depth of save state stack\n    */\n    int saveLayer(const SaveLayerRec& layerRec);\n\n    /** Removes changes to SkMatrix, clip, and SkDrawFilter since SkCanvas state was\n        last saved. The state is removed from the stack.\n\n        Does nothing if the stack is empty.\n    */\n    void restore();\n\n    /** Returns the number of saved states, each containing: SkMatrix, clip, and SkDrawFilter.\n        Equals the number of save() calls less the number of restore() calls plus one.\n        The save count of a new canvas is one.\n\n        @return  depth of save state stack\n    */\n    int getSaveCount() const;\n\n    /** Restores state to SkMatrix, clip, and SkDrawFilter values when save(), saveLayer(),\n        saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount.\n\n        Does nothing if saveCount is greater than state stack count.\n        Restores state to initial values if saveCount is less than or equal to one.\n\n        @param saveCount  depth of state stack to restore\n    */\n    void restoreToCount(int saveCount);\n\n    /** Translate SkMatrix by dx along the x-axis and dy along the y-axis.\n\n        Mathematically, replace SkMatrix with a translation matrix\n        premultiplied with SkMatrix.\n\n        This has the effect of moving the drawing by (dx, dy) before transforming\n        the result with SkMatrix.\n\n        @param dx  distance to translate in x\n        @param dy  distance to translate in y\n    */\n    void translate(SkScalar dx, SkScalar dy);\n\n    /** Scale SkMatrix by sx on the x-axis and sy on the y-axis.\n\n        Mathematically, replace SkMatrix with a scale matrix\n        premultiplied with SkMatrix.\n\n        This has the effect of scaling the drawing by (sx, sy) before transforming\n        the result with SkMatrix.\n\n        @param sx  amount to scale in x\n        @param sy  amount to scale in y\n    */\n    void scale(SkScalar sx, SkScalar sy);\n\n    /** Rotate SkMatrix by degrees. Positive degrees rotates clockwise.\n\n        Mathematically, replace SkMatrix with a rotation matrix\n        premultiplied with SkMatrix.\n\n        This has the effect of rotating the drawing by degrees before transforming\n        the result with SkMatrix.\n\n        @param degrees  amount to rotate, in degrees\n    */\n    void rotate(SkScalar degrees);\n\n    /** Rotate SkMatrix by degrees about a point at (px, py). Positive degrees rotates\n        clockwise.\n\n        Mathematically, construct a rotation matrix. Premultiply the rotation matrix by\n        a translation matrix, then replace SkMatrix with the resulting matrix\n        premultiplied with SkMatrix.\n\n        This has the effect of rotating the drawing about a given point before\n        transforming the result with SkMatrix.\n\n        @param degrees  amount to rotate, in degrees\n        @param px       x-coordinate of the point to rotate about\n        @param py       y-coordinate of the point to rotate about\n    */\n    void rotate(SkScalar degrees, SkScalar px, SkScalar py);\n\n    /** Skew SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx\n        skews the drawing right as y increases; a positive value of sy skews the drawing\n        down as x increases.\n\n        Mathematically, replace SkMatrix with a skew matrix premultiplied with SkMatrix.\n\n        This has the effect of skewing the drawing by (sx, sy) before transforming\n        the result with SkMatrix.\n\n        @param sx  amount to skew in x\n        @param sy  amount to skew in y\n    */\n    void skew(SkScalar sx, SkScalar sy);\n\n    /** Replace SkMatrix with matrix premultiplied with existing SkMatrix.\n\n        This has the effect of transforming the drawn geometry by matrix, before\n        transforming the result with existing SkMatrix.\n\n        @param matrix  matrix to premultiply with existing SkMatrix\n    */\n    void concat(const SkMatrix& matrix);\n\n    /** Replace SkMatrix with matrix.\n        Unlike concat(), any prior matrix state is overwritten.\n\n        @param matrix  matrix to copy, replacing existing SkMatrix\n    */\n    void setMatrix(const SkMatrix& matrix);\n\n    /** Sets SkMatrix to the identity matrix.\n        Any prior matrix state is overwritten.\n    */\n    void resetMatrix();\n\n    /** Replace clip with the intersection or difference of clip and rect,\n        with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix\n        before it is combined with clip.\n\n        @param rect         SkRect to combine with clip\n        @param op           SkClipOp to apply to clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);\n\n    /** Replace clip with the intersection or difference of clip and rect.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        rect is transformed by SkMatrix before it is combined with clip.\n\n        @param rect  SkRect to combine with clip\n        @param op    SkClipOp to apply to clip\n    */\n    void clipRect(const SkRect& rect, SkClipOp op) {\n        this->clipRect(rect, op, false);\n    }\n\n    /** Replace clip with the intersection of clip and rect.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        rect is transformed by SkMatrix\n        before it is combined with clip.\n\n        @param rect         SkRect to combine with clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipRect(const SkRect& rect, bool doAntiAlias = false) {\n        this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);\n    }\n\n    /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and\n        clipPath() and intersect the current clip with the specified rect.\n        The maximum clip affects only future clipping operations; it is not retroactive.\n        The clip restriction is not recorded in pictures.\n\n        Pass an empty rect to disable maximum clip.\n        This private API is for use by Android framework only.\n\n        @param rect  maximum allowed clip in device coordinates\n    */\n    void androidFramework_setDeviceClipRestriction(const SkIRect& rect);\n\n    /** Replace clip with the intersection or difference of clip and rrect,\n        with an aliased or anti-aliased clip edge.\n        rrect is transformed by SkMatrix\n        before it is combined with clip.\n\n        @param rrect        SkRRect to combine with clip\n        @param op           SkClipOp to apply to clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);\n\n    /** Replace clip with the intersection or difference of clip and rrect.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        rrect is transformed by SkMatrix before it is combined with clip.\n\n        @param rrect  SkRRect to combine with clip\n        @param op     SkClipOp to apply to clip\n    */\n    void clipRRect(const SkRRect& rrect, SkClipOp op) {\n        this->clipRRect(rrect, op, false);\n    }\n\n    /** Replace clip with the intersection of clip and rrect,\n        with an aliased or anti-aliased clip edge.\n        rrect is transformed by SkMatrix before it is combined with clip.\n\n        @param rrect        SkRRect to combine with clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {\n        this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);\n    }\n\n    /** Replace clip with the intersection or difference of clip and path,\n        with an aliased or anti-aliased clip edge. SkPath::FillType determines if path\n        describes the area inside or outside its contours; and if path contour overlaps\n        itself or another path contour, whether the overlaps form part of the area.\n        path is transformed by SkMatrix before it is combined with clip.\n\n        @param path         SkPath to combine with clip\n        @param op           SkClipOp to apply to clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);\n\n    /** Replace clip with the intersection or difference of clip and path.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        SkPath::FillType determines if path\n        describes the area inside or outside its contours; and if path contour overlaps\n        itself or another path contour, whether the overlaps form part of the area.\n        path is transformed by SkMatrix\n        before it is combined with clip.\n\n        @param path  SkPath to combine with clip\n        @param op    SkClipOp to apply to clip\n    */\n    void clipPath(const SkPath& path, SkClipOp op) {\n        this->clipPath(path, op, false);\n    }\n\n    /** Replace clip with the intersection of clip and path.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        SkPath::FillType determines if path\n        describes the area inside or outside its contours; and if path contour overlaps\n        itself or another path contour, whether the overlaps form part of the area.\n        path is transformed by SkMatrix before it is combined with clip.\n\n        @param path         SkPath to combine with clip\n        @param doAntiAlias  true if clip is to be anti-aliased\n    */\n    void clipPath(const SkPath& path, bool doAntiAlias = false) {\n        this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);\n    }\n\n    /** Experimental. For testing only.\n        Set to simplify clip stack using PathOps.\n    */\n    void setAllowSimplifyClip(bool allow) {\n        fAllowSimplifyClip = allow;\n    }\n\n    /** Replace clip with the intersection or difference of clip and SkRegion deviceRgn.\n        Resulting clip is aliased; pixels are fully contained by the clip.\n        deviceRgn is unaffected by SkMatrix.\n\n        @param deviceRgn  SkRegion to combine with clip\n        @param op         SkClipOp to apply to clip\n    */\n    void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);\n\n    /** Return true if SkRect rect, transformed by SkMatrix, can be quickly determined to be\n        outside of clip. May return false even though rect is outside of clip.\n\n        Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.\n\n        @param rect  SkRect to compare with clip\n        @return      true if rect, transformed by SkMatrix, does not intersect clip\n    */\n    bool quickReject(const SkRect& rect) const;\n\n    /** Return true if path, transformed by SkMatrix, can be quickly determined to be\n        outside of clip. May return false even though path is outside of clip.\n\n        Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.\n\n        @param path  SkPath to compare with clip\n        @return      true if path, transformed by SkMatrix, does not intersect clip\n    */\n    bool quickReject(const SkPath& path) const;\n\n    /** Return bounds of clip, transformed by inverse of SkMatrix. If clip is empty,\n        return SkRect::MakeEmpty, where all SkRect sides equal zero.\n\n        SkRect returned is outset by one to account for partial pixel coverage if clip\n        is anti-aliased.\n\n        @return  bounds of clip in local coordinates\n    */\n    SkRect getLocalClipBounds() const;\n\n    /** Return bounds of clip, transformed by inverse of SkMatrix. If clip is empty,\n        return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.\n\n        bounds is outset by one to account for partial pixel coverage if clip\n        is anti-aliased.\n\n        @param bounds  SkRect of clip in local coordinates\n        @return        true if clip bounds is not empty\n    */\n    bool getLocalClipBounds(SkRect* bounds) const {\n        *bounds = this->getLocalClipBounds();\n        return !bounds->isEmpty();\n    }\n\n    /** Return SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,\n        return SkRect::MakeEmpty, where all SkRect sides equal zero.\n\n        Unlike getLocalClipBounds(), returned SkIRect is not outset.\n\n        @return  bounds of clip in SkBaseDevice coordinates\n    */\n    SkIRect getDeviceClipBounds() const;\n\n    /** Return SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,\n        return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.\n\n        Unlike getLocalClipBounds(), bounds is not outset.\n\n        @param bounds  SkRect of clip in device coordinates\n        @return        true if clip bounds is not empty\n    */\n    bool getDeviceClipBounds(SkIRect* bounds) const {\n        *bounds = this->getDeviceClipBounds();\n        return !bounds->isEmpty();\n    }\n\n    /** Fill clip with color color.\n        mode determines how ARGB is combined with destination.\n\n        @param color  unpremultiplied ARGB\n        @param mode   SkBlendMode used to combine source color and destination\n    */\n    void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);\n\n    /** Fill clip with color color using SkBlendMode::kSrc.\n        This has the effect of replacing all pixels contained by clip with color.\n\n        @param color  unpremultiplied ARGB\n    */\n    void clear(SkColor color) {\n        this->drawColor(color, SkBlendMode::kSrc);\n    }\n\n    /** Make SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels,\n        such as drawing with SkBlendMode, return undefined results. discard() does\n        not change clip or SkMatrix.\n\n        discard() may do nothing, depending on the implementation of SkSurface or SkBaseDevice\n        that created SkCanvas.\n\n        discard() allows optimized performance on subsequent draws by removing\n        cached data associated with SkSurface or SkBaseDevice.\n        It is not necessary to call discard() once done with SkCanvas;\n        any cached data is deleted when owning SkSurface or SkBaseDevice is deleted.\n    */\n    void discard() { this->onDiscard(); }\n\n    /** Fill clip with SkPaint paint. SkPaint components SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkBlendMode affect drawing;\n        SkPathEffect in paint is ignored.\n\n        @param paint  graphics state used to fill SkCanvas\n    */\n    void drawPaint(const SkPaint& paint);\n\n    /** \\enum SkCanvas::PointMode\n        Selects if an array of points are drawn as discrete points, as lines, or as\n        an open polygon.\n    */\n    enum PointMode {\n        kPoints_PointMode,  //!< draw each point separately\n        kLines_PointMode,   //!< draw each pair of points as a line segment\n        kPolygon_PointMode, //!< draw the array of points as a open polygon\n    };\n\n    /** Draw pts using clip, SkMatrix and SkPaint paint.\n        count is the number of points; if count is less than one, has no effect.\n        mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.\n\n        If mode is kPoints_PointMode, the shape of point drawn depends on paint\n        SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a\n        circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap\n        or SkPaint::kButt_Cap, each point draws a square of width and height\n        SkPaint stroke width.\n\n        If mode is kLines_PointMode, each pair of points draws a line segment.\n        One line is drawn for every two points; each point is used once. If count is odd,\n        the final point is ignored.\n\n        If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.\n        count minus one lines are drawn; the first and last point are used once.\n\n        Each line segment respects paint SkPaint::Cap and SkPaint stroke width.\n        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.\n\n        Always draws each element one at a time; is not affected by\n        SkPaint::Join, and unlike drawPath(), does not create a mask from all points\n        and lines before drawing.\n\n        @param mode   whether pts draws points or lines\n        @param count  number of points in the array\n        @param pts    array of points to draw\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);\n\n    /** Draw point at (x, y) using clip, SkMatrix and SkPaint paint.\n\n        The shape of point drawn depends on paint SkPaint::Cap.\n        If paint is set to SkPaint::kRound_Cap, draw a circle of diameter\n        SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,\n        draw a square of width and height SkPaint stroke width.\n        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.\n\n        @param x      left edge of circle or square\n        @param y      top edge of circle or square\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);\n\n    /** Draw point p using clip, SkMatrix and SkPaint paint.\n\n        The shape of point drawn depends on paint SkPaint::Cap.\n        If paint is set to SkPaint::kRound_Cap, draw a circle of diameter\n        SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,\n        draw a square of width and height SkPaint stroke width.\n        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.\n\n        @param p      top-left edge of circle or square\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawPoint(SkPoint p, const SkPaint& paint) {\n        this->drawPoint(p.x(), p.y(), paint);\n    }\n\n    /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint stroke width describes the line thickness;\n        SkPaint::Cap draws the end rounded or square;\n        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.\n\n        @param x0     start of line segment on x-axis\n        @param y0     start of line segment on y-axis\n        @param x1     end of line segment on x-axis\n        @param y1     end of line segment on y-axis\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);\n\n    /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint stroke width describes the line thickness;\n        SkPaint::Cap draws the end rounded or square;\n        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.\n\n        @param p0     start of line segment\n        @param p1     end of line segment\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {\n        this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);\n    }\n\n    /** Draw SkRect rect using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint::Style determines if rectangle is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness, and\n        SkPaint::Join draws the corners rounded or square.\n\n        @param rect   rectangle to draw\n        @param paint  stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawRect(const SkRect& rect, const SkPaint& paint);\n\n    /** Draw SkIRect rect using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint::Style determines if rectangle is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness, and\n        SkPaint::Join draws the corners rounded or square.\n\n        @param rect   rectangle to draw\n        @param paint  stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawIRect(const SkIRect& rect, const SkPaint& paint) {\n        SkRect r;\n        r.set(rect);    // promotes the ints to scalars\n        this->drawRect(r, paint);\n    }\n\n    /** Draw SkRegion region using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint::Style determines if rectangle is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness, and\n        SkPaint::Join draws the corners rounded or square.\n\n        @param region  region to draw\n        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawRegion(const SkRegion& region, const SkPaint& paint);\n\n    /** Draw oval oval using clip, SkMatrix, and SkPaint.\n        In paint: SkPaint::Style determines if oval is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n\n        @param oval   SkRect bounds of oval\n        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawOval(const SkRect& oval, const SkPaint& paint);\n\n    /** Draw SkRRect rrect using clip, SkMatrix, and SkPaint paint.\n        In paint: SkPaint::Style determines if rrect is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n\n        rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or\n        may have any combination of positive non-square radii for the four corners.\n\n        @param rrect  SkRRect with up to eight corner radii to draw\n        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawRRect(const SkRRect& rrect, const SkPaint& paint);\n\n    /** Draw SkRRect outer and inner\n        using clip, SkMatrix, and SkPaint paint.\n        outer must contain inner or the drawing is undefined.\n        In paint: SkPaint::Style determines if SkRRect is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n        If stroked and SkRRect corner has zero length radii, SkPaint::Join can\n        draw corners rounded or square.\n\n        GPU-backed platforms optimize drawing when both outer and inner are\n        concave and outer contains inner. These platforms may not be able to draw\n        SkPath built with identical data as fast.\n\n        @param outer  SkRRect outer bounds to draw\n        @param inner  SkRRect inner bounds to draw\n        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);\n\n    /** Draw circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint.\n        If radius is zero or less, nothing is drawn.\n        In paint: SkPaint::Style determines if circle is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n\n        @param cx      circle center on the x-axis\n        @param cy      circle center on the y-axis\n        @param radius  half the diameter of circle\n        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);\n\n    /** Draw circle at center with radius using clip, SkMatrix, and SkPaint paint.\n        If radius is zero or less, nothing is drawn.\n        In paint: SkPaint::Style determines if circle is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n\n        @param center  circle center\n        @param radius  half the diameter of circle\n        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {\n        this->drawCircle(center.x(), center.y(), radius, paint);\n    }\n\n    /** Draw arc using clip, SkMatrix, and SkPaint paint.\n\n        Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus\n        sweepAngle. startAngle and sweepAngle are in degrees.\n\n        startAngle of zero places start point at the right middle edge of oval.\n        A positive sweepAngle places arc end point clockwise from start point;\n        a negative sweepAngle places arc end point counterclockwise from start point.\n        sweepAngle may exceed 360 degrees, a full circle.\n        If useCenter is true, draw a wedge that includes lines from oval\n        center to arc end points. If useCenter is false, draw arc between end points.\n\n        If SkRect oval is empty or sweepAngle is zero, nothing is drawn.\n\n        @param oval        SkRect bounds of oval containing arc to draw\n        @param startAngle  angle in degrees where arc begins\n        @param sweepAngle  sweep angle in degrees; positive is clockwise\n        @param useCenter   if true, include the center of the oval\n        @param paint       SkPaint stroke or fill, blend, color, and so on, used to draw\n    */\n    void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,\n                 bool useCenter, const SkPaint& paint);\n\n    /** Draw SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip,\n        SkMatrix, and SkPaint paint.\n\n        In paint: SkPaint::Style determines if SkRRect is stroked or filled;\n        if stroked, SkPaint stroke width describes the line thickness.\n        If rx or ry are less than zero, they are treated as if they are zero.\n        If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.\n        If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by\n        SkPaint::Join.\n\n        @param rect   SkRect bounds of SkRRect to draw\n        @param rx     axis length in x of oval describing rounded corners\n        @param ry     axis length in y of oval describing rounded corners\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);\n\n    /** Draw SkPath path using clip, SkMatrix, and SkPaint paint.\n        SkPath contains an array of path contour, each of which may be open or closed.\n\n        In paint: SkPaint::Style determines if SkRRect is stroked or filled:\n        if filled, SkPath::FillType determines whether path contour describes inside or\n        outside of fill; if stroked, SkPaint stroke width describes the line thickness,\n        SkPaint::Cap describes line ends, and SkPaint::Join describes how\n        corners are drawn.\n\n        @param path   SkPath to draw\n        @param paint  stroke, blend, color, and so on, used to draw\n    */\n    void drawPath(const SkPath& path, const SkPaint& paint);\n\n    /** Draw SkImage image, with its top-left corner at (left, top),\n        using clip, SkMatrix, and optional SkPaint paint.\n\n        If paint is supplied, apply SkColorFilter, alpha, SkImageFilter, SkBlendMode,\n        and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds. If generated\n        mask extends beyond image bounds, replicate image edge colors, just as SkShader\n        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the\n        image edge color when it samples outside of its bounds.\n\n        @param image  uncompressed rectangular map of pixels\n        @param left   left side of image\n        @param top    top side of image\n        @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                      and so on; or nullptr\n    */\n    void drawImage(const SkImage* image, SkScalar left, SkScalar top,\n                   const SkPaint* paint = nullptr);\n\n    /** Draw SkImage image, with its top-left corner at (left, top),\n        using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds. If generated\n        mask extends beyond image bounds, replicate image edge colors, just as SkShader\n        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the\n        image edge color when it samples outside of its bounds.\n\n        @param image  uncompressed rectangular map of pixels\n        @param left   left side of image\n        @param top    pop side of image\n        @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                      and so on; or nullptr\n    */\n    void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,\n                   const SkPaint* paint = nullptr) {\n        this->drawImage(image.get(), left, top, paint);\n    }\n\n    /** \\enum SkCanvas::SrcRectConstraint\n        SrcRectConstraint controls the behavior at the edge of source SkRect,\n        provided to drawImageRect(), trading off speed for precision.\n\n        SkImageFilter in SkPaint may sample multiple pixels in the image. Source SkRect\n        restricts the bounds of pixels that may be read. SkImageFilter may slow down if\n        it cannot read outside the bounds, when sampling near the edge of source SkRect.\n        SrcRectConstraint specifies whether an SkImageFilter is allowed to read pixels\n        outside source SkRect.\n    */\n    enum SrcRectConstraint {\n        kStrict_SrcRectConstraint, //!< sample only inside bounds; slower\n        kFast_SrcRectConstraint,   //!< sample outside bounds; faster\n    };\n\n    /** Draw SkRect src of SkImage image, scaled and translated to fill SkRect dst.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within src; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param src         source SkRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within src or draw faster\n    */\n    void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,\n                       const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkIRect isrc of SkImage image, scaled and translated to fill SkRect dst.\n        Note that isrc is on integer pixel boundaries; dst may include fractional\n        boundaries. Additionally transform draw using clip, SkMatrix, and optional SkPaint\n        paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param isrc        source SkIRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within isrc or draw faster\n    */\n    void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,\n                       const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkImage image, scaled and translated to fill SkRect dst, using clip, SkMatrix,\n        and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within image; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within image or draw faster\n    */\n    void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkRect src of SkImage image, scaled and translated to fill SkRect dst.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within src; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param src         source SkRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within src or draw faster\n    */\n    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,\n                       const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {\n        this->drawImageRect(image.get(), src, dst, paint, constraint);\n    }\n\n    /** Draw SkIRect isrc of SkImage image, scaled and translated to fill SkRect dst.\n        isrc is on integer pixel boundaries; dst may include fractional boundaries.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within image; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param isrc        source SkIRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within image or draw faster\n    */\n    void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,\n                       const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {\n        this->drawImageRect(image.get(), isrc, dst, paint, constraint);\n    }\n\n    /** Draw SkImage image, scaled and translated to fill SkRect dst,\n        using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within image; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param image       SkImage containing pixels, dimensions, and format\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within image or draw faster\n    */\n    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,\n                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {\n        this->drawImageRect(image.get(), dst, paint, constraint);\n    }\n\n    /** Draw SkImage image stretched proportionally to fit into SkRect dst.\n        SkIRect center divides the image into nine sections: four sides, four corners, and\n        the center. Corners are unmodified or scaled down proportionately if their sides\n        are larger than dst; center and four sides are scaled to fit remaining space, if any.\n\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds. If paint\n        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all\n        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.\n        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        @param image   SkImage containing pixels, dimensions, and format\n        @param center  SkIRect edge of image corners and sides\n        @param dst     destination SkRect of image to draw to\n        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                       and so on; or nullptr\n    */\n    void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,\n                       const SkPaint* paint = nullptr);\n\n    /** Draw SkImage image stretched proportionally to fit into SkRect dst.\n        SkIRect center divides the image into nine sections: four sides, four corners, and\n        the center. Corners are not scaled, or scaled down proportionately if their sides\n        are larger than dst; center and four sides are scaled to fit remaining space, if any.\n\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds. If paint\n        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all\n        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.\n        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.\n\n        If generated mask extends beyond image bounds, replicate image edge colors, just\n        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set\n        replicates the image edge color when it samples outside of its bounds.\n\n        @param image   SkImage containing pixels, dimensions, and format\n        @param center  SkIRect edge of image corners and sides\n        @param dst     destination SkRect of image to draw to\n        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                       and so on; or nullptr\n    */\n    void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,\n                       const SkPaint* paint = nullptr) {\n        this->drawImageNine(image.get(), center, dst, paint);\n    }\n\n    /** Draw SkBitmap bitmap, with its top-left corner at (left, top),\n        using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        @param bitmap  SkBitmap containing pixels, dimensions, and format\n        @param left    left side of bitmap\n        @param top     top side of bitmap\n        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                       and so on; or nullptr\n    */\n    void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,\n                    const SkPaint* paint = nullptr);\n\n    /** Draw SkRect src of SkBitmap bitmap, scaled and translated to fill SkRect dst.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within src; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param bitmap      SkBitmap containing pixels, dimensions, and format\n        @param src         source SkRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within src or draw faster\n    */\n    void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,\n                        const SkPaint* paint,\n                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkIRect isrc of SkBitmap bitmap, scaled and translated to fill SkRect dst.\n        isrc is on integer pixel boundaries; dst may include fractional boundaries.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param bitmap      SkBitmap containing pixels, dimensions, and format\n        @param isrc        source SkIRect of image to draw from\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  sample strictly within isrc, or draw faster\n    */\n    void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,\n                        const SkPaint* paint,\n                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkBitmap bitmap, scaled and translated to fill SkRect dst.\n        bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to\n        sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to\n        improve performance.\n\n        @param bitmap      SkBitmap containing pixels, dimensions, and format\n        @param dst         destination SkRect of image to draw to\n        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                           and so on; or nullptr\n        @param constraint  filter strictly within bitmap or draw faster\n    */\n    void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,\n                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /** Draw SkBitmap bitmap stretched proportionally to fit into SkRect dst.\n        SkIRect center divides the bitmap into nine sections: four sides, four corners,\n        and the center. Corners are not scaled, or scaled down proportionately if their\n        sides are larger than dst; center and four sides are scaled to fit remaining\n        space, if any.\n\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint\n        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all\n        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.\n        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        @param bitmap  SkBitmap containing pixels, dimensions, and format\n        @param center  SkIRect edge of image corners and sides\n        @param dst     destination SkRect of image to draw to\n        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                       and so on; or nullptr\n    */\n    void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,\n                        const SkPaint* paint = nullptr);\n\n    /** \\struct SkCanvas::Lattice\n        SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid.\n        Grid entries on even columns and even rows are fixed; these entries are\n        always drawn at their original size if the destination is large enough.\n        If the destination side is too small to hold the fixed entries, all fixed\n        entries are proportionately scaled down to fit.\n        The grid entries not on even columns and rows are scaled to fit the\n        remaining space, if any.\n    */\n    struct Lattice {\n\n        /** \\enum SkCanvas::Lattice::RectType\n            Optional setting per rectangular grid entry to make it transparent,\n            or to fill the grid entry with a color.\n        */\n        enum RectType : uint8_t {\n            kDefault     = 0, //!< draws SkBitmap into lattice rectangle\n            kTransparent,     //!< skips lattice rectangle by making it transparent\n            kFixedColor,      //!< draws one of fColors into lattice rectangle\n        };\n\n        const int*      fXDivs;     //!< x-coordinates dividing bitmap\n        const int*      fYDivs;     //!< y-coordinates dividing bitmap\n        const RectType* fRectTypes; //!< array of fill types\n        int             fXCount;    //!< number of x-coordinates\n        int             fYCount;    //!< number of y-coordinates\n        const SkIRect*  fBounds;    //!< source bounds to draw from\n        const SkColor*  fColors;    //!< array of colors\n    };\n\n    /** Draw SkBitmap bitmap stretched proportionally to fit into SkRect dst.\n\n        SkCanvas::Lattice lattice divides bitmap into a rectangular grid.\n        Each intersection of an even-numbered row and column is fixed; like the corners\n        of drawBitmapNine(), fixed lattice elements never scale larger than their initial\n        size and shrink proportionately when all fixed elements exceed the bitmap\n        dimension. All other grid elements scale to fill the available space, if any.\n\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint\n        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all\n        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.\n        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        @param bitmap   SkBitmap containing pixels, dimensions, and format\n        @param lattice  division of bitmap into fixed and variable rectangles\n        @param dst      destination SkRect of image to draw to\n        @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                        and so on; or nullptr\n    */\n    void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,\n                           const SkPaint* paint = nullptr);\n\n    /** Draw SkImage image stretched proportionally to fit into SkRect dst.\n\n        SkCanvas::Lattice lattice divides image into a rectangular grid.\n        Each intersection of an even-numbered row and column is fixed; like the corners\n        of drawBitmapNine(), fixed lattice elements never scale larger than their initial\n        size and shrink proportionately when all fixed elements exceed the bitmap\n        dimension. All other grid elements scale to fill the available space, if any.\n\n        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.\n\n        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.\n        If paint contains SkMaskFilter, generate mask from image bounds. If paint\n        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all\n        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.\n        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.\n\n        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,\n        just as SkShader made from SkShader::MakeBitmapShader with\n        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples\n        outside of its bounds.\n\n        @param image    SkImage containing pixels, dimensions, and format\n        @param lattice  division of bitmap into fixed and variable rectangles\n        @param dst      destination SkRect of image to draw to\n        @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                        and so on; or nullptr\n    */\n    void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,\n                          const SkPaint* paint = nullptr);\n\n    /** Draw text, with origin at (x, y), using clip, SkMatrix, and SkPaint paint.\n\n        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as\n        UTF-8.\n\n        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default\n        text draws left to right, positioning the first glyph left side bearing at x\n        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param x           start of text on x-axis\n        @param y           start of text on y-axis\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,\n                  const SkPaint& paint);\n\n    /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and\n        SkPaint paint.\n\n        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded\n        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired\n        results, since zero bytes may be embedded in the string.\n\n        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default\n        string draws left to right, positioning the first glyph left side bearing at x\n        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param string  character code points or glyphs drawn,\n                       ending with a char value of zero\n        @param x       start of string on x-axis\n        @param y       start of string on y-axis\n        @param paint   text size, blend, color, and so on, used to draw\n    */\n    void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint) {\n        if (!string) {\n            return;\n        }\n        this->drawText(string, strlen(string), x, y, paint);\n    }\n\n    /** Draw null terminated string, with origin at (x, y), using clip, SkMatrix, and\n        SkPaint paint.\n\n        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded\n        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired\n        results, since zero bytes may be embedded in the string.\n\n        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default\n        string draws left to right, positioning the first glyph left side bearing at x\n        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param string  character code points or glyphs drawn,\n                       ending with a char value of zero\n        @param x       start of string on x-axis\n        @param y       start of string on y-axis\n        @param paint   text size, blend, color, and so on, used to draw\n    */\n    void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint);\n\n    /** Draw each glyph in text with the origin in pos array, using clip, SkMatrix, and\n        SkPaint paint. The number of entries in pos array must match the number of glyphs\n        described by byteLength of text.\n\n        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as\n        UTF-8. pos elements meaning depends on SkPaint vertical text;\n        by default each glyph left side bearing is positioned at x and its\n        baseline is positioned at y. Text size is affected by SkMatrix and\n        SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        Layout engines such as Harfbuzz typically position each glyph\n        rather than using the font advance widths.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param pos         array of glyph origins\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],\n                     const SkPaint& paint);\n\n    /** Draw each glyph in text with its (x, y) origin composed from xpos array and\n        constY, using clip, SkMatrix, and SkPaint paint. The number of entries in xpos array\n        must match the number of glyphs described by byteLength of text.\n\n        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as\n        UTF-8. xpos elements meaning depends on SkPaint vertical text;\n        by default each glyph left side bearing is positioned at an xpos element and\n        its baseline is positioned at constY. Text size is affected by SkMatrix and\n        SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        Layout engines such as Harfbuzz typically position each glyph\n        rather than using the font advance widths if all glyphs share the same\n        baseline.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param xpos        array of x positions, used to position each glyph\n        @param constY      shared y coordinate for all of x positions\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,\n                      const SkPaint& paint);\n\n    /** Draw text on SkPath path, using clip, SkMatrix, and SkPaint paint.\n\n        Origin of text is at distance hOffset along the path, offset by a perpendicular\n        vector of length vOffset. If the path section corresponding the glyph advance is\n        curved, the glyph is drawn curved to match; control points in the glyph are\n        mapped to projected points parallel to the path. If the text advance is larger\n        than the path length, the excess text is clipped.\n\n        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as\n        UTF-8. Origin meaning depends on SkPaint::Align and SkPaint vertical text; by\n        default text positions the first glyph left side bearing at origin x and its\n        baseline at origin y. Text size is affected by SkMatrix and SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param path        SkPath providing text baseline\n        @param hOffset     distance along path to offset origin\n        @param vOffset     offset of text above (if negative) or below (if positive) the path\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,\n                          SkScalar vOffset, const SkPaint& paint);\n\n    /** Draw text on SkPath path, using clip, SkMatrix, and SkPaint paint.\n\n        Origin of text is at beginning of path offset by matrix, if not nullptr.\n        matrix transforms text before text is mapped to path. If the path section\n        corresponding the glyph advance is curved, the glyph is drawn curved to match;\n        control points in the glyph are mapped to projected points parallel to the path.\n        If the text advance is larger than the path length, the excess text is clipped.\n\n        matrix does not effect paint SkShader.\n\n        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as\n        UTF-8. Origin meaning depends on SkPaint::Align and SkPaint vertical text; by\n        default text positions the first glyph left side bearing at origin x and its\n        baseline at origin y. Text size is affected by matrix parameter, SkCanvas SkMatrix,\n        and SkPaint text size.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param path        SkPath providing text baseline\n        @param matrix      transform of glyphs before mapping to path; may be nullptr\n                           to use identity SkMatrix\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,\n                        const SkMatrix* matrix, const SkPaint& paint);\n\n    /** Draw text, transforming each glyph by the corresponding SkRSXform,\n        using clip, SkMatrix, and SkPaint paint.\n\n        SkRSXform xform array specifies a separate square scale, rotation, and translation\n        for each glyph. xform does not affect paint SkShader.\n\n        Optional SkRect cullRect is a conservative bounds of text, taking into account\n        SkRSXform and paint. If cullRect is outside of clip, canvas can skip drawing.\n\n        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,\n        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws\n        filled 12 point black glyphs.\n\n        @param text        character code points or glyphs drawn\n        @param byteLength  byte length of text array\n        @param xform       SkRSXform rotates, scales, and translates each glyph individually\n        @param cullRect    SkRect bounds of text for efficient clipping; or nullptr\n        @param paint       text size, blend, color, and so on, used to draw\n    */\n    void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                         const SkRect* cullRect, const SkPaint& paint);\n\n    /** Draw SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.\n\n        blob contains glyphs, their positions, and paint attributes specific to text:\n        SkTypeface, SkPaint text size, SkPaint text scale x, SkPaint text skew x,\n        SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,\n        SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,\n        SkPaint subpixel text, and SkPaint vertical text.\n\n        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.\n\n        Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,\n        SkImageFilter, and SkDrawLooper; apply to blob.\n\n        @param blob   glyphs, positions, and their paints' text size, typeface, and so on\n        @param x      horizontal offset applied to blob\n        @param y      vertical offset applied to blob\n        @param paint  blend, color, stroking, and so on, used to draw\n    */\n    void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);\n\n    /** Draw SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.\n\n        blob contains glyphs, their positions, and paint attributes specific to text:\n        SkTypeface, SkPaint text size, SkPaint text scale x, SkPaint text skew x,\n        SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,\n        SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,\n        SkPaint subpixel text, and SkPaint vertical text.\n\n        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.\n\n        Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,\n        SkImageFilter, and SkDrawLooper; apply to blob.\n\n        @param blob   glyphs, positions, and their paints' text size, typeface, and so on\n        @param x      horizontal offset applied to blob\n        @param y      vertical offset applied to blob\n        @param paint  blend, color, stroking, and so on, used to draw\n    */\n    void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {\n        this->drawTextBlob(blob.get(), x, y, paint);\n    }\n\n    /** Draw SkPicture picture, using clip and SkMatrix.\n        Clip and SkMatrix are unchanged by picture contents, as if\n        save() was called before and restore() was called after drawPicture().\n\n        SkPicture records a series of draw commands for later playback.\n\n        @param picture  recorded drawing commands to play\n    */\n    void drawPicture(const SkPicture* picture) {\n        this->drawPicture(picture, nullptr, nullptr);\n    }\n\n    /** Draw SkPicture picture, using clip and SkMatrix.\n        Clip and SkMatrix are unchanged by picture contents, as if\n        save() was called before and restore() was called after drawPicture().\n\n        SkPicture records a series of draw commands for later playback.\n\n        @param picture  recorded drawing commands to play\n    */\n    void drawPicture(const sk_sp<SkPicture>& picture) {\n        this->drawPicture(picture.get());\n    }\n\n    /** Draw SkPicture picture, using clip and SkMatrix; transforming picture with\n        SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,\n        SkImageFilter, and SkBlendMode, if provided.\n\n        matrix transformation is equivalent to: save(), concat(), drawPicture(), restore().\n        paint use is equivalent to: saveLayer(), drawPicture(), restore().\n\n        @param picture  recorded drawing commands to play\n        @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr\n        @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr\n    */\n    void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);\n\n    /** Draw SkPicture picture, using clip and SkMatrix; transforming picture with\n        SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,\n        SkImageFilter, and SkBlendMode, if provided.\n\n        matrix transformation is equivalent to: save(), concat(), drawPicture(), restore().\n        paint use is equivalent to: saveLayer(), drawPicture(), restore().\n\n        @param picture  recorded drawing commands to play\n        @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr\n        @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr\n    */\n    void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) {\n        this->drawPicture(picture.get(), matrix, paint);\n    }\n\n    /** Draw SkVertices vertices, a triangle mesh, using clip and SkMatrix.\n        If vertices texs and vertices colors are defined in vertices, and SkPaint paint\n        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.\n\n        @param vertices  triangle mesh to draw\n        @param mode      combines vertices colors with SkShader, if both are present\n        @param paint     specifies the SkShader, used as SkVertices texture; may be nullptr\n    */\n    void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);\n\n    /** Draw SkVertices vertices, a triangle mesh, using clip and SkMatrix.\n        If vertices texs and vertices colors are defined in vertices, and SkPaint paint\n        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.\n\n        @param vertices  triangle mesh to draw\n        @param mode      combines vertices colors with SkShader, if both are present\n        @param paint     specifies the SkShader, used as SkVertices texture, may be nullptr\n    */\n    void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);\n\n    /** Draws a Coons_Patch: the interpolation of four cubics with shared corners,\n        associating a color, and optionally a texture coordinate, with each corner.\n\n        Coons_Patch uses clip and SkMatrix, paint SkShader, SkColorFilter,\n        alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated\n        as Coons_Patch texture; SkBlendMode mode combines color colors and SkShader if\n        both are provided.\n\n        SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,\n        in clockwise order, sharing every fourth point. The last SkPath cubic ends at the\n        first point.\n\n        Color array color associates colors with corners in top-left, top-right,\n        bottom-right, bottom-left order.\n\n        If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to\n        corners in top-left, top-right, bottom-right, bottom-left order.\n\n        @param cubics     SkPath cubic array, sharing common points\n        @param colors     color array, one for each corner\n        @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;\n                          may be nullptr\n        @param mode       SkBlendMode for colors, and for SkShader if paint has one\n        @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw\n    */\n    void drawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                   const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);\n\n    /** Draws SkPath cubic Coons_Patch: the interpolation of four cubics with shared corners,\n        associating a color, and optionally a texture coordinate, with each corner.\n\n        Coons_Patch uses clip and SkMatrix, paint SkShader, SkColorFilter,\n        alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated\n        as Coons_Patch texture; SkBlendMode mode combines color colors and SkShader if\n        both are provided.\n\n        SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,\n        in clockwise order, sharing every fourth point. The last SkPath cubic ends at the\n        first point.\n\n        Color array color associates colors with corners in top-left, top-right,\n        bottom-right, bottom-left order.\n\n        If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to\n        corners in top-left, top-right, bottom-right, bottom-left order.\n\n        @param cubics     SkPath cubic array, sharing common points\n        @param colors     color array, one for each corner\n        @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;\n                          may be nullptr\n        @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw\n    */\n    void drawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                   const SkPoint texCoords[4], const SkPaint& paint) {\n        this->drawPatch(cubics, colors, texCoords, SkBlendMode::kModulate, paint);\n    }\n\n    /** Draw a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.\n        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode\n        to draw, if present. For each entry in the array, SkRect tex locates sprite in\n        atlas, and SkRSXform xform transforms it into destination space.\n\n        xform, text, and colors if present, must contain count entries.\n        Optional colors are applied for each sprite using SkBlendMode.\n        Optional cullRect is a conservative bounds of all transformed sprites.\n        If cullRect is outside of clip, canvas can skip drawing.\n\n        @param atlas     SkImage containing sprites\n        @param xform     SkRSXform mappings for sprites in atlas\n        @param tex       SkRect locations of sprites in atlas\n        @param colors    one per sprite, blended with sprite using SkBlendMode; may be nullptr\n        @param count     number of sprites to draw\n        @param mode      SkBlendMode combining colors and sprites\n        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr\n        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr\n    */\n    void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],\n                   const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,\n                   const SkPaint* paint);\n\n    /** Draw a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.\n        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode\n        to draw, if present. For each entry in the array, SkRect tex locates sprite in\n        atlas, and SkRSXform xform transforms it into destination space.\n\n        xform, text, and colors if present, must contain count entries.\n        Optional colors is applied for each sprite using SkBlendMode.\n        Optional cullRect is a conservative bounds of all transformed sprites.\n        If cullRect is outside of clip, canvas can skip drawing.\n\n        @param atlas     SkImage containing sprites\n        @param xform     SkRSXform mappings for sprites in atlas\n        @param tex       SkRect locations of sprites in atlas\n        @param colors    one per sprite, blended with sprite using SkBlendMode; may be nullptr\n        @param count     number of sprites to draw\n        @param mode      SkBlendMode combining colors and sprites\n        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr\n        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr\n    */\n    void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],\n                   const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,\n                   const SkPaint* paint) {\n        this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cullRect, paint);\n    }\n\n    /** Draw a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.\n        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode\n        to draw, if present. For each entry in the array, SkRect tex locates sprite in\n        atlas, and SkRSXform xform transforms it into destination space.\n\n        xform and text must contain count entries.\n        Optional cullRect is a conservative bounds of all transformed sprites.\n        If cullRect is outside of clip, canvas can skip drawing.\n\n        @param atlas     SkImage containing sprites\n        @param xform     SkRSXform mappings for sprites in atlas\n        @param tex       SkRect locations of sprites in atlas\n        @param count     number of sprites to draw\n        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr\n        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr\n    */\n    void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,\n                   const SkRect* cullRect, const SkPaint* paint) {\n        this->drawAtlas(atlas, xform, tex, nullptr, count, SkBlendMode::kDst, cullRect, paint);\n    }\n\n    /** Draw a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.\n        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode\n        to draw, if present. For each entry in the array, SkRect tex locates sprite in\n        atlas, and SkRSXform xform transforms it into destination space.\n\n        xform and text must contain count entries.\n        Optional cullRect is a conservative bounds of all transformed sprites.\n        If cullRect is outside of clip, canvas can skip drawing.\n\n        @param atlas     SkImage containing sprites\n        @param xform     SkRSXform mappings for sprites in atlas\n        @param tex       SkRect locations of sprites in atlas\n        @param count     number of sprites to draw\n        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr\n        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr\n    */\n    void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],\n                   int count, const SkRect* cullRect, const SkPaint* paint) {\n        this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkBlendMode::kDst,\n                        cullRect, paint);\n    }\n\n    /** Draw SkDrawable drawable using clip and SkMatrix, concatenated with\n        optional matrix.\n\n        If SkCanvas has an asynchronous implementation, as is the case\n        when it is recording into SkPicture, then drawable will be referenced,\n        so that SkDrawable::draw() can be called when the operation is finalized. To force\n        immediate drawing, call SkDrawable::draw() instead.\n\n        @param drawable  custom struct encapsulating drawing commands\n        @param matrix    transformation applied to drawing; may be nullptr\n    */\n    void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);\n\n    /** Draw SkDrawable drawable using clip and SkMatrix, offset by (x, y).\n\n        If SkCanvas has an asynchronous implementation, as is the case\n        when it is recording into SkPicture, then drawable will be referenced,\n        so that SkDrawable::draw() can be called when the operation is finalized. To force\n        immediate drawing, call SkDrawable::draw() instead.\n\n        @param drawable  custom struct encapsulating drawing commands\n        @param x         offset into SkCanvas writable pixels in x\n        @param y         offset into SkCanvas writable pixels in y\n    */\n    void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);\n\n    /** Associate SkRect on SkCanvas with an annotation; a key-value pair, where the key is\n        a null-terminated utf8 string, and optional value is stored as SkData.\n\n        Only some canvas implementations, such as recording to SkPicture, or drawing to\n        document pdf, use annotations.\n\n        @param rect   SkRect extent of canvas to annotate\n        @param key    string used for lookup\n        @param value  data holding value stored in annotation\n    */\n    void drawAnnotation(const SkRect& rect, const char key[], SkData* value);\n\n    /** Associate SkRect on SkCanvas when an annotation; a key-value pair, where the key is\n        a null-terminated utf8 string, and optional value is stored as SkData.\n\n        Only some canvas implementations, such as recording to SkPicture, or drawing to\n        document pdf, use annotations.\n\n        @param rect   SkRect extent of canvas to annotate\n        @param key    string used for lookup\n        @param value  data holding value stored in annotation\n    */\n    void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {\n        this->drawAnnotation(rect, key, value.get());\n    }\n\n    //////////////////////////////////////////////////////////////////////////\n\n#ifdef SK_SUPPORT_LEGACY_DRAWFILTER\n    /** To be deprecated soon.\n    */\n    SkDrawFilter* getDrawFilter() const;\n\n    /** To be deprecated soon.\n    */\n    virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);\n#endif\n\n    /** Returns true if clip is empty; that is, nothing will draw.\n\n        May do work when called; it should not be called\n        more often than needed. However, once called, subsequent calls perform no\n        work until clip changes.\n\n        @return  true if clip is empty\n    */\n    virtual bool isClipEmpty() const;\n\n    /** Returns true if clip is SkRect and not empty.\n        Returns false if the clip is empty, or if it is not SkRect.\n\n        @return  true if clip is SkRect and not empty\n    */\n    virtual bool isClipRect() const;\n\n    /** Returns SkMatrix.\n        This does not account for translation by SkBaseDevice or SkSurface.\n\n        @return  SkMatrix in SkCanvas\n    */\n    const SkMatrix& getTotalMatrix() const;\n\n    ///////////////////////////////////////////////////////////////////////////\n\n    // don't call\n    virtual GrRenderTargetContext* internal_private_accessTopLayerRenderTargetContext();\n    SkIRect internal_private_getTopLayerBounds() const { return getTopLayerBounds(); }\n\n    // TEMP helpers until we switch virtual over to const& for src-rect\n    void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,\n                              const SkPaint* paint,\n                              SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n    void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,\n                               const SkPaint* paint,\n                               SrcRectConstraint constraint = kStrict_SrcRectConstraint);\n\n    /**\n     *  Returns the global clip as a region. If the clip contains AA, then only the bounds\n     *  of the clip may be returned.\n     */\n    void temporary_internal_getRgnClip(SkRegion* region);\n\n    void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);\n\n\nprotected:\n    // default impl defers to getDevice()->newSurface(info)\n    virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);\n\n    // default impl defers to its device\n    virtual bool onPeekPixels(SkPixmap* pixmap);\n    virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);\n    virtual SkImageInfo onImageInfo() const;\n    virtual bool onGetProps(SkSurfaceProps* props) const;\n    virtual void onFlush();\n\n    // Subclass save/restore notifiers.\n    // Overriders should call the corresponding INHERITED method up the inheritance chain.\n    // getSaveLayerStrategy()'s return value may suppress full layer allocation.\n    enum SaveLayerStrategy {\n        kFullLayer_SaveLayerStrategy,\n        kNoLayer_SaveLayerStrategy,\n    };\n\n    virtual void willSave() {}\n    // Overriders should call the corresponding INHERITED method up the inheritance chain.\n    virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {\n        return kFullLayer_SaveLayerStrategy;\n    }\n    virtual void willRestore() {}\n    virtual void didRestore() {}\n    virtual void didConcat(const SkMatrix& ) {}\n    virtual void didSetMatrix(const SkMatrix& ) {}\n    virtual void didTranslate(SkScalar dx, SkScalar dy) {\n        this->didConcat(SkMatrix::MakeTrans(dx, dy));\n    }\n\n    // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to\n    // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using\n    // that mechanism  will be required to implement the new function.\n    virtual void onDrawPaint(const SkPaint& paint);\n    virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);\n    virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);\n    virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);\n    virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);\n    virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,\n                           bool useCenter, const SkPaint& paint);\n    virtual void onDrawPath(const SkPath& path, const SkPaint& paint);\n    virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);\n\n    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,\n                            SkScalar y, const SkPaint& paint);\n    virtual void onDrawPosText(const void* text, size_t byteLength,\n                               const SkPoint pos[], const SkPaint& paint);\n    virtual void onDrawPosTextH(const void* text, size_t byteLength,\n                                const SkScalar xpos[], SkScalar constY,\n                                const SkPaint& paint);\n    virtual void onDrawTextOnPath(const void* text, size_t byteLength,\n                                  const SkPath& path, const SkMatrix* matrix,\n                                  const SkPaint& paint);\n    virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                                   const SkRect* cullRect, const SkPaint& paint);\n    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,\n                                const SkPaint& paint);\n\n    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                           const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);\n    virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],\n                              const SkPaint& paint);\n    virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,\n                                      const SkPaint& paint);\n\n    virtual void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint);\n    virtual void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,\n                                 const SkPaint* paint, SrcRectConstraint constraint);\n    virtual void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,\n                                 const SkPaint* paint);\n    virtual void onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,\n                                    const SkPaint* paint);\n\n    virtual void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,\n                              const SkPaint* paint);\n    virtual void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,\n                                  const SkPaint* paint, SrcRectConstraint constraint);\n    virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,\n                                  const SkPaint* paint);\n    virtual void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,\n                                     const SkRect& dst, const SkPaint* paint);\n\n    virtual void onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect rect[],\n                             const SkColor colors[], int count, SkBlendMode mode,\n                             const SkRect* cull, const SkPaint* paint);\n\n    virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);\n    virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);\n\n    virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);\n    virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,\n                               const SkPaint* paint);\n\n    enum ClipEdgeStyle {\n        kHard_ClipEdgeStyle,\n        kSoft_ClipEdgeStyle\n    };\n\n    virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);\n    virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);\n    virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);\n    virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);\n\n    virtual void onDiscard();\n\n    // Clip rectangle bounds. Called internally by saveLayer.\n    // returns false if the entire rectangle is entirely clipped out\n    // If non-NULL, The imageFilter parameter will be used to expand the clip\n    // and offscreen bounds for any margin required by the filter DAG.\n    bool clipRectBounds(const SkRect* bounds, SaveLayerFlags flags, SkIRect* intersection,\n                        const SkImageFilter* imageFilter = nullptr);\n\n    SkBaseDevice* getTopDevice() const;\n\nprivate:\n    /** After calling saveLayer(), there can be any number of devices that make\n     up the top-most drawing area. LayerIter can be used to iterate through\n     those devices. Note that the iterator is only valid until the next API\n     call made on the canvas. Ownership of all pointers in the iterator stays\n     with the canvas, so none of them should be modified or deleted.\n     */\n    class LayerIter /*: SkNoncopyable*/ {\n    public:\n        /** Initialize iterator with canvas, and set values for 1st device */\n        LayerIter(SkCanvas*);\n        ~LayerIter();\n\n        /** Return true if the iterator is done */\n        bool done() const { return fDone; }\n        /** Cycle to the next device */\n        void next();\n\n        // These reflect the current device in the iterator\n\n        SkBaseDevice*   device() const;\n        const SkMatrix& matrix() const;\n        SkIRect clipBounds() const;\n        const SkPaint&  paint() const;\n        int             x() const;\n        int             y() const;\n\n    private:\n        // used to embed the SkDrawIter object directly in our instance, w/o\n        // having to expose that class def to the public. There is an assert\n        // in our constructor to ensure that fStorage is large enough\n        // (though needs to be a compile-time-assert!). We use intptr_t to work\n        // safely with 32 and 64 bit machines (to ensure the storage is enough)\n        intptr_t          fStorage[32];\n        class SkDrawIter* fImpl;    // this points at fStorage\n        SkPaint           fDefaultPaint;\n        bool              fDone;\n    };\n\n    static bool BoundsAffectsClip(SaveLayerFlags);\n\n    static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,\n                                     SkBaseDevice* dst, const SkIPoint& dstOrigin,\n                                     const SkMatrix& ctm);\n\n    enum ShaderOverrideOpacity {\n        kNone_ShaderOverrideOpacity,        //!< there is no overriding shader (bitmap or image)\n        kOpaque_ShaderOverrideOpacity,      //!< the overriding shader is opaque\n        kNotOpaque_ShaderOverrideOpacity,   //!< the overriding shader may not be opaque\n    };\n\n    // notify our surface (if we have one) that we are about to draw, so it\n    // can perform copy-on-write or invalidate any cached images\n    void predrawNotify(bool willOverwritesEntireSurface = false);\n    void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);\n    void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {\n        this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity\n                                                                : kNotOpaque_ShaderOverrideOpacity);\n    }\n\n    SkBaseDevice* getDevice() const;\n\n    class MCRec;\n\n    SkDeque     fMCStack;\n    // points to top of stack\n    MCRec*      fMCRec;\n\n    // the first N recs that can fit here mean we won't call malloc\n    static constexpr int kMCRecSize      = 128;  // most recent measurement\n    static constexpr int kMCRecCount     = 32;   // common depth for save/restores\n    static constexpr int kDeviceCMSize   = 224;  // most recent measurement\n\n    intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];\n    intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];\n\n    const SkSurfaceProps fProps;\n\n    int         fSaveCount;         // value returned by getSaveCount()\n\n    SkMetaData* fMetaData;\n    std::unique_ptr<SkRasterHandleAllocator> fAllocator;\n\n    SkSurface_Base*  fSurfaceBase;\n    SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }\n    void setSurfaceBase(SkSurface_Base* sb) {\n        fSurfaceBase = sb;\n    }\n    friend class SkSurface_Base;\n    friend class SkSurface_Gpu;\n\n    SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();\n\n    void doSave();\n    void checkForDeferredSave();\n    void internalSetMatrix(const SkMatrix&);\n\n    friend class SkAndroidFrameworkUtils;\n    friend class SkCanvasPriv;      // needs kDontClipToLayer_PrivateSaveLayerFlag\n    friend class SkDrawIter;        // needs setupDrawForLayerDevice()\n    friend class AutoDrawLooper;\n    friend class SkDebugCanvas;     // needs experimental fAllowSimplifyClip\n    friend class SkSurface_Raster;  // needs getDevice()\n    friend class SkNoDrawCanvas;    // InitFlags\n    friend class SkPictureImageFilter;  // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)\n    friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)\n    friend class SkOverdrawCanvas;\n    friend class SkRasterHandleAllocator;\n\n    enum InitFlags {\n        kDefault_InitFlags                  = 0,\n        kConservativeRasterClip_InitFlag    = 1 << 0,\n    };\nprotected:\n    // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)\n    SkCanvas(const SkIRect& bounds, InitFlags);\nprivate:\n    SkCanvas(sk_sp<SkBaseDevice> device, InitFlags);\n    SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,\n             SkRasterHandleAllocator::Handle);\n\n    void resetForNextPicture(const SkIRect& bounds);\n\n    // needs gettotalclip()\n    friend class SkCanvasStateUtils;\n\n    // call this each time we attach ourselves to a device\n    //  - constructor\n    //  - internalSaveLayer\n    void setupDevice(SkBaseDevice*);\n\n    void init(sk_sp<SkBaseDevice>, InitFlags);\n\n    /**\n     * Gets the bounds of the top level layer in global canvas coordinates. We don't want this\n     * to be public because it exposes decisions about layer sizes that are internal to the canvas.\n     */\n    SkIRect getTopLayerBounds() const;\n\n    void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,\n                                const SkRect& dst, const SkPaint* paint,\n                                SrcRectConstraint);\n    void internalDrawPaint(const SkPaint& paint);\n    void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);\n    void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, SkImage* clipImage,\n                            const SkMatrix& clipMatrix);\n\n    // shared by save() and saveLayer()\n    void internalSave();\n    void internalRestore();\n\n    /*\n     *  Returns true if drawing the specified rect (or all if it is null) with the specified\n     *  paint (or default if null) would overwrite the entire root device of the canvas\n     *  (i.e. the canvas' surface if it had one).\n     */\n    bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;\n\n    /**\n     *  Returns true if the paint's imagefilter can be invoked directly, without needed a layer.\n     */\n    bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);\n\n    /**\n     *  Returns true if the clip (for any active layer) contains antialiasing.\n     *  If the clip is empty, this will return false.\n     */\n    bool androidFramework_isClipAA() const;\n\n    /**\n     *  Keep track of the device clip bounds and if the matrix is scale-translate.  This allows\n     *  us to do a fast quick reject in the common case.\n     */\n    bool   fIsScaleTranslate;\n    SkRect fDeviceClipBounds;\n\n    bool fAllowSoftClip;\n    bool fAllowSimplifyClip;\n\n    class AutoValidateClip : ::SkNoncopyable {\n    public:\n        explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {\n            fCanvas->validateClip();\n        }\n        ~AutoValidateClip() { fCanvas->validateClip(); }\n\n    private:\n        const SkCanvas* fCanvas;\n    };\n\n#ifdef SK_DEBUG\n    void validateClip() const;\n#else\n    void validateClip() const {}\n#endif\n\n    typedef SkRefCnt INHERITED;\n};\n\n/** \\class SkAutoCanvasRestore\n    Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore\n    goes out of scope. Use this to guarantee that the canvas is restored to a known\n    state.\n*/\nclass SkAutoCanvasRestore : SkNoncopyable {\npublic:\n\n    /** Preserves SkCanvas save count. Optionally saves SkCanvas clip and SkCanvas matrix.\n\n        @param canvas  SkCanvas to guard\n        @param doSave  call SkCanvas::save()\n        @return        utility to restore SkCanvas state on destructor\n    */\n    SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {\n        if (fCanvas) {\n            fSaveCount = canvas->getSaveCount();\n            if (doSave) {\n                canvas->save();\n            }\n        }\n    }\n\n    /** Restores SkCanvas to saved state. Destructor is called when container goes out of\n        scope.\n    */\n    ~SkAutoCanvasRestore() {\n        if (fCanvas) {\n            fCanvas->restoreToCount(fSaveCount);\n        }\n    }\n\n    /** Restores SkCanvas to saved state immediately. Subsequent calls and\n        ~SkAutoCanvasRestore have no effect.\n    */\n    void restore() {\n        if (fCanvas) {\n            fCanvas->restoreToCount(fSaveCount);\n            fCanvas = nullptr;\n        }\n    }\n\nprivate:\n    SkCanvas*   fCanvas;\n    int         fSaveCount;\n};\n#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)\n\n#endif\n"
  },
  {
    "path": "include/core/SkCanvasVirtualEnforcer.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCanvasVirtualEnforcer_DEFINED\n#define SkCanvasVirtualEnforcer_DEFINED\n\n#include \"SkCanvas.h\"\n\n// If you would ordinarily want to inherit from Base (eg SkCanvas, SkNWayCanvas), instead\n// inherit from SkCanvasVirtualEnforcer<Base>, which will make the build fail if you forget\n// to override one of SkCanvas' key virtual hooks.\ntemplate <typename Base>\nclass SkCanvasVirtualEnforcer : public Base {\npublic:\n    using Base::Base;\n\nprotected:\n    void onDrawPaint(const SkPaint& paint) override = 0;\n    void onDrawRect(const SkRect& rect, const SkPaint& paint) override = 0;\n    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override = 0;\n    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,\n                      const SkPaint& paint) override = 0;\n    void onDrawOval(const SkRect& rect, const SkPaint& paint) override = 0;\n    void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,\n                   const SkPaint& paint) override = 0;\n    void onDrawPath(const SkPath& path, const SkPaint& paint) override = 0;\n    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override = 0;\n\n    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,\n                    const SkPaint& paint) override = 0;\n    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],\n                       const SkPaint& paint) override = 0;\n    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],\n                        SkScalar constY, const SkPaint& paint) override = 0;\n    void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,\n                          const SkMatrix* matrix, const SkPaint& paint) override = 0;\n    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                           const SkRect* cullRect, const SkPaint& paint) override = 0;\n    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,\n                        const SkPaint& paint) override = 0;\n\n    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                     const SkPoint texCoords[4], SkBlendMode mode,\n                     const SkPaint& paint) override = 0;\n    void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],\n                      const SkPaint& paint) override = 0;\n    void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,\n                              const SkPaint& paint) override = 0;\n\n    void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy,\n                     const SkPaint* paint) override = 0;\n    void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,\n                         const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) override = 0;\n    void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,\n                         const SkPaint* paint) override = 0;\n    void onDrawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,\n                            const SkRect& dst, const SkPaint* paint) override = 0;\n\n    void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,\n                      const SkPaint* paint) override = 0;\n    void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,\n                          const SkPaint* paint,\n                          SkCanvas::SrcRectConstraint constraint) override = 0;\n    void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,\n                          const SkPaint* paint) override = 0;\n    void onDrawBitmapLattice(const SkBitmap& bitmap, const SkCanvas::Lattice& lattice,\n                             const SkRect& dst, const SkPaint* paint) override = 0;\n\n    void onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect rect[],\n                     const SkColor colors[], int count, SkBlendMode mode, const SkRect* cull,\n                     const SkPaint* paint) override = 0;\n\n    void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override = 0;\n    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override = 0;\n\n    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override = 0;\n    void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,\n                       const SkPaint* paint) override = 0;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkClipOp.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkClipOp_DEFINED\n#define SkClipOp_DEFINED\n\n#include \"SkTypes.h\"\n\nenum class SkClipOp {\n    kDifference    = 0,\n    kIntersect     = 1,\n\n#ifdef SK_SUPPORT_DEPRECATED_CLIPOPS\n    kUnion_deprecated             = 2,\n    kXOR_deprecated               = 3,\n    kReverseDifference_deprecated = 4,\n    kReplace_deprecated           = 5,\n#else\n    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway2   = 2,\n    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway3   = 3,\n    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway4   = 4,\n    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway5   = 5,\n#endif\n\n    // Used internally for validation, can only shrink to 1 when the deprecated flag is gone\n    kMax_EnumValue = 5,\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkColor.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColor_DEFINED\n#define SkColor_DEFINED\n\n#include \"SkScalar.h\"\n#include \"SkTypes.h\"\n\n/** \\file SkColor.h\n\n    Types and macros for colors\n*/\n\n/** 8-bit type for an alpha value. 0xFF is 100% opaque, 0x00 is 100% transparent.\n*/\ntypedef uint8_t SkAlpha;\n/** 32 bit ARGB color value, not premultiplied. The color components are always in\n    a known order. This is different from SkPMColor, which has its bytes in a configuration\n    dependent order, to match the format of kARGB32 bitmaps. SkColor is the type used to\n    specify colors in SkPaint and in gradients.\n*/\ntypedef uint32_t SkColor;\n\n/** Return a SkColor value from 8 bit component values\n*/\nstatic constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {\n    return SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255),\n           (a << 24) | (r << 16) | (g << 8) | (b << 0);\n}\n\n/** Return a SkColor value from 8 bit component values, with an implied value\n    of 0xFF for alpha (fully opaque)\n*/\n#define SkColorSetRGB(r, g, b)  SkColorSetARGB(0xFF, r, g, b)\n\n/** return the alpha byte from a SkColor value */\n#define SkColorGetA(color)      (((color) >> 24) & 0xFF)\n/** return the red byte from a SkColor value */\n#define SkColorGetR(color)      (((color) >> 16) & 0xFF)\n/** return the green byte from a SkColor value */\n#define SkColorGetG(color)      (((color) >>  8) & 0xFF)\n/** return the blue byte from a SkColor value */\n#define SkColorGetB(color)      (((color) >>  0) & 0xFF)\n\nstatic constexpr inline SkColor SkColorSetA(SkColor c, U8CPU a) {\n    return (c & 0x00FFFFFF) | (a << 24);\n}\n\n// common colors\n\n/** transparent SkAlpha value */\nconstexpr SkAlpha SK_AlphaTRANSPARENT = 0x00;\n/** opaque SkAlpha value */\nconstexpr SkAlpha SK_AlphaOPAQUE      = 0xFF;\n\n/** transparent SkColor value */\nconstexpr SkColor SK_ColorTRANSPARENT = SkColorSetARGB(0x00, 0x00, 0x00, 0x00);\n\n/** black SkColor value */\nconstexpr SkColor SK_ColorBLACK       = SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);\n/** dark gray SkColor value */\nconstexpr SkColor SK_ColorDKGRAY      = SkColorSetARGB(0xFF, 0x44, 0x44, 0x44);\n/** gray SkColor value */\nconstexpr SkColor SK_ColorGRAY        = SkColorSetARGB(0xFF, 0x88, 0x88, 0x88);\n/** light gray SkColor value */\nconstexpr SkColor SK_ColorLTGRAY      = SkColorSetARGB(0xFF, 0xCC, 0xCC, 0xCC);\n/** white SkColor value */\nconstexpr SkColor SK_ColorWHITE       = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);\n\n/** red SkColor value */\nconstexpr SkColor SK_ColorRED         = SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00);\n/** green SkColor value */\nconstexpr SkColor SK_ColorGREEN       = SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00);\n/** blue SkColor value */\nconstexpr SkColor SK_ColorBLUE        = SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF);\n/** yellow SkColor value */\nconstexpr SkColor SK_ColorYELLOW      = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0x00);\n/** cyan SkColor value */\nconstexpr SkColor SK_ColorCYAN        = SkColorSetARGB(0xFF, 0x00, 0xFF, 0xFF);\n/** magenta SkColor value */\nconstexpr SkColor SK_ColorMAGENTA     = SkColorSetARGB(0xFF, 0xFF, 0x00, 0xFF);\n\n////////////////////////////////////////////////////////////////////////\n\n/** Convert RGB components to HSV.\n        hsv[0] is Hue [0 .. 360)\n        hsv[1] is Saturation [0...1]\n        hsv[2] is Value [0...1]\n    @param red  red component value [0..255]\n    @param green  green component value [0..255]\n    @param blue  blue component value [0..255]\n    @param hsv  3 element array which holds the resulting HSV components.\n*/\nSK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);\n\n/** Convert the argb color to its HSV components.\n        hsv[0] is Hue [0 .. 360)\n        hsv[1] is Saturation [0...1]\n        hsv[2] is Value [0...1]\n    @param color the argb color to convert. Note: the alpha component is ignored.\n    @param hsv  3 element array which holds the resulting HSV components.\n*/\nstatic inline void SkColorToHSV(SkColor color, SkScalar hsv[3]) {\n    SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);\n}\n\n/** Convert HSV components to an ARGB color. The alpha component is passed through unchanged.\n        hsv[0] is Hue [0 .. 360)\n        hsv[1] is Saturation [0...1]\n        hsv[2] is Value [0...1]\n    If hsv values are out of range, they are pinned.\n    @param alpha the alpha component of the returned argb color.\n    @param hsv  3 element array which holds the input HSV components.\n    @return the resulting argb color\n*/\nSK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);\n\n/** Convert HSV components to an ARGB color. The alpha component set to 0xFF.\n        hsv[0] is Hue [0 .. 360)\n        hsv[1] is Saturation [0...1]\n        hsv[2] is Value [0...1]\n    If hsv values are out of range, they are pinned.\n    @param hsv  3 element array which holds the input HSV components.\n    @return the resulting argb color\n*/\nstatic inline SkColor SkHSVToColor(const SkScalar hsv[3]) {\n    return SkHSVToColor(0xFF, hsv);\n}\n\n////////////////////////////////////////////////////////////////////////\n\n/** 32 bit ARGB color value, premultiplied. The byte order for this value is\n    configuration dependent, matching the format of kARGB32 bitmaps. This is different\n    from SkColor, which is nonpremultiplied, and is always in the same byte order.\n*/\ntypedef uint32_t SkPMColor;\n\n/** Return a SkPMColor value from unpremultiplied 8 bit component values\n*/\nSK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);\n/** Return a SkPMColor value from a SkColor value. This is done by multiplying the color\n    components by the color's alpha, and by arranging the bytes in a configuration\n    dependent order, to match the format of kARGB32 bitmaps.\n*/\nSK_API SkPMColor SkPreMultiplyColor(SkColor c);\n\n///////////////////////////////////////////////////////////////////////////////////////////////////\n\nstruct SkPM4f;\n\n/*\n *  The float values are 0...1 unpremultiplied\n */\nstruct SK_API SkColor4f {\n    float fR;\n    float fG;\n    float fB;\n    float fA;\n\n    bool operator==(const SkColor4f& other) const {\n        return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;\n    }\n    bool operator!=(const SkColor4f& other) const {\n        return !(*this == other);\n    }\n\n    const float* vec() const { return &fR; }\n    float* vec() { return &fR; }\n\n    static SkColor4f Pin(float r, float g, float b, float a);\n    /** Convert to SkColor4f, assuming SkColor is sRGB */\n    static SkColor4f FromColor(SkColor);\n\n    SkColor toSkColor() const;\n\n    SkColor4f pin() const {\n        return Pin(fR, fG, fB, fA);\n    }\n\n    SkPM4f premul() const;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkColorFilter.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorFilter_DEFINED\n#define SkColorFilter_DEFINED\n\n#include \"SkBlendMode.h\"\n#include \"SkColor.h\"\n#include \"SkFlattenable.h\"\n#include \"SkRefCnt.h\"\n\nclass GrContext;\nclass GrColorSpaceInfo;\nclass GrFragmentProcessor;\nclass SkArenaAlloc;\nclass SkBitmap;\nclass SkColorSpace;\nclass SkColorSpaceXformer;\nclass SkRasterPipeline;\nclass SkString;\n\n/**\n *  ColorFilters are optional objects in the drawing pipeline. When present in\n *  a paint, they are called with the \"src\" colors, and return new colors, which\n *  are then passed onto the next stage (either ImageFilter or Xfermode).\n *\n *  All subclasses are required to be reentrant-safe : it must be legal to share\n *  the same instance between several threads.\n */\nclass SK_API SkColorFilter : public SkFlattenable {\npublic:\n    /**\n     *  If the filter can be represented by a source color plus Mode, this\n     *  returns true, and sets (if not NULL) the color and mode appropriately.\n     *  If not, this returns false and ignores the parameters.\n     */\n    virtual bool asColorMode(SkColor* color, SkBlendMode* bmode) const;\n\n    /**\n     *  If the filter can be represented by a 5x4 matrix, this\n     *  returns true, and sets the matrix appropriately.\n     *  If not, this returns false and ignores the parameter.\n     */\n    virtual bool asColorMatrix(SkScalar matrix[20]) const;\n\n    /**\n     *  If the filter can be represented by per-component table, return true,\n     *  and if table is not null, copy the bitmap containing the table into it.\n     *\n     *  The table bitmap will be in SkBitmap::kA8_Config. Each row corresponding\n     *  to each component in ARGB order. e.g. row[0] == alpha, row[1] == red,\n     *  etc. To transform a color, you (logically) perform the following:\n     *\n     *      a' = *table.getAddr8(a, 0);\n     *      r' = *table.getAddr8(r, 1);\n     *      g' = *table.getAddr8(g, 2);\n     *      b' = *table.getAddr8(b, 3);\n     *\n     *  The original component value is the horizontal index for a given row,\n     *  and the stored value at that index is the new value for that component.\n     */\n    virtual bool asComponentTable(SkBitmap* table) const;\n\n    void appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool shaderIsOpaque) const;\n\n    enum Flags {\n        /** If set the filter methods will not change the alpha channel of the colors.\n        */\n        kAlphaUnchanged_Flag = 1 << 0,\n    };\n\n    /** Returns the flags for this filter. Override in subclasses to return custom flags.\n    */\n    virtual uint32_t getFlags() const { return 0; }\n\n    SkColor filterColor(SkColor) const;\n    SkColor4f filterColor4f(const SkColor4f&) const;\n\n    /** Create a colorfilter that uses the specified color and mode.\n        If the Mode is DST, this function will return NULL (since that\n        mode will have no effect on the result).\n        @param c    The source color used with the specified mode\n        @param mode The blend that is applied to each color in\n                        the colorfilter's filterSpan[16,32] methods\n        @return colorfilter object that applies the src color and mode,\n                    or NULL if the mode will have no effect.\n    */\n    static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkBlendMode mode);\n\n    /** Construct a colorfilter whose effect is to first apply the inner filter and then apply\n     *  this filter, applied to the output of the inner filter.\n     *\n     *  result = this(inner(...))\n     *\n     *  Due to internal limits, it is possible that this will return NULL, so the caller must\n     *  always check.\n     */\n    sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const;\n\n    // DEPRECATED, call makeComposed instead\n    static sk_sp<SkColorFilter> MakeComposeFilter(sk_sp<SkColorFilter> outer,\n                                                  sk_sp<SkColorFilter> inner) {\n        return outer ? outer->makeComposed(inner) : inner;\n    }\n\n    /** Construct a color filter that transforms a color by a 4x5 matrix. The matrix is in row-\n     *  major order and the translation column is specified in unnormalized, 0...255, space.\n     */\n    static sk_sp<SkColorFilter> MakeMatrixFilterRowMajor255(const SkScalar array[20]);\n\n    /** Construct a colorfilter that applies the srgb gamma curve to the RGB channels */\n    static sk_sp<SkColorFilter> MakeLinearToSRGBGamma();\n\n    /** Construct a colorfilter that applies the inverse of the srgb gamma curve to the\n     *  RGB channels\n     */\n    static sk_sp<SkColorFilter> MakeSRGBToLinearGamma();\n\n#if SK_SUPPORT_GPU\n    /**\n     *  A subclass may implement this factory function to work with the GPU backend. It returns\n     *  a GrFragmentProcessor that implemets the color filter in GPU shader code.\n     *\n     *  The fragment processor receives a premultiplied input color and produces a premultiplied\n     *  output color.\n     *\n     *  A null return indicates that the color filter isn't implemented for the GPU backend.\n     */\n    virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(\n            GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const;\n#endif\n\n    bool affectsTransparentBlack() const {\n        return this->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;\n    }\n\n    virtual void toString(SkString* str) const = 0;\n\n    static void InitializeFlattenables();\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkColorFilter_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkColorFilter_Type;\n    }\n\n    static sk_sp<SkColorFilter> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkColorFilter>(static_cast<SkColorFilter*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkColorFilter_Type, data, size, procs).release()));\n    }\n\nprotected:\n    SkColorFilter() {}\n\n    sk_sp<SkColorFilter> makeColorSpace(SkColorSpaceXformer* xformer) const {\n        return this->onMakeColorSpace(xformer);\n    }\n    virtual sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer*) const {\n        return sk_ref_sp(const_cast<SkColorFilter*>(this));\n    }\n\n    /**\n     *  If this subclass can optimally createa composition with the inner filter, return it as\n     *  a new filter (which the caller must unref() when it is done). If no such optimization\n     *  is known, return NULL.\n     *\n     *  e.g. result(color) == this_filter(inner(color))\n     */\n    virtual sk_sp<SkColorFilter> onMakeComposed(sk_sp<SkColorFilter>) const { return nullptr; }\n\nprivate:\n    /*\n     *  Returns 1 if this is a single filter (not a composition of other filters), otherwise it\n     *  reutrns the number of leaf-node filters in a composition. This should be the same value\n     *  as the number of GrFragmentProcessors returned by asFragmentProcessors's array parameter.\n     *\n     *  e.g. compose(filter, compose(compose(filter, filter), filter)) --> 4\n     */\n    virtual int privateComposedFilterCount() const { return 1; }\n\n    virtual void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,\n                                bool shaderIsOpaque) const = 0;\n\n    friend class SkColorSpaceXformer;\n    friend class SkComposeColorFilter;\n\n    typedef SkFlattenable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkColorPriv.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorPriv_DEFINED\n#define SkColorPriv_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkMath.h\"\n\n/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a\n    byte into a scale value, so that we can say scale * value >> 8 instead of\n    alpha * value / 255.\n\n    In debugging, asserts that alpha is 0..255\n*/\nstatic inline unsigned SkAlpha255To256(U8CPU alpha) {\n    SkASSERT(SkToU8(alpha) == alpha);\n    // this one assues that blending on top of an opaque dst keeps it that way\n    // even though it is less accurate than a+(a>>7) for non-opaque dsts\n    return alpha + 1;\n}\n\n/** Multiplify value by 0..256, and shift the result down 8\n    (i.e. return (value * alpha256) >> 8)\n */\n#define SkAlphaMul(value, alpha256)     (((value) * (alpha256)) >> 8)\n\nstatic inline U8CPU SkUnitScalarClampToByte(SkScalar x) {\n    return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);\n}\n\n#define SK_A32_BITS     8\n#define SK_R32_BITS     8\n#define SK_G32_BITS     8\n#define SK_B32_BITS     8\n\n#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)\n#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)\n#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)\n#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)\n\n/*\n *  Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).\n *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.\n *\n *  For easier compatibility with Skia's GPU backend, we further restrict these\n *  to either (in memory-byte-order) RGBA or BGRA. Note that this \"order\" does\n *  not directly correspond to the same shift-order, since we have to take endianess\n *  into account.\n *\n *  Here we enforce this constraint.\n */\n\n#ifdef SK_CPU_BENDIAN\n    #define SK_RGBA_R32_SHIFT   24\n    #define SK_RGBA_G32_SHIFT   16\n    #define SK_RGBA_B32_SHIFT   8\n    #define SK_RGBA_A32_SHIFT   0\n#else\n    #define SK_RGBA_R32_SHIFT   0\n    #define SK_RGBA_G32_SHIFT   8\n    #define SK_RGBA_B32_SHIFT   16\n    #define SK_RGBA_A32_SHIFT   24\n#endif\n\n#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)\n#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)\n#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)\n#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)\n\n#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)\n#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)\n#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)\n#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)\n\n/**\n *  Pack the components into a SkPMColor, checking (in the debug version) that\n *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)\n */\nstatic inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {\n    SkA32Assert(a);\n    SkASSERT(r <= a);\n    SkASSERT(g <= a);\n    SkASSERT(b <= a);\n\n    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |\n           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);\n}\n\n/**\n *  Same as SkPackARGB32, but this version guarantees to not check that the\n *  values are premultiplied in the debug version.\n */\nstatic inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {\n    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |\n           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);\n}\n\nstatic inline\nSkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {\n    SkA32Assert(a);\n    SkR32Assert(r);\n    SkG32Assert(g);\n    SkB32Assert(b);\n\n    if (a != 255) {\n        r = SkMulDiv255Round(r, a);\n        g = SkMulDiv255Round(g, a);\n        b = SkMulDiv255Round(b, a);\n    }\n    return SkPackARGB32(a, r, g, b);\n}\n\n// When Android is compiled optimizing for size, SkAlphaMulQ doesn't get\n// inlined; forcing inlining significantly improves performance.\nstatic SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {\n    uint32_t mask = 0xFF00FF;\n\n    uint32_t rb = ((c & mask) * scale) >> 8;\n    uint32_t ag = ((c >> 8) & mask) * scale;\n    return (rb & mask) | (ag & ~mask);\n}\n\nstatic inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {\n    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));\n}\n\n////////////////////////////////////////////////////////////////////////////////////////////\n// Convert a 16bit pixel to a 32bit pixel\n\n#define SK_R16_BITS     5\n#define SK_G16_BITS     6\n#define SK_B16_BITS     5\n\n#define SK_R16_SHIFT    (SK_B16_BITS + SK_G16_BITS)\n#define SK_G16_SHIFT    (SK_B16_BITS)\n#define SK_B16_SHIFT    0\n\n#define SK_R16_MASK     ((1 << SK_R16_BITS) - 1)\n#define SK_G16_MASK     ((1 << SK_G16_BITS) - 1)\n#define SK_B16_MASK     ((1 << SK_B16_BITS) - 1)\n\n#define SkGetPackedR16(color)   (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)\n#define SkGetPackedG16(color)   (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)\n#define SkGetPackedB16(color)   (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)\n\nstatic inline unsigned SkR16ToR32(unsigned r) {\n    return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));\n}\n\nstatic inline unsigned SkG16ToG32(unsigned g) {\n    return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));\n}\n\nstatic inline unsigned SkB16ToB32(unsigned b) {\n    return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));\n}\n\n#define SkPacked16ToR32(c)      SkR16ToR32(SkGetPackedR16(c))\n#define SkPacked16ToG32(c)      SkG16ToG32(SkGetPackedG16(c))\n#define SkPacked16ToB32(c)      SkB16ToB32(SkGetPackedB16(c))\n\n#endif\n"
  },
  {
    "path": "include/core/SkColorSpace.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorSpace_DEFINED\n#define SkColorSpace_DEFINED\n\n#include \"SkMatrix44.h\"\n#include \"SkRefCnt.h\"\n\nclass SkData;\nstruct skcms_ICCProfile;\n\nenum SkGammaNamed {\n    kLinear_SkGammaNamed,\n    kSRGB_SkGammaNamed,\n    k2Dot2Curve_SkGammaNamed,\n    kNonStandard_SkGammaNamed,\n};\n\n/**\n *  Describes a color gamut with primaries and a white point.\n */\nstruct SK_API SkColorSpacePrimaries {\n    float fRX;\n    float fRY;\n    float fGX;\n    float fGY;\n    float fBX;\n    float fBY;\n    float fWX;\n    float fWY;\n\n    /**\n     *  Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut\n     *  representation of SkColorSpace.\n     */\n    bool toXYZD50(SkMatrix44* toXYZD50) const;\n};\n\n/**\n *  Contains the coefficients for a common transfer function equation, specified as\n *  a transformation from a curved space to linear.\n *\n *  LinearVal = C*InputVal + F        , for 0.0f <= InputVal <  D\n *  LinearVal = (A*InputVal + B)^G + E, for D    <= InputVal <= 1.0f\n *\n *  Function is undefined if InputVal is not in [ 0.0f, 1.0f ].\n *  Resulting LinearVals must be in [ 0.0f, 1.0f ].\n *  Function must be positive and increasing.\n */\nstruct SK_API SkColorSpaceTransferFn {\n    float fG;\n    float fA;\n    float fB;\n    float fC;\n    float fD;\n    float fE;\n    float fF;\n\n    /**\n     * Produces a new parametric transfer function equation that is the mathematical inverse of\n     * this one.\n     */\n    SkColorSpaceTransferFn invert() const;\n\n    /**\n     * Transform a single float by this transfer function.\n     * For negative inputs, returns sign(x) * f(abs(x)).\n     */\n    float operator()(float x) {\n        SkScalar s = SkScalarSignAsScalar(x);\n        x = sk_float_abs(x);\n        if (x >= fD) {\n            return s * (powf(fA * x + fB, fG) + fE);\n        } else {\n            return s * (fC * x + fF);\n        }\n    }\n};\n\nclass SK_API SkColorSpace : public SkRefCnt {\npublic:\n    /**\n     *  Create the sRGB color space.\n     */\n    static sk_sp<SkColorSpace> MakeSRGB();\n\n    /**\n     *  Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for\n     *  half-float surfaces, and high precision individual colors (gradient stops, etc...)\n     */\n    static sk_sp<SkColorSpace> MakeSRGBLinear();\n\n    enum RenderTargetGamma : uint8_t {\n        kLinear_RenderTargetGamma,\n\n        /**\n         *  Transfer function is the canonical sRGB curve, which has a short linear segment\n         *  followed by a 2.4f exponential.\n         */\n        kSRGB_RenderTargetGamma,\n    };\n\n    enum Gamut {\n        kSRGB_Gamut,\n        kAdobeRGB_Gamut,\n        kDCIP3_D65_Gamut,\n        kRec2020_Gamut,\n    };\n\n    /**\n     *  Create an SkColorSpace from a transfer function and a color gamut.\n     *\n     *  Transfer function can be specified as an enum or as the coefficients to an equation.\n     *  Gamut can be specified as an enum or as the matrix transformation to XYZ D50.\n     */\n    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, Gamut gamut);\n    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);\n    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs, Gamut gamut);\n    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs,\n                                       const SkMatrix44& toXYZD50);\n\n    static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);\n\n    /**\n     *  Create an SkColorSpace from an ICC profile.\n     */\n    static sk_sp<SkColorSpace> MakeICC(const void*, size_t);\n\n    /**\n     *  Create an SkColorSpace from a parsed (skcms) ICC profile.\n     */\n    static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);\n\n    /**\n     *  Convert this color space to an skcms ICC profile struct.\n     */\n    void toProfile(skcms_ICCProfile*) const;\n\n    /**\n     *  Types of colorspaces.\n     */\n    enum Type {\n        kRGB_Type,\n        kCMYK_Type,\n        kGray_Type,\n    };\n    Type type() const;\n\n    SkGammaNamed gammaNamed() const;\n\n    /**\n     *  Returns true if the color space gamma is near enough to be approximated as sRGB.\n     *  This includes the canonical sRGB transfer function as well as a 2.2f exponential\n     *  transfer function.\n     */\n    bool gammaCloseToSRGB() const;\n\n    /**\n     *  Returns true if the color space gamma is linear.\n     */\n    bool gammaIsLinear() const;\n\n    /**\n     *  If the transfer function can be represented as coefficients to the standard\n     *  equation, returns true and sets |fn| to the proper values.\n     *\n     *  If not, returns false.\n     */\n    bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;\n\n    /**\n     *  Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.\n     *  Returns false otherwise.\n     */\n    bool toXYZD50(SkMatrix44* toXYZD50) const;\n\n    /**\n     *  Describes color space gamut as a transformation to XYZ D50.\n     *  Returns nullptr if color gamut cannot be described in terms of XYZ D50.\n     */\n    const SkMatrix44* toXYZD50() const;\n\n    /**\n     *  Describes color space gamut as a transformation from XYZ D50\n     *  Returns nullptr if color gamut cannot be described in terms of XYZ D50.\n     */\n    const SkMatrix44* fromXYZD50() const;\n\n    /**\n     *  Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking\n     *  of gamuts, at the (very small) risk of collision.\n     *  Returns 0 if color gamut cannot be described in terms of XYZ D50.\n     */\n    uint32_t toXYZD50Hash() const;\n\n    /**\n     *  Returns a color space with the same gamut as this one, but with a linear gamma.\n     *  For color spaces whose gamut can not be described in terms of XYZ D50, returns\n     *  linear sRGB.\n     */\n    virtual sk_sp<SkColorSpace> makeLinearGamma() const = 0;\n\n    /**\n     *  Returns a color space with the same gamut as this one, with with the sRGB transfer\n     *  function. For color spaces whose gamut can not be described in terms of XYZ D50, returns\n     *  sRGB.\n     */\n    virtual sk_sp<SkColorSpace> makeSRGBGamma() const = 0;\n\n    /**\n     *  Returns a color space with the same transfer function as this one, but with the primary\n     *  colors rotated. For any XYZ space, this produces a new color space that maps RGB to GBR\n     *  (when applied to a source), and maps RGB to BRG (when applied to a destination). For other\n     *  types of color spaces, returns nullptr.\n     *\n     *  This is used for testing, to construct color spaces that have severe and testable behavior.\n     */\n    virtual sk_sp<SkColorSpace> makeColorSpin() const { return nullptr; }\n\n    /**\n     *  Returns true if the color space is sRGB.\n     *  Returns false otherwise.\n     *\n     *  This allows a little bit of tolerance, given that we might see small numerical error\n     *  in some cases: converting ICC fixed point to float, converting white point to D50,\n     *  rounding decisions on transfer function and matrix.\n     *\n     *  This does not consider a 2.2f exponential transfer function to be sRGB.  While these\n     *  functions are similar (and it is sometimes useful to consider them together), this\n     *  function checks for logical equality.\n     */\n    bool isSRGB() const;\n\n    /**\n     *  Returns nullptr on failure.  Fails when we fallback to serializing ICC data and\n     *  the data is too large to serialize.\n     */\n    sk_sp<SkData> serialize() const;\n\n    /**\n     *  If |memory| is nullptr, returns the size required to serialize.\n     *  Otherwise, serializes into |memory| and returns the size.\n     */\n    size_t writeToMemory(void* memory) const;\n\n    static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);\n\n    /**\n     *  If both are null, we return true.  If one is null and the other is not, we return false.\n     *  If both are non-null, we do a deeper compare.\n     */\n    static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);\n\nprivate:\n    virtual const SkMatrix44* onToXYZD50() const = 0;\n    virtual uint32_t onToXYZD50Hash() const = 0;\n    virtual const SkMatrix44* onFromXYZD50() const = 0;\n\n    virtual SkGammaNamed onGammaNamed() const = 0;\n    virtual bool onGammaCloseToSRGB() const = 0;\n    virtual bool onGammaIsLinear() const = 0;\n    virtual bool onIsNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const = 0;\n    virtual bool onIsCMYK() const { return false; }\n\n    virtual const SkData* onProfileData() const { return nullptr; }\n\n    using INHERITED = SkRefCnt;\n};\n\nenum class SkTransferFunctionBehavior {\n    /**\n     *  Converts to a linear space before premultiplying, unpremultiplying, or blending.\n     */\n    kRespect,\n\n    /**\n     *  Premultiplies, unpremultiplies, and blends ignoring the transfer function.  Pixels are\n     *  treated as if they are linear, regardless of their transfer function encoding.\n     */\n    kIgnore,\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkColorSpaceXform.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorSpaceXform_DEFINED\n#define SkColorSpaceXform_DEFINED\n\n#include \"SkImageInfo.h\"\n\nclass SkColorSpace;\n\nclass SK_API SkColorSpaceXform : SkNoncopyable {\npublic:\n\n    /**\n     *  Create an object to handle color space conversions.\n     *\n     *  @param srcSpace The encoded color space.\n     *  @param dstSpace The destination color space.\n     *\n     */\n    static std::unique_ptr<SkColorSpaceXform> New(SkColorSpace* srcSpace, SkColorSpace* dstSpace);\n\n    enum ColorFormat {\n        kRGBA_8888_ColorFormat,\n        kBGRA_8888_ColorFormat,\n\n        // Unsigned, big-endian, 16-bit integer\n        kRGB_U16_BE_ColorFormat,   // Src only\n        kRGBA_U16_BE_ColorFormat,  // Src only\n\n        kRGBA_F16_ColorFormat,\n        kRGBA_F32_ColorFormat,\n\n        kBGR_565_ColorFormat,      // Dst only, kOpaque only\n    };\n\n    /**\n     *  Apply the color conversion to a |src| buffer, storing the output in the |dst| buffer.\n     *\n     *  F16 and F32 are only supported when the color space is linear. This function will return\n     *  false in unsupported cases.\n     *\n     *  @param dst            Stored in the format described by |dstColorFormat|\n     *  @param src            Stored in the format described by |srcColorFormat|\n     *  @param len            Number of pixels in the buffers\n     *  @param dstColorFormat Describes color format of |dst|\n     *  @param srcColorFormat Describes color format of |src|\n     *  @param alphaType      Describes alpha properties of the |dst| (and |src|)\n     *                        kUnpremul preserves input alpha values\n     *                        kPremul   performs a premultiplication and also preserves alpha values\n     *                        kOpaque   optimization hint, |dst| alphas set to 1\n     *\n     */\n    virtual bool apply(ColorFormat dstFormat, void* dst, ColorFormat srcFormat, const void* src,\n                       int count, SkAlphaType alphaType) const = 0;\n\n    virtual ~SkColorSpaceXform() {}\n\n    enum AlphaOp {\n        kPreserve_AlphaOp,      // just transfer src-alpha to dst-alpha\n        kPremul_AlphaOp,        // like kPreserve, but multiplies RGB by it\n        kSrcIsOpaque_AlphaOp,   // src alphas are all 1, this is a perf hint\n    };\n    static bool Apply(SkColorSpace* dstCS, ColorFormat dstFormat, void* dst,\n                      SkColorSpace* srcCS, ColorFormat srcFormat, const void* src,\n                      int count, AlphaOp);\n\nprotected:\n    SkColorSpaceXform() {}\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkColorSpaceXformCanvas.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorSpaceXformCanvas_DEFINED\n#define SkColorSpaceXformCanvas_DEFINED\n\n#include <SkCanvas.h>\n#include <SkColorSpace.h>\n#include <memory>\n\n// Proxy SkCanvas calls to unowned target, transforming colors into targetCS as it goes.\n// May return nullptr if |targetCS| is unsupported.\nstd::unique_ptr<SkCanvas> SK_API SkCreateColorSpaceXformCanvas(SkCanvas* target,\n                                                               sk_sp<SkColorSpace> targetCS);\n\n#endif  //SkColorSpaceXformCanvas_DEFINED\n"
  },
  {
    "path": "include/core/SkCoverageMode.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCoverageMode_DEFINED\n#define SkCoverageMode_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n *  Describes geometric operations (ala SkRegion::Op) that can be applied to coverage bytes.\n *  These can be thought of as variants of porter-duff (SkBlendMode) modes, but only applied\n *  to the alpha channel.\n *\n *  See SkMaskFilter for ways to use these when combining two different masks.\n */\nenum class SkCoverageMode {\n    kUnion,             // A ∪ B    A+B-A*B\n    kIntersect,         // A ∩ B    A*B\n    kDifference,        // A - B    A*(1-B)\n    kReverseDifference, // B - A    B*(1-A)\n    kXor,               // A ⊕ B    A+B-2*A*B\n\n    kLast = kXor,\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkData.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkData_DEFINED\n#define SkData_DEFINED\n\n#include <stdio.h>\n\n#include \"SkRefCnt.h\"\n\nclass SkStream;\n\n/**\n *  SkData holds an immutable data buffer. Not only is the data immutable,\n *  but the actual ptr that is returned (by data() or bytes()) is guaranteed\n *  to always be the same for the life of this instance.\n */\nclass SK_API SkData final : public SkNVRefCnt<SkData> {\npublic:\n    /**\n     *  Returns the number of bytes stored.\n     */\n    size_t size() const { return fSize; }\n\n    bool isEmpty() const { return 0 == fSize; }\n\n    /**\n     *  Returns the ptr to the data.\n     */\n    const void* data() const { return fPtr; }\n\n    /**\n     *  Like data(), returns a read-only ptr into the data, but in this case\n     *  it is cast to uint8_t*, to make it easy to add an offset to it.\n     */\n    const uint8_t* bytes() const {\n        return reinterpret_cast<const uint8_t*>(fPtr);\n    }\n\n    /**\n     *  USE WITH CAUTION.\n     *  This call will assert that the refcnt is 1, as a precaution against modifying the\n     *  contents when another client/thread has access to the data.\n     */\n    void* writable_data() {\n        if (fSize) {\n            // only assert we're unique if we're not empty\n            SkASSERT(this->unique());\n        }\n        return fPtr;\n    }\n\n    /**\n     *  Helper to copy a range of the data into a caller-provided buffer.\n     *  Returns the actual number of bytes copied, after clamping offset and\n     *  length to the size of the data. If buffer is NULL, it is ignored, and\n     *  only the computed number of bytes is returned.\n     */\n    size_t copyRange(size_t offset, size_t length, void* buffer) const;\n\n    /**\n     *  Returns true if these two objects have the same length and contents,\n     *  effectively returning 0 == memcmp(...)\n     */\n    bool equals(const SkData* other) const;\n\n    /**\n     *  Function that, if provided, will be called when the SkData goes out\n     *  of scope, allowing for custom allocation/freeing of the data's contents.\n     */\n    typedef void (*ReleaseProc)(const void* ptr, void* context);\n\n    /**\n     *  Create a new dataref by copying the specified data\n     */\n    static sk_sp<SkData> MakeWithCopy(const void* data, size_t length);\n\n\n    /**\n     *  Create a new data with uninitialized contents. The caller should call writable_data()\n     *  to write into the buffer, but this must be done before another ref() is made.\n     */\n    static sk_sp<SkData> MakeUninitialized(size_t length);\n\n    /**\n     *  Create a new dataref by copying the specified c-string\n     *  (a null-terminated array of bytes). The returned SkData will have size()\n     *  equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same\n     *  as \"\".\n     */\n    static sk_sp<SkData> MakeWithCString(const char cstr[]);\n\n    /**\n     *  Create a new dataref, taking the ptr as is, and using the\n     *  releaseproc to free it. The proc may be NULL.\n     */\n    static sk_sp<SkData> MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx);\n\n    /**\n     *  Call this when the data parameter is already const and will outlive the lifetime of the\n     *  SkData. Suitable for with const globals.\n     */\n    static sk_sp<SkData> MakeWithoutCopy(const void* data, size_t length) {\n        return MakeWithProc(data, length, DummyReleaseProc, nullptr);\n    }\n\n    /**\n     *  Create a new dataref from a pointer allocated by malloc. The Data object\n     *  takes ownership of that allocation, and will handling calling sk_free.\n     */\n    static sk_sp<SkData> MakeFromMalloc(const void* data, size_t length);\n\n    /**\n     *  Create a new dataref the file with the specified path.\n     *  If the file cannot be opened, this returns NULL.\n     */\n    static sk_sp<SkData> MakeFromFileName(const char path[]);\n\n    /**\n     *  Create a new dataref from a stdio FILE.\n     *  This does not take ownership of the FILE, nor close it.\n     *  The caller is free to close the FILE at its convenience.\n     *  The FILE must be open for reading only.\n     *  Returns NULL on failure.\n     */\n    static sk_sp<SkData> MakeFromFILE(FILE* f);\n\n    /**\n     *  Create a new dataref from a file descriptor.\n     *  This does not take ownership of the file descriptor, nor close it.\n     *  The caller is free to close the file descriptor at its convenience.\n     *  The file descriptor must be open for reading only.\n     *  Returns NULL on failure.\n     */\n    static sk_sp<SkData> MakeFromFD(int fd);\n\n    /**\n     *  Attempt to read size bytes into a SkData. If the read succeeds, return the data,\n     *  else return NULL. Either way the stream's cursor may have been changed as a result\n     *  of calling read().\n     */\n    static sk_sp<SkData> MakeFromStream(SkStream*, size_t size);\n\n    /**\n     *  Create a new dataref using a subset of the data in the specified\n     *  src dataref.\n     */\n    static sk_sp<SkData> MakeSubset(const SkData* src, size_t offset, size_t length);\n\n    /**\n     *  Returns a new empty dataref (or a reference to a shared empty dataref).\n     *  New or shared, the caller must see that unref() is eventually called.\n     */\n    static sk_sp<SkData> MakeEmpty();\n\nprivate:\n    friend class SkNVRefCnt<SkData>;\n    ReleaseProc fReleaseProc;\n    void*       fReleaseProcContext;\n    void*       fPtr;\n    size_t      fSize;\n\n    SkData(const void* ptr, size_t size, ReleaseProc, void* context);\n    explicit SkData(size_t size);   // inplace new/delete\n    ~SkData();\n\n    // Ensure the unsized delete is called.\n    void operator delete(void* p) { ::operator delete(p); }\n\n    // shared internal factory\n    static sk_sp<SkData> PrivateNewWithCopy(const void* srcOrNull, size_t length);\n\n    static void DummyReleaseProc(const void*, void*); // {}\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDataTable.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDataTable_DEFINED\n#define SkDataTable_DEFINED\n\n#include \"../private/SkTDArray.h\"\n#include \"SkData.h\"\n#include \"SkString.h\"\n\n/**\n *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is\n *  organized into a table of entries, each with a length, so the entries are\n *  not required to all be the same size.\n */\nclass SK_API SkDataTable : public SkRefCnt {\npublic:\n    /**\n     *  Returns true if the table is empty (i.e. has no entries).\n     */\n    bool isEmpty() const { return 0 == fCount; }\n\n    /**\n     *  Return the number of entries in the table. 0 for an empty table\n     */\n    int count() const { return fCount; }\n\n    /**\n     *  Return the size of the index'th entry in the table. The caller must\n     *  ensure that index is valid for this table.\n     */\n    size_t atSize(int index) const;\n\n    /**\n     *  Return a pointer to the data of the index'th entry in the table.\n     *  The caller must ensure that index is valid for this table.\n     *\n     *  @param size If non-null, this returns the byte size of this entry. This\n     *              will be the same value that atSize(index) would return.\n     */\n    const void* at(int index, size_t* size = nullptr) const;\n\n    template <typename T>\n    const T* atT(int index, size_t* size = nullptr) const {\n        return reinterpret_cast<const T*>(this->at(index, size));\n    }\n\n    /**\n     *  Returns the index'th entry as a c-string, and assumes that the trailing\n     *  null byte had been copied into the table as well.\n     */\n    const char* atStr(int index) const {\n        size_t size;\n        const char* str = this->atT<const char>(index, &size);\n        SkASSERT(strlen(str) + 1 == size);\n        return str;\n    }\n\n    typedef void (*FreeProc)(void* context);\n\n    static sk_sp<SkDataTable> MakeEmpty();\n\n    /**\n     *  Return a new DataTable that contains a copy of the data stored in each\n     *  \"array\".\n     *\n     *  @param ptrs array of points to each element to be copied into the table.\n     *  @param sizes array of byte-lengths for each entry in the corresponding\n     *               ptrs[] array.\n     *  @param count the number of array elements in ptrs[] and sizes[] to copy.\n     */\n    static sk_sp<SkDataTable> MakeCopyArrays(const void * const * ptrs,\n                                             const size_t sizes[], int count);\n\n    /**\n     *  Return a new table that contains a copy of the data in array.\n     *\n     *  @param array contiguous array of data for all elements to be copied.\n     *  @param elemSize byte-length for a given element.\n     *  @param count the number of entries to be copied out of array. The number\n     *               of bytes that will be copied is count * elemSize.\n     */\n    static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);\n\n    static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,\n                                            FreeProc proc, void* context);\n\nprivate:\n    struct Dir {\n        const void* fPtr;\n        uintptr_t   fSize;\n    };\n\n    int         fCount;\n    size_t      fElemSize;\n    union {\n        const Dir*  fDir;\n        const char* fElems;\n    } fU;\n\n    FreeProc    fFreeProc;\n    void*       fFreeProcContext;\n\n    SkDataTable();\n    SkDataTable(const void* array, size_t elemSize, int count,\n                FreeProc, void* context);\n    SkDataTable(const Dir*, int count, FreeProc, void* context);\n    virtual ~SkDataTable();\n\n    friend class SkDataTableBuilder;    // access to Dir\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDeferredDisplayListRecorder.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDeferredDisplayListMaker_DEFINED\n#define SkDeferredDisplayListMaker_DEFINED\n\n#include \"SkImageInfo.h\"\n#include \"SkRefCnt.h\"\n#include \"SkSurfaceCharacterization.h\"\n#include \"SkTypes.h\"\n\n#include \"../private/SkDeferredDisplayList.h\"\n\nclass GrBackendFormat;\nclass GrBackendTexture;\nclass GrContext;\n\nclass SkCanvas;\nclass SkImage;\nclass SkSurface;\n\n/*\n * This class is intended to be used as:\n *   Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface\n *   Create one of these (an SkDDLMaker) on the stack\n *   Get the canvas and render into it\n *   Snap off and hold on to an SkDeferredDisplayList\n *   Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)\n *\n * This class never accesses the GPU but performs all the cpu work it can. It\n * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side\n * work in parallel ahead of time).\n */\nclass SK_API SkDeferredDisplayListRecorder {\npublic:\n    SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);\n    ~SkDeferredDisplayListRecorder();\n\n    const SkSurfaceCharacterization& characterization() const {\n        return fCharacterization;\n    }\n\n    // The backing canvas will become invalid (and this entry point will return\n    // null) once 'detach' is called.\n    // Note: ownership of the SkCanvas is not transfered via this call.\n    SkCanvas* getCanvas();\n\n    std::unique_ptr<SkDeferredDisplayList> detach();\n\n    // Matches the defines in SkImage_Gpu.h\n    typedef void* TextureContext;\n    typedef void (*TextureReleaseProc)(TextureContext textureContext);\n    typedef void (*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);\n    typedef void (*PromiseDoneProc)(TextureContext textureContext);\n\n    /**\n        Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main\n        difference is that the client doesn't have the backend texture on the gpu yet but they know\n        all the properties of the texture. So instead of passing in a GrBackendTexture the client\n        supplies a GrBackendFormat, width, height, and GrMipMapped state.\n\n        When we actually send the draw calls to the GPU, we will call the textureFulfillProc and\n        the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must\n        match those set during the SkImage creation, and it must have a valid backend gpu texture.\n        The gpu texture supplied by the client must stay valid until we call the textureReleaseProc.\n\n        When we are done with the texture returned by the textureFulfillProc we will call the\n        textureReleaseProc passing in the textureContext. This is a signal to the client that they\n        are free to delete the underlying gpu texture. If future draws also use the same promise\n        image we will call the textureFulfillProc again if we've already called the\n        textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in pairs.\n        In other words we will never call textureFulfillProc or textureReleaseProc multiple times\n        for the same textureContext before calling the other.\n\n        We we call the promiseDoneProc when we will no longer call the textureFulfillProc again. We\n        pass in the textureContext as a parameter to the promiseDoneProc. We also guarantee that\n        there will be no outstanding textureReleaseProcs that still need to be called when we call\n        the textureDoneProc. Thus when the textureDoneProc gets called the client is able to cleanup\n        all GPU objects and meta data needed for the textureFulfill call.\n\n        This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context.\n\n        @param backendFormat       format of promised gpu texture\n        @param width               width of promised gpu texture\n        @param height              height of promised gpu texture\n        @param mipMapped           mip mapped state of promised gpu texture\n        @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorType           one of: kUnknown_SkColorType, kAlpha_8_SkColorType,\n                                   kRGB_565_SkColorType, kARGB_4444_SkColorType,\n                                   kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,\n                                   kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param alphaType           one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,\n                                   kPremul_SkAlphaType, kUnpremul_SkAlphaType\n        @param colorSpace          range of colors; may be nullptr\n        @param textureFulfillProc  function called to get actual gpu texture\n        @param textureReleaseProc  function called when texture can be released\n        @param promiseDoneProc     function called when we will no longer call textureFulfillProc\n        @param textureContext      state passed to textureFulfillProc and textureReleaseProc\n        @return                    created SkImage, or nullptr\n     */\n    sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,\n                                      int width,\n                                      int height,\n                                      GrMipMapped mipMapped,\n                                      GrSurfaceOrigin origin,\n                                      SkColorType colorType,\n                                      SkAlphaType alphaType,\n                                      sk_sp<SkColorSpace> colorSpace,\n                                      TextureFulfillProc textureFulfillProc,\n                                      TextureReleaseProc textureReleaseProc,\n                                      PromiseDoneProc promiseDoneProc,\n                                      TextureContext textureContext);\n\nprivate:\n    bool init();\n\n    const SkSurfaceCharacterization             fCharacterization;\n\n#if SK_SUPPORT_GPU\n    sk_sp<GrContext>                            fContext;\n    sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;\n    sk_sp<SkSurface>                            fSurface;\n#endif\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDeque.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkDeque_DEFINED\n#define SkDeque_DEFINED\n\n#include \"SkTypes.h\"\n\n/*\n * The deque class works by blindly creating memory space of a specified element\n * size. It manages the memory as a doubly linked list of blocks each of which\n * can contain multiple elements. Pushes and pops add/remove blocks from the\n * beginning/end of the list as necessary while each block tracks the used\n * portion of its memory.\n * One behavior to be aware of is that the pops do not immediately remove an\n * empty block from the beginning/end of the list (Presumably so push/pop pairs\n * on the block boundaries don't cause thrashing). This can result in the first/\n * last element not residing in the first/last block.\n */\nclass SK_API SkDeque : SkNoncopyable {\npublic:\n    /**\n     * elemSize specifies the size of each individual element in the deque\n     * allocCount specifies how many elements are to be allocated as a block\n     */\n    explicit SkDeque(size_t elemSize, int allocCount = 1);\n    SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCount = 1);\n    ~SkDeque();\n\n    bool    empty() const { return 0 == fCount; }\n    int     count() const { return fCount; }\n    size_t  elemSize() const { return fElemSize; }\n\n    const void* front() const { return fFront; }\n    const void* back() const  { return fBack; }\n\n    void* front() {\n        return (void*)((const SkDeque*)this)->front();\n    }\n\n    void* back() {\n        return (void*)((const SkDeque*)this)->back();\n    }\n\n    /**\n     * push_front and push_back return a pointer to the memory space\n     * for the new element\n     */\n    void* push_front();\n    void* push_back();\n\n    void pop_front();\n    void pop_back();\n\nprivate:\n    struct Block;\n\npublic:\n    class Iter {\n    public:\n        enum IterStart {\n            kFront_IterStart,\n            kBack_IterStart,\n        };\n\n        /**\n         * Creates an uninitialized iterator. Must be reset()\n         */\n        Iter();\n\n        Iter(const SkDeque& d, IterStart startLoc);\n        void* next();\n        void* prev();\n\n        void reset(const SkDeque& d, IterStart startLoc);\n\n    private:\n        SkDeque::Block* fCurBlock;\n        char*           fPos;\n        size_t          fElemSize;\n    };\n\n    // Inherit privately from Iter to prevent access to reverse iteration\n    class F2BIter : private Iter {\n    public:\n        F2BIter() {}\n\n        /**\n         * Wrap Iter's 2 parameter ctor to force initialization to the\n         * beginning of the deque\n         */\n        F2BIter(const SkDeque& d) : INHERITED(d, kFront_IterStart) {}\n\n        using Iter::next;\n\n        /**\n         * Wrap Iter::reset to force initialization to the beginning of the\n         * deque\n         */\n        void reset(const SkDeque& d) {\n            this->INHERITED::reset(d, kFront_IterStart);\n        }\n\n    private:\n        typedef Iter INHERITED;\n    };\n\nprivate:\n    // allow unit test to call numBlocksAllocated\n    friend class DequeUnitTestHelper;\n\n    void*   fFront;\n    void*   fBack;\n\n    Block*  fFrontBlock;\n    Block*  fBackBlock;\n    size_t  fElemSize;\n    void*   fInitialStorage;\n    int     fCount;             // number of elements in the deque\n    int     fAllocCount;        // number of elements to allocate per block\n\n    Block*  allocateBlock(int allocCount);\n    void    freeBlock(Block* block);\n\n    /**\n     * This returns the number of chunk blocks allocated by the deque. It\n     * can be used to gauge the effectiveness of the selected allocCount.\n     */\n    int  numBlocksAllocated() const;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDocument.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDocument_DEFINED\n#define SkDocument_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkPicture.h\"\n#include \"SkRect.h\"\n#include \"SkRefCnt.h\"\n#include \"SkString.h\"\n#include \"SkTime.h\"\n\nclass SkCanvas;\nclass SkWStream;\n\n#ifdef SK_BUILD_FOR_WIN\nstruct IXpsOMObjectFactory;\n#endif\n\n/** SK_ScalarDefaultDPI is 72 DPI.\n*/\n#define SK_ScalarDefaultRasterDPI           72.0f\n\n/**\n *  High-level API for creating a document-based canvas. To use..\n *\n *  1. Create a document, specifying a stream to store the output.\n *  2. For each \"page\" of content:\n *      a. canvas = doc->beginPage(...)\n *      b. draw_my_content(canvas);\n *      c. doc->endPage();\n *  3. Close the document with doc->close().\n */\nclass SK_API SkDocument : public SkRefCnt {\npublic:\n    struct OptionalTimestamp {\n        SkTime::DateTime fDateTime;\n        bool fEnabled;\n        OptionalTimestamp() : fEnabled(false) {}\n    };\n\n    /**\n     *  Optional metadata to be passed into the PDF factory function.\n     */\n    struct PDFMetadata {\n        /**\n         * The document's title.\n         */\n        SkString fTitle;\n        /**\n         * The name of the person who created the document.\n         */\n        SkString fAuthor;\n        /**\n         * The subject of the document.\n         */\n        SkString fSubject;\n        /**\n         * Keywords associated with the document.  Commas may be used\n         * to delineate keywords within the string.\n         */\n        SkString fKeywords;\n        /**\n         * If the document was converted to PDF from another format,\n         * the name of the conforming product that created the\n         * original document from which it was converted.\n         */\n        SkString fCreator;\n        /**\n         * The product that is converting this document to PDF.\n         *\n         * Leave fProducer empty to get the default, correct value.\n         */\n        SkString fProducer;\n        /**\n         * The date and time the document was created.\n         */\n        OptionalTimestamp fCreation;\n        /**\n         * The date and time the document was most recently modified.\n         */\n        OptionalTimestamp fModified;\n\n        /** The DPI (pixels-per-inch) at which features without\n         *  native PDF support will be rasterized (e.g. draw image\n         *  with perspective, draw text with perspective, ...)  A\n         *  larger DPI would create a PDF that reflects the\n         *  original intent with better fidelity, but it can make\n         *  for larger PDF files too, which would use more memory\n         *  while rendering, and it would be slower to be processed\n         *  or sent online or to printer.\n         */\n        SkScalar fRasterDPI = SK_ScalarDefaultRasterDPI;\n\n        /** If true, include XMP metadata, a document UUID, and sRGB output intent information.\n         *  This adds length to the document and makes it non-reproducable, but are necessary\n         *  features for PDF/A-2b conformance\n         */\n        bool fPDFA = false;\n\n        /**\n         *  Encoding quality controls the trade-off between size and quality. By default this is\n         *  set to 101 percent, which corresponds to lossless encoding. If this value is set to\n         *  a value <= 100, and the image is opaque, it will be encoded (using JPEG) with that\n         *  quality setting.\n         */\n        int fEncodingQuality = 101;\n    };\n\n    /**\n     *  Create a PDF-backed document, writing the results into a\n     *  SkWStream.\n     *\n     *  PDF pages are sized in point units. 1 pt == 1/72 inch == 127/360 mm.\n     *\n     *  @param stream A PDF document will be written to this stream.  The document may write\n     *         to the stream at anytime during its lifetime, until either close() is\n     *         called or the document is deleted.\n     *  @param metadata a PDFmetadata object.  Any fields may be left empty.\n     *\n     *  @returns NULL if there is an error, otherwise a newly created PDF-backed SkDocument.\n     */\n    static sk_sp<SkDocument> MakePDF(SkWStream* stream, const PDFMetadata& metadata);\n    static sk_sp<SkDocument> MakePDF(SkWStream* stream);\n\n#ifdef SK_BUILD_FOR_WIN\n    /**\n     *  Create a XPS-backed document, writing the results into the stream.\n     *\n     *  @param stream A XPS document will be written to this stream.  The\n     *                document may write to the stream at anytime during its\n     *                lifetime, until either close() or abort() are called or\n     *                the document is deleted.\n     *  @param xpsFactory A pointer to a COM XPS factory.  Must be non-null.\n     *                    The document will take a ref to the factory. See\n     *                    dm/DMSrcSink.cpp for an example.\n     *  @param dpi The DPI (pixels-per-inch) at which features without\n     *             native XPS support will be rasterized (e.g. draw image\n     *             with perspective, draw text with perspective, ...)  A\n     *             larger DPI would create a XPS that reflects the\n     *             original intent with better fidelity, but it can make\n     *             for larger XPS files too, which would use more memory\n     *             while rendering, and it would be slower to be processed\n     *             or sent online or to printer.\n     *\n     *  @returns nullptr if XPS is not supported.\n     */\n    static sk_sp<SkDocument> MakeXPS(SkWStream* stream,\n                                     IXpsOMObjectFactory* xpsFactory,\n                                     SkScalar dpi = SK_ScalarDefaultRasterDPI);\n#endif\n\n    /**\n     *  Begin a new page for the document, returning the canvas that will draw\n     *  into the page. The document owns this canvas, and it will go out of\n     *  scope when endPage() or close() is called, or the document is deleted.\n     */\n    SkCanvas* beginPage(SkScalar width, SkScalar height, const SkRect* content = nullptr);\n\n    /**\n     *  Call endPage() when the content for the current page has been drawn\n     *  (into the canvas returned by beginPage()). After this call the canvas\n     *  returned by beginPage() will be out-of-scope.\n     */\n    void endPage();\n\n    /**\n     *  Call close() when all pages have been drawn. This will close the file\n     *  or stream holding the document's contents. After close() the document\n     *  can no longer add new pages. Deleting the document will automatically\n     *  call close() if need be.\n     */\n    void close();\n\n    /**\n     *  Call abort() to stop producing the document immediately.\n     *  The stream output must be ignored, and should not be trusted.\n     */\n    void abort();\n\nprotected:\n    SkDocument(SkWStream*);\n\n    // note: subclasses must call close() in their destructor, as the base class\n    // cannot do this for them.\n    virtual ~SkDocument();\n\n    virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height) = 0;\n    virtual void onEndPage() = 0;\n    virtual void onClose(SkWStream*) = 0;\n    virtual void onAbort() = 0;\n\n    // Allows subclasses to write to the stream as pages are written.\n    SkWStream* getStream() { return fStream; }\n\n    enum State {\n        kBetweenPages_State,\n        kInPage_State,\n        kClosed_State\n    };\n    State getState() const { return fState; }\n\nprivate:\n    SkWStream* fStream;\n    State      fState;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDrawFilter.h",
    "content": "\n/*\n * Copyright 2011 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkDrawFilter_DEFINED\n#define SkDrawFilter_DEFINED\n\n#include \"SkRefCnt.h\"\n\nclass SkCanvas;\nclass SkPaint;\n\n/**\n *  DEPRECATED - use SkPaintFilterCanvas instead.\n *\n *  Right before something is being draw, filter() is called with the\n *  paint. The filter may modify the paint as it wishes, which will then be\n *  used for the actual drawing. Note: this modification only lasts for the\n *  current draw, as a temporary copy of the paint is used.\n */\nclass SK_API SkDrawFilter : public SkRefCnt {\npublic:\n    enum Type {\n        kPaint_Type,\n        kPoint_Type,\n        kLine_Type,\n        kBitmap_Type,\n        kRect_Type,\n        kRRect_Type,\n        kOval_Type,\n        kPath_Type,\n        kText_Type,\n    };\n\n    static constexpr int kTypeCount = kText_Type + 1;\n\n    /**\n     *  Called with the paint that will be used to draw the specified type.\n     *  The implementation may modify the paint as they wish. If filter()\n     *  returns false, the draw will be skipped.\n     */\n    virtual bool filter(SkPaint*, Type) = 0;\n\nprivate:\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDrawLooper.h",
    "content": "\n/*\n * Copyright 2011 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkDrawLooper_DEFINED\n#define SkDrawLooper_DEFINED\n\n#include \"SkBlurTypes.h\"\n#include \"SkFlattenable.h\"\n#include \"SkPoint.h\"\n#include \"SkColor.h\"\n\nclass  SkArenaAlloc;\nclass  SkCanvas;\nclass  SkColorSpaceXformer;\nclass  SkPaint;\nstruct SkRect;\nclass  SkString;\n\n/** \\class SkDrawLooper\n    Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,\n    and something is drawn to a canvas with that paint, the looper subclass will\n    be called, allowing it to modify the canvas and/or paint for that draw call.\n    More than that, via the next() method, the looper can modify the draw to be\n    invoked multiple times (hence the name loop-er), allow it to perform effects\n    like shadows or frame/fills, that require more than one pass.\n*/\nclass SK_API SkDrawLooper : public SkFlattenable {\npublic:\n    /**\n     *  Holds state during a draw. Users call next() until it returns false.\n     *\n     *  Subclasses of SkDrawLooper should create a subclass of this object to\n     *  hold state specific to their subclass.\n     */\n    class SK_API Context : ::SkNoncopyable {\n    public:\n        Context() {}\n        virtual ~Context() {}\n\n        /**\n         *  Called in a loop on objects returned by SkDrawLooper::createContext().\n         *  Each time true is returned, the object is drawn (possibly with a modified\n         *  canvas and/or paint). When false is finally returned, drawing for the object\n         *  stops.\n         *\n         *  On each call, the paint will be in its original state, but the\n         *  canvas will be as it was following the previous call to next() or\n         *  createContext().\n         *\n         *  The implementation must ensure that, when next() finally returns\n         *  false, the canvas has been restored to the state it was\n         *  initially, before createContext() was first called.\n         */\n        virtual bool next(SkCanvas* canvas, SkPaint* paint) = 0;\n    };\n\n    /**\n     *  Called right before something is being drawn. Returns a Context\n     *  whose next() method should be called until it returns false.\n     */\n    virtual Context* makeContext(SkCanvas*, SkArenaAlloc*) const = 0;\n\n    /**\n     * The fast bounds functions are used to enable the paint to be culled early\n     * in the drawing pipeline. If a subclass can support this feature it must\n     * return true for the canComputeFastBounds() function.  If that function\n     * returns false then computeFastBounds behavior is undefined otherwise it\n     * is expected to have the following behavior. Given the parent paint and\n     * the parent's bounding rect the subclass must fill in and return the\n     * storage rect, where the storage rect is with the union of the src rect\n     * and the looper's bounding rect.\n     */\n    bool canComputeFastBounds(const SkPaint& paint) const;\n    void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;\n\n    struct BlurShadowRec {\n        SkScalar        fSigma;\n        SkVector        fOffset;\n        SkColor         fColor;\n        SkBlurStyle     fStyle;\n    };\n    /**\n     *  If this looper can be interpreted as having two layers, such that\n     *      1. The first layer (bottom most) just has a blur and translate\n     *      2. The second layer has no modifications to either paint or canvas\n     *      3. No other layers.\n     *  then return true, and if not null, fill out the BlurShadowRec).\n     *\n     *  If any of the above are not met, return false and ignore the BlurShadowRec parameter.\n     */\n    virtual bool asABlurShadow(BlurShadowRec*) const;\n\n    virtual void toString(SkString* str) const = 0;\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkDrawLooper_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkDrawLooper_Type;\n    }\n\n    static sk_sp<SkDrawLooper> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkDrawLooper>(static_cast<SkDrawLooper*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkDrawLooper_Type, data, size, procs).release()));\n    }\n\nprotected:\n    sk_sp<SkDrawLooper> makeColorSpace(SkColorSpaceXformer* xformer) const {\n        return this->onMakeColorSpace(xformer);\n    }\n    virtual sk_sp<SkDrawLooper> onMakeColorSpace(SkColorSpaceXformer*) const = 0;\n\n    SkDrawLooper() {}\n\nprivate:\n    friend class SkColorSpaceXformer;\n\n    typedef SkFlattenable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkDrawable.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDrawable_DEFINED\n#define SkDrawable_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkScalar.h\"\n\nclass SkCanvas;\nclass SkMatrix;\nclass SkPicture;\nstruct SkRect;\n\n/**\n *  Base-class for objects that draw into SkCanvas.\n *\n *  The object has a generation ID, which is guaranteed to be unique across all drawables. To\n *  allow for clients of the drawable that may want to cache the results, the drawable must\n *  change its generation ID whenever its internal state changes such that it will draw differently.\n */\nclass SK_API SkDrawable : public SkFlattenable {\npublic:\n    SkDrawable();\n\n    /**\n     *  Draws into the specified content. The drawing sequence will be balanced upon return\n     *  (i.e. the saveLevel() on the canvas will match what it was when draw() was called,\n     *  and the current matrix and clip settings will not be changed.\n     */\n    void draw(SkCanvas*, const SkMatrix* = nullptr);\n    void draw(SkCanvas*, SkScalar x, SkScalar y);\n\n    SkPicture* newPictureSnapshot();\n\n    /**\n     *  Return a unique value for this instance. If two calls to this return the same value,\n     *  it is presumed that calling the draw() method will render the same thing as well.\n     *\n     *  Subclasses that change their state should call notifyDrawingChanged() to ensure that\n     *  a new value will be returned the next time it is called.\n     */\n    uint32_t getGenerationID();\n\n    /**\n     *  Return the (conservative) bounds of what the drawable will draw. If the drawable can\n     *  change what it draws (e.g. animation or in response to some external change), then this\n     *  must return a bounds that is always valid for all possible states.\n     */\n    SkRect getBounds();\n\n    /**\n     *  Calling this invalidates the previous generation ID, and causes a new one to be computed\n     *  the next time getGenerationID() is called. Typically this is called by the object itself,\n     *  in response to its internal state changing.\n     */\n    void notifyDrawingChanged();\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkDrawable_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkDrawable_Type;\n    }\n\n    static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkDrawable>(static_cast<SkDrawable*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkDrawable_Type, data, size, procs).release()));\n    }\n\n    Factory getFactory() const override { return nullptr; }\n\nprotected:\n    virtual SkRect onGetBounds() = 0;\n    virtual void onDraw(SkCanvas*) = 0;\n\n    /**\n     *  Default implementation calls onDraw() with a canvas that records into a picture. Subclasses\n     *  may override if they have a more efficient way to return a picture for the current state\n     *  of their drawable. Note: this picture must draw the same as what would be drawn from\n     *  onDraw().\n     */\n    virtual SkPicture* onNewPictureSnapshot();\n\nprivate:\n    int32_t fGenerationID;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkEncodedImageFormat.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEncodedImageFormat_DEFINED\n#define SkEncodedImageFormat_DEFINED\n\n#include <stdint.h>\n\n/**\n *  Enum describing format of encoded data.\n */\nenum class SkEncodedImageFormat {\n#ifdef SK_BUILD_FOR_GOOGLE3\n    kUnknown,\n#endif\n    kBMP,\n    kGIF,\n    kICO,\n    kJPEG,\n    kPNG,\n    kWBMP,\n    kWEBP,\n    kPKM,\n    kKTX,\n    kASTC,\n    kDNG,\n    kHEIF,\n};\n\n#endif  // SkEncodedImageFormat_DEFINED\n"
  },
  {
    "path": "include/core/SkExecutor.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkExecutor_DEFINED\n#define SkExecutor_DEFINED\n\n#include <functional>\n#include <memory>\n\nclass SkExecutor {\npublic:\n    virtual ~SkExecutor();\n\n    // Create a thread pool SkExecutor with a fixed thread count, by default the number of cores.\n    static std::unique_ptr<SkExecutor> MakeFIFOThreadPool(int threads = 0);\n    static std::unique_ptr<SkExecutor> MakeLIFOThreadPool(int threads = 0);\n\n    // There is always a default SkExecutor available by calling SkExecutor::GetDefault().\n    static SkExecutor& GetDefault();\n    static void SetDefault(SkExecutor*);  // Does not take ownership.  Not thread safe.\n\n    // Add work to execute.\n    virtual void add(std::function<void(void)>) = 0;\n\n    // If it makes sense for this executor, use this thread to execute work for a little while.\n    virtual void borrow() {}\n};\n\n#endif//SkExecutor_DEFINED\n"
  },
  {
    "path": "include/core/SkFilterQuality.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFilterQuality_DEFINED\n#define SkFilterQuality_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n *  Controls how much filtering to be done when scaling/transforming complex colors\n *  e.g. images\n */\nenum SkFilterQuality {\n    kNone_SkFilterQuality,      //!< fastest but lowest quality, typically nearest-neighbor\n    kLow_SkFilterQuality,       //!< typically bilerp\n    kMedium_SkFilterQuality,    //!< typically bilerp + mipmaps for down-scaling\n    kHigh_SkFilterQuality,      //!< slowest but highest quality, typically bicubic or better\n\n    kLast_SkFilterQuality = kHigh_SkFilterQuality,\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkFlattenable.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFlattenable_DEFINED\n#define SkFlattenable_DEFINED\n\n#include \"SkRefCnt.h\"\n\nclass SkData;\nclass SkReadBuffer;\nclass SkWriteBuffer;\n\nstruct SkSerialProcs;\nstruct SkDeserialProcs;\n\n/** \\class SkFlattenable\n\n SkFlattenable is the base class for objects that need to be flattened\n into a data stream for either transport or as part of the key to the\n font cache.\n */\nclass SK_API SkFlattenable : public SkRefCnt {\npublic:\n    enum Type {\n        kSkColorFilter_Type,\n        kSkDrawable_Type,\n        kSkDrawLooper_Type,\n        kSkImageFilter_Type,\n        kSkMaskFilter_Type,\n        kSkPathEffect_Type,\n        kSkPixelRef_Type,\n        kSkUnused_Type4,    // used to be SkRasterizer\n        kSkShaderBase_Type,\n        kSkUnused_Type,     // used to be SkUnitMapper\n        kSkUnused_Type2,\n        kSkUnused_Type3,    // used to be SkNormalSource\n    };\n\n    typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);\n\n    SkFlattenable() {}\n\n    /** Implement this to return a factory function pointer that can be called\n     to recreate your class given a buffer (previously written to by your\n     override of flatten().\n     */\n    virtual Factory getFactory() const = 0;\n\n    /**\n     *  Returns the name of the object's class.\n     *\n     *  Subclasses should override this function if they intend to provide\n     *  support for flattening without using the global registry.\n     *\n     *  If the flattenable is registered, there is no need to override.\n     */\n    virtual const char* getTypeName() const { return FactoryToName(getFactory()); }\n\n    static Factory NameToFactory(const char name[]);\n    static const char* FactoryToName(Factory);\n    static bool NameToType(const char name[], Type* type);\n\n    static void Register(const char name[], Factory, Type);\n\n    /**\n     *  Override this if your subclass needs to record data that it will need to recreate itself\n     *  from its CreateProc (returned by getFactory()).\n     *\n     *  DEPRECATED public : will move to protected ... use serialize() instead\n     */\n    virtual void flatten(SkWriteBuffer&) const {}\n\n    virtual Type getFlattenableType() const = 0;\n\n    //\n    // public ways to serialize / deserialize\n    //\n    sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;\n    size_t serialize(void* memory, size_t memory_size,\n                     const SkSerialProcs* = nullptr) const;\n    static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,\n                                            const SkDeserialProcs* procs = nullptr);\n\nprotected:\n    class PrivateInitializer {\n    public:\n        static void InitCore();\n        static void InitEffects();\n    };\n\nprivate:\n    static void InitializeFlattenablesIfNeeded();\n    static void Finalize();\n\n    friend class SkGraphics;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkFont.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFont_DEFINED\n#define SkFont_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkScalar.h\"\n\nclass SkPaint;\nclass SkTypeface;\n\nenum SkTextEncoding {\n    kUTF8_SkTextEncoding,\n    kUTF16_SkTextEncoding,\n    kUTF32_SkTextEncoding,\n    kGlyphID_SkTextEncoding,\n};\n\n/*\n 1. The Hinting enum in SkPaint is gone entirely, absorbed into SkFont's flags.\n\n 2. SkPaint Flags look like this today\n\n enum Flags {\n     kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing\n     kDither_Flag          = 0x04,   //!< mask to enable dithering\n     kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text\n     kLinearText_Flag      = 0x40,   //!< mask to enable linear-text\n     kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning\n     kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering\n     kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes\n     kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter\n     kVerticalText_Flag    = 0x1000,\n };\n\n SkFont would absorb these:\n\n     kFakeBoldText_Flag    = 0x20,   //!< mask to enable fake-bold text\n     kLinearText_Flag      = 0x40,   //!< mask to enable linear-text\n     kSubpixelText_Flag    = 0x80,   //!< mask to enable subpixel text positioning\n     kLCDRenderText_Flag   = 0x200,  //!< mask to enable subpixel glyph renderering\n     kEmbeddedBitmapText_Flag = 0x400, //!< mask to enable embedded bitmap strikes\n     kAutoHinting_Flag     = 0x800,  //!< mask to force Freetype's autohinter\n     kVerticalText_Flag    = 0x1000,\n\n leaving these still in paint\n\n     kAntiAlias_Flag       = 0x01,   //!< mask to enable antialiasing\n     kDither_Flag          = 0x04,   //!< mask to enable dithering\n\n 3. Antialiasing\n\n    SkFont has a mask-type: BW, AA, LCD\n    SkPaint has antialias boolean\n\n    What to do if the font's mask-type disagrees with the paint?\n\n */\n\nclass SkFont : public SkRefCnt {\npublic:\n    enum Flags {\n        /**\n         *  Use the system's automatic hinting mechanism to hint the typeface.\n         *  This is a last resort hinting method applied only if other hinting methods do not apply.\n         *  TODO: where to put auto-normal vs auto-light?\n         */\n        kEnableAutoHints_Flag       = 1 << 0,\n\n        /**\n         *  If the typeface contains explicit bytecodes for hinting, use them.\n         *  If both bytecode and auto hints are specified, attempt to use the bytecodes first;\n         *  if that fails (e.g. there are no codes), then attempt to autohint.\n         */\n        kEnableByteCodeHints_Flag   = 1 << 1,\n\n        /**\n         *  If the typeface contains explicit bitmaps for hinting, use them.\n         *  If both bytecode and auto hints are also specified, attempt to use the bitmaps first;\n         *  if that fails (e.g. there are no bitmaps), then attempt to bytecode or autohint.\n         */\n        kEmbeddedBitmaps_Flag       = 1 << 2,\n\n        /**\n         *  Use rounded metric values (e.g. advance).\n         *  If either auto or bytecode hinting was used, apply those results to the metrics of the\n         *  glyphs as well. If no hinting was applied, the metrics will just be rounded to the\n         *  nearest integer.\n         *\n         *  This applies to calls that return metrics (e.g. measureText) and to drawing the glyphs\n         *  (see SkCanvas drawText and drawPosText).\n         */\n        kUseNonlinearMetrics_Flag   = 1 << 3,\n\n        kVertical_Flag              = 1 << 4,\n\n        kEmbolden_Flag              = 1 << 6,\n    };\n\n    enum MaskType {\n        kBW_MaskType,\n        kA8_MaskType,\n        kLCD_MaskType,\n    };\n\n    static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, MaskType, uint32_t flags);\n    static sk_sp<SkFont> Make(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX,\n                              MaskType, uint32_t flags);\n\n    /**\n     *  Return a font with the same attributes of this font, but with the specified size.\n     *  If size is not supported (e.g. <= 0 or non-finite) NULL will be returned.\n     */\n    sk_sp<SkFont> makeWithSize(SkScalar size) const;\n    /**\n     *  Return a font with the same attributes of this font, but with the flags.\n     */\n    sk_sp<SkFont> makeWithFlags(uint32_t newFlags) const;\n\n    SkTypeface* getTypeface() const { return fTypeface.get(); }\n    SkScalar    getSize() const { return fSize; }\n    SkScalar    getScaleX() const { return fScaleX; }\n    SkScalar    getSkewX() const { return fSkewX; }\n    uint32_t    getFlags() const { return fFlags; }\n    MaskType    getMaskType() const { return (MaskType)fMaskType; }\n\n    bool isVertical() const { return SkToBool(fFlags & kVertical_Flag); }\n    bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_Flag); }\n    bool isEnableAutoHints() const { return SkToBool(fFlags & kEnableAutoHints_Flag); }\n    bool isEnableByteCodeHints() const { return SkToBool(fFlags & kEnableByteCodeHints_Flag); }\n    bool isUseNonLinearMetrics() const { return SkToBool(fFlags & kUseNonlinearMetrics_Flag); }\n\n    int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding,\n                     SkGlyphID glyphs[], int maxGlyphCount) const;\n\n    int countText(const void* text, size_t byteLength, SkTextEncoding encoding) {\n        return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);\n    }\n\n    SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding) const;\n\n    static sk_sp<SkFont> Testing_CreateFromPaint(const SkPaint&);\n\nprivate:\n    static constexpr int kAllFlags = 0xFF;\n\n    SkFont(sk_sp<SkTypeface>, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType,\n           uint32_t flags);\n\n    sk_sp<SkTypeface> fTypeface;\n    SkScalar    fSize;\n    SkScalar    fScaleX;\n    SkScalar    fSkewX;\n    uint16_t    fFlags;\n    uint8_t     fMaskType;\n//  uint8_t     fPad;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkFontArguments.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontAgruments_DEFINED\n#define SkFontAgruments_DEFINED\n\n#include \"SkScalar.h\"\n#include \"SkTypes.h\"\n\n/** Represents a set of actual arguments for a font. */\nstruct SkFontArguments {\n    struct VariationPosition {\n        struct Coordinate {\n            SkFourByteTag axis;\n            SkScalar value;\n        };\n        const Coordinate* coordinates;\n        int coordinateCount;\n    };\n    // deprecated, use VariationCoordinate instead\n    struct Axis {\n       SkFourByteTag fTag;\n       SkScalar fStyleValue;\n    };\n\n    SkFontArguments() : fCollectionIndex(0), fVariationDesignPosition{nullptr, 0} {}\n\n    /** Specify the index of the desired font.\n     *\n     *  Font formats like ttc, dfont, cff, cid, pfr, t42, t1, and fon may actually be indexed\n     *  collections of fonts.\n     */\n    SkFontArguments& setCollectionIndex(int collectionIndex) {\n        fCollectionIndex = collectionIndex;\n        return *this;\n    }\n\n    // deprecated, use setVariationDesignPosition instead.\n    SkFontArguments& setAxes(const Axis* axes, int axisCount) {\n        fVariationDesignPosition.coordinates =\n                reinterpret_cast<const VariationPosition::Coordinate*>(axes);\n        fVariationDesignPosition.coordinateCount = axisCount;\n        return *this;\n    }\n\n    /** Specify a position in the variation design space.\n     *\n     *  Any axis not specified will use the default value.\n     *  Any specified axis not actually present in the font will be ignored.\n     *\n     *  @param position not copied. The value must remain valid for life of SkFontArguments.\n     */\n    SkFontArguments& setVariationDesignPosition(VariationPosition position) {\n        fVariationDesignPosition.coordinates = position.coordinates;\n        fVariationDesignPosition.coordinateCount = position.coordinateCount;\n        return *this;\n    }\n\n    int getCollectionIndex() const {\n        return fCollectionIndex;\n    }\n    // deprecated, use getVariationDesignPosition instead.\n    const Axis* getAxes(int* axisCount) const {\n        *axisCount = fVariationDesignPosition.coordinateCount;\n        return reinterpret_cast<const Axis*>(fVariationDesignPosition.coordinates);\n    }\n    VariationPosition getVariationDesignPosition() const {\n        return fVariationDesignPosition;\n    }\nprivate:\n    int fCollectionIndex;\n    VariationPosition fVariationDesignPosition;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkFontLCDConfig.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontLCDConfig_DEFINED\n#define SkFontLCDConfig_DEFINED\n\n#include \"SkTypes.h\"\n\nclass SK_API SkFontLCDConfig {\npublic:\n    /** LCDs either have their color elements arranged horizontally or\n        vertically. When rendering subpixel glyphs we need to know which way\n        round they are.\n\n        Note, if you change this after startup, you'll need to flush the glyph\n        cache because it'll have the wrong type of masks cached.\n\n        @deprecated use SkPixelGeometry instead.\n    */\n    enum LCDOrientation {\n        kHorizontal_LCDOrientation = 0,    //!< this is the default\n        kVertical_LCDOrientation   = 1,\n    };\n\n    /** @deprecated set on Device creation. */\n    static void SetSubpixelOrientation(LCDOrientation orientation);\n    /** @deprecated get from Device. */\n    static LCDOrientation GetSubpixelOrientation();\n\n    /** LCD color elements can vary in order. For subpixel text we need to know\n        the order which the LCDs uses so that the color fringes are in the\n        correct place.\n\n        Note, if you change this after startup, you'll need to flush the glyph\n        cache because it'll have the wrong type of masks cached.\n\n        kNONE_LCDOrder means that the subpixel elements are not spatially\n        separated in any usable fashion.\n\n        @deprecated use SkPixelGeometry instead.\n     */\n    enum LCDOrder {\n        kRGB_LCDOrder = 0,    //!< this is the default\n        kBGR_LCDOrder = 1,\n        kNONE_LCDOrder = 2,\n    };\n\n    /** @deprecated set on Device creation. */\n    static void SetSubpixelOrder(LCDOrder order);\n    /** @deprecated get from Device. */\n    static LCDOrder GetSubpixelOrder();\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkFontStyle.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontStyle_DEFINED\n#define SkFontStyle_DEFINED\n\n#include \"SkTypes.h\"\n\nclass SK_API SkFontStyle {\npublic:\n    enum Weight {\n        kInvisible_Weight   =    0,\n        kThin_Weight        =  100,\n        kExtraLight_Weight  =  200,\n        kLight_Weight       =  300,\n        kNormal_Weight      =  400,\n        kMedium_Weight      =  500,\n        kSemiBold_Weight    =  600,\n        kBold_Weight        =  700,\n        kExtraBold_Weight   =  800,\n        kBlack_Weight       =  900,\n        kExtraBlack_Weight  = 1000,\n    };\n\n    enum Width {\n        kUltraCondensed_Width   = 1,\n        kExtraCondensed_Width   = 2,\n        kCondensed_Width        = 3,\n        kSemiCondensed_Width    = 4,\n        kNormal_Width           = 5,\n        kSemiExpanded_Width     = 6,\n        kExpanded_Width         = 7,\n        kExtraExpanded_Width    = 8,\n        kUltraExpanded_Width    = 9,\n    };\n\n    enum Slant {\n        kUpright_Slant,\n        kItalic_Slant,\n        kOblique_Slant,\n    };\n\n    constexpr SkFontStyle(int weight, int width, Slant slant) : fValue(\n        (SkTPin<int>(weight, kInvisible_Weight, kExtraBlack_Weight)) +\n        (SkTPin<int>(width, kUltraCondensed_Width, kUltraExpanded_Width) << 16) +\n        (SkTPin<int>(slant, kUpright_Slant, kOblique_Slant) << 24)\n     ) { }\n\n    constexpr SkFontStyle() : SkFontStyle{kNormal_Weight, kNormal_Width, kUpright_Slant} { }\n\n    bool operator==(const SkFontStyle& rhs) const {\n        return fValue == rhs.fValue;\n    }\n\n    int weight() const { return fValue & 0xFFFF; }\n    int width() const { return (fValue >> 16) & 0xFF; }\n    Slant slant() const { return (Slant)((fValue >> 24) & 0xFF); }\n\n    static constexpr SkFontStyle Normal() {\n        return SkFontStyle(kNormal_Weight, kNormal_Width, kUpright_Slant);\n    }\n    static constexpr SkFontStyle Bold() {\n        return SkFontStyle(kBold_Weight,   kNormal_Width, kUpright_Slant);\n    }\n    static constexpr SkFontStyle Italic() {\n        return SkFontStyle(kNormal_Weight, kNormal_Width, kItalic_Slant );\n    }\n    static constexpr SkFontStyle BoldItalic() {\n        return SkFontStyle(kBold_Weight,   kNormal_Width, kItalic_Slant );\n    }\n\nprivate:\n    uint32_t fValue;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkGraphics.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkGraphics_DEFINED\n#define SkGraphics_DEFINED\n\n#include \"SkRefCnt.h\"\n\nclass SkData;\nclass SkImageGenerator;\nclass SkTraceMemoryDump;\n\nclass SK_API SkGraphics {\npublic:\n    /**\n     *  Call this at process initialization time if your environment does not\n     *  permit static global initializers that execute code.\n     *  Init() is thread-safe and idempotent.\n     */\n    static void Init();\n\n    // We're in the middle of cleaning this up.\n    static void Term() {}\n\n    /**\n     *  Return the version numbers for the library. If the parameter is not\n     *  null, it is set to the version number.\n     */\n    static void GetVersion(int32_t* major, int32_t* minor, int32_t* patch);\n\n    /**\n     *  Return the max number of bytes that should be used by the font cache.\n     *  If the cache needs to allocate more, it will purge previous entries.\n     *  This max can be changed by calling SetFontCacheLimit().\n     */\n    static size_t GetFontCacheLimit();\n\n    /**\n     *  Specify the max number of bytes that should be used by the font cache.\n     *  If the cache needs to allocate more, it will purge previous entries.\n     *\n     *  This function returns the previous setting, as if GetFontCacheLimit()\n     *  had be called before the new limit was set.\n     */\n    static size_t SetFontCacheLimit(size_t bytes);\n\n    /**\n     *  Return the number of bytes currently used by the font cache.\n     */\n    static size_t GetFontCacheUsed();\n\n    /**\n     *  Return the number of entries in the font cache.\n     *  A cache \"entry\" is associated with each typeface + pointSize + matrix.\n     */\n    static int GetFontCacheCountUsed();\n\n    /**\n     *  Return the current limit to the number of entries in the font cache.\n     *  A cache \"entry\" is associated with each typeface + pointSize + matrix.\n     */\n    static int GetFontCacheCountLimit();\n\n    /**\n     *  Set the limit to the number of entries in the font cache, and return\n     *  the previous value. If this new value is lower than the previous,\n     *  it will automatically try to purge entries to meet the new limit.\n     */\n    static int SetFontCacheCountLimit(int count);\n\n    /*\n     *  Returns the maximum point size for text that may be cached.\n     *\n     *  Sizes above this will be drawn directly from the font's outline.\n     *  Setting this to a large value may speed up drawing larger text (repeatedly),\n     *  but could cause the cache to purge other sizes more often.\n     *\n     *  This value is a hint to the font engine, and the actual limit may be different due to\n     *  implementation specific details.\n     */\n    static int GetFontCachePointSizeLimit();\n\n    /*\n     *  Set the maximum point size for text that may be cached, returning the previous value.\n     *\n     *  Sizes above this will be drawn directly from the font's outline.\n     *  Setting this to a large value may speed up drawing larger text (repeatedly),\n     *  but could cause the cache to purge other sizes more often.\n     *\n     *  This value is a hint to the font engine, and the actual limit may be different due to\n     *  implementation specific details.\n     */\n    static int SetFontCachePointSizeLimit(int maxPointSize);\n\n    /**\n     *  For debugging purposes, this will attempt to purge the font cache. It\n     *  does not change the limit, but will cause subsequent font measures and\n     *  draws to be recreated, since they will no longer be in the cache.\n     */\n    static void PurgeFontCache();\n\n    /**\n     *  Scaling bitmaps with the kHigh_SkFilterQuality setting is\n     *  expensive, so the result is saved in the global Scaled Image\n     *  Cache.\n     *\n     *  This function returns the memory usage of the Scaled Image Cache.\n     */\n    static size_t GetResourceCacheTotalBytesUsed();\n\n    /**\n     *  These functions get/set the memory usage limit for the resource cache, used for temporary\n     *  bitmaps and other resources. Entries are purged from the cache when the memory useage\n     *  exceeds this limit.\n     */\n    static size_t GetResourceCacheTotalByteLimit();\n    static size_t SetResourceCacheTotalByteLimit(size_t newLimit);\n\n    /**\n     *  For debugging purposes, this will attempt to purge the resource cache. It\n     *  does not change the limit.\n     */\n    static void PurgeResourceCache();\n\n    /**\n     *  When the cachable entry is very lage (e.g. a large scaled bitmap), adding it to the cache\n     *  can cause most/all of the existing entries to be purged. To avoid the, the client can set\n     *  a limit for a single allocation. If a cacheable entry would have been cached, but its size\n     *  exceeds this limit, then we do not attempt to cache it at all.\n     *\n     *  Zero is the default value, meaning we always attempt to cache entries.\n     */\n    static size_t GetResourceCacheSingleAllocationByteLimit();\n    static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit);\n\n    /**\n     *  Dumps memory usage of caches using the SkTraceMemoryDump interface. See SkTraceMemoryDump\n     *  for usage of this method.\n     */\n    static void DumpMemoryStatistics(SkTraceMemoryDump* dump);\n\n    /**\n     *  Free as much globally cached memory as possible. This will purge all private caches in Skia,\n     *  including font and image caches.\n     *\n     *  If there are caches associated with GPU context, those will not be affected by this call.\n     */\n    static void PurgeAllCaches();\n\n    /**\n     *  Applications with command line options may pass optional state, such\n     *  as cache sizes, here, for instance:\n     *  font-cache-limit=12345678\n     *\n     *  The flags format is name=value[;name=value...] with no spaces.\n     *  This format is subject to change.\n     */\n    static void SetFlags(const char* flags);\n\n    typedef std::unique_ptr<SkImageGenerator>\n                                            (*ImageGeneratorFromEncodedDataFactory)(sk_sp<SkData>);\n\n    /**\n     *  To instantiate images from encoded data, first looks at this runtime function-ptr. If it\n     *  exists, it is called to create an SkImageGenerator from SkData. If there is no function-ptr\n     *  or there is, but it returns NULL, then skia will call its internal default implementation.\n     *\n     *  Returns the previous factory (which could be NULL).\n     */\n    static ImageGeneratorFromEncodedDataFactory\n                    SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory);\n};\n\nclass SkAutoGraphics {\npublic:\n    SkAutoGraphics() {\n        SkGraphics::Init();\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkICC.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkICC_DEFINED\n#define SkICC_DEFINED\n\n#include \"SkData.h\"\n#include \"SkRefCnt.h\"\n\nstruct SkColorSpaceTransferFn;\n\nSK_API sk_sp<SkData> SkWriteICCProfile(const SkColorSpaceTransferFn&, const float toXYZD50[9]);\n\nnamespace SkICC {\n    static inline sk_sp<SkData> WriteToICC(const SkColorSpaceTransferFn& fn,\n                                           const SkMatrix44& toXYZD50) {\n        if (toXYZD50.get(3,0) == 0 && toXYZD50.get(3,1) == 0 && toXYZD50.get(3,2) == 0 &&\n            toXYZD50.get(3,3) == 1 &&\n            toXYZD50.get(0,3) == 0 && toXYZD50.get(1,3) == 0 && toXYZD50.get(2,3) == 0) {\n\n            float m33[9];\n            for (int r = 0; r < 3; r++)\n            for (int c = 0; c < 3; c++) {\n                m33[3*r+c] = toXYZD50.get(r,c);\n            }\n            return SkWriteICCProfile(fn, m33);\n\n        }\n        return nullptr;\n    }\n}\n\n#endif//SkICC_DEFINED\n"
  },
  {
    "path": "include/core/SkImage.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImage_DEFINED\n#define SkImage_DEFINED\n\n#include \"GrTypes.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkImageInfo.h\"\n#include \"SkImageEncoder.h\"\n#include \"SkRefCnt.h\"\n#include \"SkScalar.h\"\n#include \"SkShader.h\"\n\n#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26\n#include <android/hardware_buffer.h>\n#endif\n\nclass SkData;\nclass SkCanvas;\nclass SkImageFilter;\nclass SkImageGenerator;\nclass SkPaint;\nclass SkPicture;\nclass SkString;\nclass SkSurface;\nclass GrBackendTexture;\nclass GrContext;\nclass GrContextThreadSafeProxy;\nclass GrTexture;\n\n/** \\class SkImage\n    SkImage describes a two dimensional array of pixels to draw. The pixels may be\n    decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,\n    or located in GPU memory as a GPU texture.\n\n    SkImage cannot be modified after it is created. SkImage may allocate additional\n    storage as needed; for instance, an encoded SkImage may decode when drawn.\n\n    SkImage width and height are greater than zero. Creating an SkImage with zero width\n    or height returns SkImage equal to nullptr.\n\n    SkImage may be created from SkBitmap, SkPixmap, SkSurface, SkPicture, encoded streams,\n    GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported\n    include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details\n    vary with platform.\n*/\nclass SK_API SkImage : public SkRefCnt {\npublic:\n    typedef void* ReleaseContext;\n\n    /** Creates SkImage from SkPixmap and copy of pixels. Since pixels are copied, SkPixmap\n        pixels may be modified or deleted without affecting SkImage.\n\n        SkImage is returned if SkPixmap is valid. Valid SkPixmap parameters include:\n        dimensions are greater than zero;\n        each dimension fits in 29 bits;\n        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;\n        row bytes are large enough to hold one row of pixels;\n        pixel address is not nullptr.\n\n        @param pixmap  SkImageInfo, pixel address, and row bytes\n        @return        copy of SkPixmap pixels, or nullptr\n    */\n    static sk_sp<SkImage> MakeRasterCopy(const SkPixmap& pixmap);\n\n    /** Creates SkImage from SkImageInfo, sharing pixels.\n\n        SkImage is returned if SkImageInfo is valid. Valid SkImageInfo parameters include:\n        dimensions are greater than zero;\n        each dimension fits in 29 bits;\n        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;\n        rowBytes are large enough to hold one row of pixels;\n        pixels is not nullptr, and contains enough data for SkImage.\n\n        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace\n        @param pixels    address or pixel storage\n        @param rowBytes  size of pixel row or larger\n        @return          SkImage sharing pixels, or nullptr\n    */\n    static sk_sp<SkImage> MakeRasterData(const SkImageInfo& info, sk_sp<SkData> pixels,\n                                         size_t rowBytes);\n\n    typedef void (*RasterReleaseProc)(const void* pixels, ReleaseContext);\n\n    /** Creates SkImage from pixmap, sharing SkPixmap pixels. Pixels must remain valid and\n        unchanged until rasterReleaseProc is called. rasterReleaseProc is passed\n        releaseContext when SkImage is deleted or no longer refers to pixmap pixels.\n\n        Pass nullptr for rasterReleaseProc to share SkPixmap without requiring a callback\n        when SkImage is released. Pass nullptr for releaseContext if rasterReleaseProc\n        does not require state.\n\n        SkImage is returned if pixmap is valid. Valid SkPixmap parameters include:\n        dimensions are greater than zero;\n        each dimension fits in 29 bits;\n        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;\n        row bytes are large enough to hold one row of pixels;\n        pixel address is not nullptr.\n\n        @param pixmap             SkImageInfo, pixel address, and row bytes\n        @param rasterReleaseProc  function called when pixels can be released; or nullptr\n        @param releaseContext     state passed to rasterReleaseProc; or nullptr\n        @return                   SkImage sharing pixmap\n    */\n    static sk_sp<SkImage> MakeFromRaster(const SkPixmap& pixmap,\n                                         RasterReleaseProc rasterReleaseProc,\n                                         ReleaseContext releaseContext);\n\n    /** Creates SkImage from bitmap, sharing or copying bitmap pixels. If the bitmap\n        is marked immutable, and its pixel memory is shareable, it may be shared\n        instead of copied.\n\n        SkImage is returned if bitmap is valid. Valid SkBitmap parameters include:\n        dimensions are greater than zero;\n        each dimension fits in 29 bits;\n        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;\n        row bytes are large enough to hold one row of pixels;\n        pixel address is not nullptr.\n\n        @param bitmap  SkImageInfo, row bytes, and pixels\n        @return        created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromBitmap(const SkBitmap& bitmap);\n\n    /** Creates SkImage from data returned by imageGenerator. Generated data is owned by SkImage and may not\n        be shared or accessed.\n\n        subset allows selecting a portion of the full image. Pass nullptr to select the entire image;\n        otherwise, subset must be contained by image bounds.\n\n        SkImage is returned if generator data is valid. Valid data parameters vary by type of data\n        and platform.\n\n        imageGenerator may wrap SkPicture data, codec data, or custom data.\n\n        @param imageGenerator  stock or custom routines to retrieve SkImage\n        @param subset          bounds of returned SkImage; may be nullptr\n        @return                created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator,\n                                            const SkIRect* subset = nullptr);\n\n    /** Creates SkImage from encoded data.\n        subset allows selecting a portion of the full image. Pass nullptr to select the entire image;\n        otherwise, subset must be contained by image bounds.\n\n        SkImage is returned if format of the encoded data is recognized and supported.\n        Recognized formats vary by platform.\n\n        @param encoded  data of SkImage to decode\n        @param subset   bounds of returned SkImage; may be nullptr\n        @return         created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);\n\n    typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);\n\n    /** Creates SkImage from GPU texture associated with context. Caller is responsible for\n        managing the lifetime of GPU texture.\n\n        SkImage is returned if format of backendTexture is recognized and supported.\n        Recognized formats vary by GPU back-end.\n\n        @param context         GPU context\n        @param backendTexture  texture residing on GPU\n        @param origin          one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorType       one of:\n                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                               kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param alphaType       one of:\n                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                               kUnpremul_SkAlphaType\n        @param colorSpace      range of colors; may be nullptr\n        @return                created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromTexture(GrContext* context,\n                                          const GrBackendTexture& backendTexture,\n                                          GrSurfaceOrigin origin,\n                                          SkColorType colorType,\n                                          SkAlphaType alphaType,\n                                          sk_sp<SkColorSpace> colorSpace) {\n        return MakeFromTexture(context, backendTexture, origin, colorType, alphaType, colorSpace,\n                               nullptr, nullptr);\n    }\n\n    /** Creates SkImage from GPU texture associated with context. GPU texture must stay\n        valid and unchanged until textureReleaseProc is called. textureReleaseProc is\n        passed releaseContext when SkImage is deleted or no longer refers to texture.\n\n        SkImage is returned if format of backendTexture is recognized and supported.\n        Recognized formats vary by GPU back-end.\n\n        @param context             GPU context\n        @param backendTexture      texture residing on GPU\n        @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorType           one of:\n                                   kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                                   kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                                   kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                                   kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param alphaType           one of:\n                                   kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                                   kUnpremul_SkAlphaType\n        @param colorSpace          range of colors; may be nullptr\n        @param textureReleaseProc  function called when texture can be released\n        @param releaseContext      state passed to textureReleaseProc\n        @return                    created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromTexture(GrContext* context,\n                                          const GrBackendTexture& backendTexture,\n                                          GrSurfaceOrigin origin,\n                                          SkColorType colorType,\n                                          SkAlphaType alphaType,\n                                          sk_sp<SkColorSpace> colorSpace,\n                                          TextureReleaseProc textureReleaseProc,\n                                          ReleaseContext releaseContext);\n\n    /** Creates SkImage from encoded data. SkImage is uploaded to GPU back-end using context.\n\n        Created SkImage is available to other GPU contexts, and is available across thread\n        boundaries. All contexts must be in the same GPU_Share_Group, or otherwise\n        share resources.\n\n        When SkImage is no longer referenced, context releases texture memory\n        asynchronously.\n\n        GrBackendTexture decoded from data is uploaded to match SkSurface created with\n        dstColorSpace. SkColorSpace of SkImage is determined by encoded data.\n\n        SkImage is returned if format of data is recognized and supported, and if context\n        supports moving resources. Recognized formats vary by platform and GPU back-end.\n\n        SkImage is returned using MakeFromEncoded() if context is nullptr or does not support\n        moving resources between contexts.\n\n        @param context                GPU context\n        @param data                   SkImage to decode\n        @param buildMips              create SkImage as Mip_Map if true\n        @param dstColorSpace          range of colors of matching SkSurface on GPU\n        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary\n        @return                       created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> data,\n                                                      bool buildMips, SkColorSpace* dstColorSpace,\n                                                      bool limitToMaxTextureSize = false);\n\n    /** Creates SkImage from pixmap. SkImage is uploaded to GPU back-end using context.\n\n        Created SkImage is available to other GPU contexts, and is available across thread\n        boundaries. All contexts must be in the same GPU_Share_Group, or otherwise\n        share resources.\n\n        When SkImage is no longer referenced, context releases texture memory\n        asynchronously.\n\n        GrBackendTexture created from pixmap is uploaded to match SkSurface created with\n        dstColorSpace. SkColorSpace of SkImage is determined by pixmap.colorSpace().\n\n        SkImage is returned referring to GPU back-end if context is not nullptr,\n        format of data is recognized and supported, and if context supports moving\n        resources between contexts. Otherwise, pixmap pixel data is copied and SkImage\n        as returned in raster format if possible; nullptr may be returned.\n        Recognized GPU formats vary by platform and GPU back-end.\n\n        @param context                GPU context\n        @param pixmap                 SkImageInfo, pixel address, and row bytes\n        @param buildMips              create SkImage as Mip_Map if true\n        @param dstColorSpace          range of colors of matching SkSurface on GPU\n        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary\n        @return                       created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeCrossContextFromPixmap(GrContext* context, const SkPixmap& pixmap,\n                                                     bool buildMips, SkColorSpace* dstColorSpace,\n                                                     bool limitToMaxTextureSize = false);\n\n    /** Creates SkImage from backendTexture associated with context. backendTexture and\n        returned SkImage are managed internally, and are released when no longer needed.\n\n        SkImage is returned if format of backendTexture is recognized and supported.\n        Recognized formats vary by GPU back-end.\n\n        @param context         GPU context\n        @param backendTexture  texture residing on GPU\n        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorType       one of:\n                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                               kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param alphaType       one of:\n                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                               kUnpremul_SkAlphaType\n        @param colorSpace      range of colors; may be nullptr\n        @return                created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext* context,\n                                                 const GrBackendTexture& backendTexture,\n                                                 GrSurfaceOrigin surfaceOrigin,\n                                                 SkColorType colorType,\n                                                 SkAlphaType alphaType = kPremul_SkAlphaType,\n                                                 sk_sp<SkColorSpace> colorSpace = nullptr);\n\n    /** Creates SkImage from copy of yuvTextures, an array of textures on GPU.\n        yuvTextures contain pixels for YUV planes of SkImage. Returned SkImage has the dimensions\n        yuvTextures[0]. yuvColorSpace describes how YUV colors convert to RGB colors.\n\n        @param context        GPU context\n        @param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,\n                              kRec709_SkYUVColorSpace\n        @param yuvTextures    array of YUV textures on GPU\n        @param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorSpace     range of colors; may be nullptr\n        @return               created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,\n                                                  const GrBackendTexture yuvTextures[3],\n                                                  GrSurfaceOrigin surfaceOrigin,\n                                                  sk_sp<SkColorSpace> colorSpace = nullptr);\n\n    /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.\n        nv12Textures[0] contains pixels for YUV_Component_Y plane.\n        nv12Textures[1] contains pixels for YUV_Component_U plane,\n        followed by pixels for YUV_Component_V plane.\n        Returned SkImage has the dimensions nv12Textures[2].\n        yuvColorSpace describes how YUV colors convert to RGB colors.\n\n        @param context        GPU context\n        @param yuvColorSpace  one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,\n                              kRec709_SkYUVColorSpace\n        @param nv12Textures   array of YUV textures on GPU\n        @param surfaceOrigin  one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorSpace     range of colors; may be nullptr\n        @return               created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext* context,\n                                                   SkYUVColorSpace yuvColorSpace,\n                                                   const GrBackendTexture nv12Textures[2],\n                                                   GrSurfaceOrigin surfaceOrigin,\n                                                   sk_sp<SkColorSpace> colorSpace = nullptr);\n\n    enum class BitDepth {\n        kU8,  //!< uses 8-bit unsigned int per color component\n        kF16, //!< uses 16-bit float per color component\n    };\n\n    /** Creates SkImage from picture. Returned SkImage width and height are set by dimensions.\n        SkImage draws picture with matrix and paint, set to bitDepth and colorSpace.\n\n        If matrix is nullptr, draws with identity SkMatrix. If paint is nullptr, draws\n        with default SkPaint. colorSpace may be nullptr.\n\n        @param picture     stream of drawing commands\n        @param dimensions  width and height\n        @param matrix      SkMatrix to rotate, scale, translate, and so on; may be nullptr\n        @param paint       SkPaint to apply transparency, filtering, and so on; may be nullptr\n        @param bitDepth    8-bit integer or 16-bit float: per component\n        @param colorSpace  range of colors; may be nullptr\n        @return            created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,\n                                          const SkMatrix* matrix, const SkPaint* paint,\n                                          BitDepth bitDepth,\n                                          sk_sp<SkColorSpace> colorSpace);\n\n#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26\n    /** (see skbug.com/7447)\n        Creates SkImage from Android hardware buffer.\n        Returned SkImage takes a reference on the buffer.\n\n        Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.\n\n        @param hardwareBuffer  AHardwareBuffer Android hardware buffer\n        @param alphaType       one of:\n                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                               kUnpremul_SkAlphaType\n        @param colorSpace      range of colors; may be nullptr\n        @return                created SkImage, or nullptr\n    */\n    static sk_sp<SkImage> MakeFromAHardwareBuffer(AHardwareBuffer* hardwareBuffer,\n                                                 SkAlphaType alphaType = kPremul_SkAlphaType,\n                                                 sk_sp<SkColorSpace> colorSpace = nullptr);\n#endif\n\n    /** Returns pixel count in each row.\n\n        @return  pixel width in SkImage\n    */\n    int width() const { return fWidth; }\n\n    /** Returns pixel row count.\n\n        @return  pixel height in SkImage\n    */\n    int height() const { return fHeight; }\n\n    /** Returns SkISize { width(), height() }.\n\n        @return  integral size of width() and height()\n    */\n    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }\n\n    /** Returns SkIRect { 0, 0, width(), height() }.\n\n        @return  integral rectangle from origin to width() and height()\n    */\n    SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }\n\n    /** Returns value unique to image. SkImage contents cannot change after SkImage is\n        created. Any operation to create a new SkImage will receive generate a new\n        unique number.\n\n        @return  unique identifier\n    */\n    uint32_t uniqueID() const { return fUniqueID; }\n\n    /** Returns SkAlphaType, one of:\n        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n        kUnpremul_SkAlphaType.\n\n        SkAlphaType returned was a parameter to an SkImage constructor,\n        or was parsed from encoded data.\n\n        @return  SkAlphaType in SkImage\n    */\n    SkAlphaType alphaType() const;\n\n    /** Returns SkColorType if known; otherwise, returns kUnknown_SkColorType.\n\n        @return  SkColorType of SkImage\n    */\n    SkColorType colorType() const;\n\n    /** Returns SkColorSpace, the range of colors, associated with SkImage.  The\n        reference count of SkColorSpace is unchanged. The returned SkColorSpace is\n        immutable.\n\n        SkColorSpace returned was passed to an SkImage constructor,\n        or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage\n        is drawn, depending on the capabilities of the SkSurface receiving the drawing.\n\n        @return  SkColorSpace in SkImage, or nullptr\n    */\n    SkColorSpace* colorSpace() const;\n\n    /** Returns a smart pointer to SkColorSpace, the range of colors, associated with\n        SkImage.  The smart pointer tracks the number of objects sharing this\n        SkColorSpace reference so the memory is released when the owners destruct.\n\n        The returned SkColorSpace is immutable.\n\n        SkColorSpace returned was passed to an SkImage constructor,\n        or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage\n        is drawn, depending on the capabilities of the SkSurface receiving the drawing.\n\n        @return  SkColorSpace in SkImage, or nullptr, wrapped in a smart pointer\n    */\n    sk_sp<SkColorSpace> refColorSpace() const;\n\n    /** Returns true if SkImage pixels represent transparency only. If true, each pixel\n        is packed in 8 bits as defined by kAlpha_8_SkColorType.\n\n        @return  true if pixels represent a transparency mask\n    */\n    bool isAlphaOnly() const;\n\n    /** Returns true if pixels ignore their alpha value and are treated as fully opaque.\n\n        @return  true if SkAlphaType is kOpaque_SkAlphaType\n    */\n    bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }\n\n    /** Creates SkShader from SkImage. SkShader dimensions are taken from SkImage. SkShader uses\n        SkShader::TileMode rules to fill drawn area outside SkImage. localMatrix permits\n        transforming SkImage before SkCanvas matrix is applied.\n\n        @param tileMode1    tiling in x, one of: SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode,\n                            SkShader::kMirror_TileMode\n        @param tileMode2    tiling in y, one of: SkShader::kClamp_TileMode, SkShader::kRepeat_TileMode,\n                            SkShader::kMirror_TileMode\n        @param localMatrix  SkImage transformation, or nullptr\n        @return             SkShader containing SkImage\n    */\n    sk_sp<SkShader> makeShader(SkShader::TileMode tileMode1, SkShader::TileMode tileMode2,\n                               const SkMatrix* localMatrix = nullptr) const;\n\n    /** Creates SkShader from SkImage. SkShader dimensions are taken from SkImage. SkShader uses\n        SkShader::kClamp_TileMode to fill drawn area outside SkImage. localMatrix permits\n        transforming SkImage before SkCanvas matrix is applied.\n\n        @param localMatrix  SkImage transformation, or nullptr\n        @return             SkShader containing SkImage\n    */\n    sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const {\n        return this->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, localMatrix);\n    }\n\n    /** Copies SkImage pixel address, row bytes, and SkImageInfo to pixmap, if address\n        is available, and returns true. If pixel address is not available, return\n        false and leave pixmap unchanged.\n\n        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored\n        @return        true if SkImage has direct access to pixels\n    */\n    bool peekPixels(SkPixmap* pixmap) const;\n\n    /** Deprecated.\n    */\n    GrTexture* getTexture() const;\n\n    /** Returns true the contents of SkImage was created on or uploaded to GPU memory,\n        and is available as a GPU texture.\n\n        @return  true if SkImage is a GPU texture\n    */\n    bool isTextureBacked() const;\n\n    /** Returns true if SkImage can be drawn on either raster surface or GPU surface.\n        If context is nullptr, tests if SkImage draws on raster surface;\n        otherwise, tests if SkImage draws on GPU surface associated with context.\n\n        SkImage backed by GPU texture may become invalid if associated GrContext is\n        invalid. lazy image may be invalid and may not draw to raster surface or\n        GPU surface or both.\n\n        @param context  GPU context\n        @return         true if SkImage can be drawn\n    */\n    bool isValid(GrContext* context) const;\n\n    /** Retrieves the back-end texture. If SkImage has no back-end texture, an invalid\n        object is returned. Call GrBackendTexture::isValid to determine if the result\n        is valid.\n\n        If flushPendingGrContextIO is true, completes deferred I/O operations.\n\n        If origin in not nullptr, copies location of content drawn into SkImage.\n\n        @param flushPendingGrContextIO  flag to flush outstanding requests\n        @param origin                   storage for one of: kTopLeft_GrSurfaceOrigin,\n                                        kBottomLeft_GrSurfaceOrigin; or nullptr\n        @return                         back-end API texture handle; invalid on failure\n    */\n    GrBackendTexture getBackendTexture(bool flushPendingGrContextIO,\n                                       GrSurfaceOrigin* origin = nullptr) const;\n\n    /** \\enum SkImage::CachingHint\n        CachingHint selects whether Skia may internally cache SkBitmap generated by\n        decoding SkImage, or by copying SkImage from GPU to CPU. The default behavior\n        allows caching SkBitmap.\n\n        Choose kDisallow_CachingHint if SkImage pixels are to be used only once, or\n        if SkImage pixels reside in a cache outside of Skia, or to reduce memory pressure.\n\n        Choosing kAllow_CachingHint does not ensure that pixels will be cached.\n        SkImage pixels may not be cached if memory requirements are too large or\n        pixels are not accessible.\n    */\n    enum CachingHint {\n        kAllow_CachingHint,    //!< allows internally caching decoded and copied pixels\n        kDisallow_CachingHint, //!< disallows internally caching decoded and copied pixels\n    };\n\n    /** Copies SkRect of pixels from SkImage to dstPixels. Copy starts at offset (srcX, srcY),\n        and does not exceed SkImage (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of\n        destination. dstRowBytes specifics the gap from one destination row to the next.\n        Returns true if pixels are copied. Returns false if:\n        - dstInfo.addr() equals nullptr\n        - dstRowBytes is less than dstInfo.minRowBytes()\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkImage SkColorType is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkImage SkAlphaType is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkImage SkColorSpace is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().\n\n        If cachingHint is kAllow_CachingHint, pixels may be retained locally.\n        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @param cachingHint  one of: kAllow_CachingHint, kDisallow_CachingHint\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;\n\n    /** Copies a SkRect of pixels from SkImage to dst. Copy starts at (srcX, srcY), and\n        does not exceed SkImage (width(), height()).\n\n        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,\n        and row bytes of destination. dst.rowBytes() specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if:\n        - dst pixel storage equals nullptr\n        - dst.rowBytes is less than SkImageInfo::minRowBytes\n        - SkPixelRef is nullptr\n\n        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.\n        If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.\n        If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must\n        match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative.\n        Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().\n\n        If cachingHint is kAllow_CachingHint, pixels may be retained locally.\n        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.\n\n        @param dst          destination SkPixmap: SkImageInfo, pixels, row bytes\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @param cachingHint  one of: kAllow_CachingHint, kDisallow_CachingHint\n        @return             true if pixels are copied to dst\n    */\n    bool readPixels(const SkPixmap& dst, int srcX, int srcY,\n                    CachingHint cachingHint = kAllow_CachingHint) const;\n\n    /** Copies SkImage to dst, scaling pixels to fit dst.width() and dst.height(), and\n        converting pixels to match dst.colorType() and dst.alphaType(). Returns true if\n        pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is\n        less than dst SkImageInfo::minRowBytes.\n\n        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.\n        If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.\n        If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must\n        match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        Scales the image, with filterQuality, to match dst.width() and dst.height().\n        filterQuality kNone_SkFilterQuality is fastest, typically implemented with\n        nearest neighbor filter. kLow_SkFilterQuality is typically implemented with\n        bilerp filter. kMedium_SkFilterQuality is typically implemented with\n        bilerp filter, and Filter_Quality_MipMap when size is reduced.\n        kHigh_SkFilterQuality is slowest, typically implemented with Filter_Quality_BiCubic.\n\n        If cachingHint is kAllow_CachingHint, pixels may be retained locally.\n        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.\n\n        @param dst            destination SkPixmap: SkImageInfo, pixels, row bytes\n        @param filterQuality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,\n                              kMedium_SkFilterQuality, kHigh_SkFilterQuality\n        @param cachingHint    one of: kAllow_CachingHint, kDisallow_CachingHint\n        @return               true if pixels are scaled to fit dst\n    */\n    bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality,\n                     CachingHint cachingHint = kAllow_CachingHint) const;\n\n    /** Encodes SkImage pixels, returning result as SkData.\n\n        Returns nullptr if encoding fails, or if encodedImageFormat is not supported.\n\n        SkImage encoding in a format requires both building with one or more of:\n        SK_HAS_JPEG_LIBRARY, SK_HAS_PNG_LIBRARY, SK_HAS_WEBP_LIBRARY; and platform support\n        for the encoded format.\n\n        If SK_BUILD_FOR_MAC or SK_BUILD_FOR_IOS is defined, encodedImageFormat can\n        additionally be one of: SkEncodedImageFormat::kICO, SkEncodedImageFormat::kBMP,\n        SkEncodedImageFormat::kGIF.\n\n        quality is a platform and format specific metric trading off size and encoding\n        error. When used, quality equaling 100 encodes with the least error. quality may\n        be ignored by the encoder.\n\n        @param encodedImageFormat  one of: SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kPNG,\n                                   SkEncodedImageFormat::kWEBP\n        @param quality             encoder specific metric with 100 equaling best\n        @return                    encoded SkImage, or nullptr\n    */\n    sk_sp<SkData> encodeToData(SkEncodedImageFormat encodedImageFormat, int quality) const;\n\n    /** Encodes SkImage pixels, returning result as SkData. Returns existing encoded data\n        if present; otherwise, SkImage is encoded with SkEncodedImageFormat::kPNG. Skia\n        must be built with SK_HAS_PNG_LIBRARY to encode SkImage.\n\n        Returns nullptr if existing encoded data is missing or invalid, and\n        encoding fails.\n\n        @return  encoded SkImage, or nullptr\n    */\n    sk_sp<SkData> encodeToData() const;\n\n    /** Returns encoded SkImage pixels as SkData, if SkImage was created from supported\n        encoded stream format. Platform support for formats vary and may require building\n        with one or more of: SK_HAS_JPEG_LIBRARY, SK_HAS_PNG_LIBRARY, SK_HAS_WEBP_LIBRARY.\n\n        Returns nullptr if SkImage contents are not encoded.\n\n        @return  encoded SkImage, or nullptr\n    */\n    sk_sp<SkData> refEncodedData() const;\n\n    /** Appends SkImage description to string, including unique ID, width, height, and\n        whether the image is opaque.\n\n        @param string  storage for description; existing content is preserved\n        @return        string appended with SkImage description\n    */\n    const char* toString(SkString* string) const;\n\n    /** Returns subset of SkImage. subset must be fully contained by SkImage dimensions().\n        The implementation may share pixels, or may copy them.\n\n        Returns nullptr if subset is empty, or subset is not contained by bounds, or\n        pixels in SkImage could not be read or copied.\n\n        @param subset  bounds of returned SkImage\n        @return        partial or full SkImage, or nullptr\n    */\n    sk_sp<SkImage> makeSubset(const SkIRect& subset) const;\n\n    /** Returns SkImage backed by GPU texture associated with context. Returned SkImage is\n        compatible with SkSurface created with dstColorSpace. Returns original\n        SkImage if context and dstColorSpace match.\n\n        Returns nullptr if context is nullptr, or if SkImage was created with another\n        GrContext.\n\n        @param context        GPU context\n        @param dstColorSpace  range of colors of matching SkSurface on GPU\n        @return               created SkImage, or nullptr\n    */\n    sk_sp<SkImage> makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace) const;\n\n    /** Returns raster image or lazy image. Copies SkImage backed by GPU texture into\n        CPU memory if needed. Returns original SkImage if decoded in raster bitmap,\n        or if encoded in a stream.\n\n        Returns nullptr if backed by GPU texture and copy fails.\n\n        @return  raster image, lazy image, or nullptr\n    */\n    sk_sp<SkImage> makeNonTextureImage() const;\n\n    /** Returns raster image. Copies SkImage backed by GPU texture into CPU memory,\n        or decodes SkImage from lazy image. Returns original SkImage if decoded in\n        raster bitmap.\n\n        Returns nullptr if copy, decode, or pixel read fails.\n\n        @return  raster image, or nullptr\n    */\n    sk_sp<SkImage> makeRasterImage() const;\n\n    /** Creates filtered SkImage. filter processes original SkImage, potentially changing\n        color, position, and size. subset is the bounds of original SkImage processed\n        by filter. clipBounds is the expected bounds of the filtered SkImage. outSubset\n        is required storage for the actual bounds of the filtered SkImage. offset is\n        required storage for translation of returned SkImage.\n\n        Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset\n        and offset are undefined.\n\n        Useful for animation of SkImageFilter that varies size from frame to frame.\n        Returned SkImage is created larger than required by filter so that GPU texture\n        can be reused with different sized effects. outSubset describes the valid bounds\n        of GPU texture returned. offset translates the returned SkImage to keep subsequent\n        animation frames aligned with respect to each other.\n\n        @param filter      how SkImage is sampled when transformed\n        @param subset      bounds of SkImage processed by filter\n        @param clipBounds  expected bounds of filtered SkImage\n        @param outSubset   storage for returned SkImage bounds\n        @param offset      storage for returned SkImage translation\n        @return            filtered SkImage, or nullptr\n    */\n    sk_sp<SkImage> makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,\n                                  const SkIRect& clipBounds, SkIRect* outSubset,\n                                  SkIPoint* offset) const;\n\n    typedef std::function<void(GrBackendTexture)> BackendTextureReleaseProc;\n\n    /** Creates a GrBackendTexture from the provided SkImage. Returns true and\n        stores result in backendTexture and backendTextureReleaseProc if\n        texture is created; otherwise, returns false and leaves\n        backendTexture and backendTextureReleaseProc unmodified.\n\n        Call backendTextureReleaseProc after deleting backendTexture.\n        backendTextureReleaseProc cleans up auxiliary data related to returned\n        backendTexture. The caller must delete returned backendTexture after use.\n\n        If SkImage is both texture backed and singly referenced, image is returned in\n        backendTexture without conversion or making a copy. SkImage is singly referenced\n        if its was transferred solely using std::move().\n\n        If SkImage is not texture backed, returns texture with SkImage contents.\n\n        @param context                    GPU context\n        @param image                      SkImage used for texture\n        @param backendTexture             storage for back-end texture\n        @param backendTextureReleaseProc  storage for clean up function\n        @return                           true if back-end texture was created\n    */\n    static bool MakeBackendTextureFromSkImage(GrContext* context,\n                                              sk_sp<SkImage> image,\n                                              GrBackendTexture* backendTexture,\n                                              BackendTextureReleaseProc* backendTextureReleaseProc);\n\n    enum LegacyBitmapMode {\n        kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable\n    };\n\n    /** Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is\n        kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.\n        Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if\n        SkBitmap write did not succeed.\n\n        @param bitmap            storage for legacy SkBitmap\n        @param legacyBitmapMode  to be deprecated\n        @return                  true if SkBitmap was created\n    */\n    bool asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;\n\n    /** Returns true if SkImage is backed by an image-generator or other service that creates\n        and caches its pixels or texture on-demand.\n\n        @return  true if SkImage is created as needed\n    */\n    bool isLazyGenerated() const;\n\n    /** Creates SkImage in target SkColorSpace.\n        Returns nullptr if SkImage could not be created.\n\n        Returns original SkImage if it is in target SkColorSpace.\n        Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.\n        If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.\n\n        SkTransferFunctionBehavior is to be deprecated.\n\n        Set premulBehavior to SkTransferFunctionBehavior::kRespect to convert SkImage\n        pixels to a linear space, before converting to destination SkColorType\n        and SkColorSpace.\n\n        Set premulBehavior to SkTransferFunctionBehavior::kIgnore to treat SkImage\n        pixels as linear, when converting to destination SkColorType\n        and SkColorSpace, ignoring pixel encoding.\n\n        @param target          SkColorSpace describing color range of returned SkImage\n        @param premulBehavior  one of: SkTransferFunctionBehavior::kRespect,\n                               SkTransferFunctionBehavior::kIgnore\n        @return                created SkImage in target SkColorSpace\n    */\n    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target,\n                                  SkTransferFunctionBehavior premulBehavior) const;\n\nprivate:\n    SkImage(int width, int height, uint32_t uniqueID);\n    friend class SkImage_Base;\n\n    const int       fWidth;\n    const int       fHeight;\n    const uint32_t  fUniqueID;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkImageEncoder.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageEncoder_DEFINED\n#define SkImageEncoder_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkData.h\"\n#include \"SkEncodedImageFormat.h\"\n#include \"SkStream.h\"\n\n/**\n * Encode SkPixmap in the given binary image format.\n *\n * @param  dst     results are written to this stream.\n * @param  src     source pixels.\n * @param  format  image format, not all formats are supported.\n * @param  quality range from 0-100, this is supported by jpeg and webp.\n *                 higher values correspond to improved visual quality, but less compression.\n *\n * @return false iff input is bad or format is unsupported.\n *\n * Will always return false if Skia is compiled without image\n * encoders.\n *\n * Note that webp encodes will use webp lossy compression.\n *\n * For examples of encoding an image to a file or to a block of memory,\n * see tools/sk_tool_utils.h.\n */\nSK_API bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,\n                          SkEncodedImageFormat format, int quality);\n\n/**\n * The following helper function wraps SkEncodeImage().\n */\ninline bool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFormat f, int q) {\n    SkPixmap pixmap;\n    return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);\n}\n\n/**\n * Encode SkPixmap in the given binary image format.\n *\n * @param  src     source pixels.\n * @param  format  image format, not all formats are supported.\n * @param  quality range from 0-100, this is supported by jpeg and webp.\n *                 higher values correspond to improved visual quality, but less compression.\n *\n * @return encoded data or nullptr if input is bad or format is unsupported.\n *\n * Will always return nullptr if Skia is compiled without image\n * encoders.\n *\n * Note that webp encodes will use webp lossy compression.\n */\nSK_API sk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality);\n\n/**\n *  Helper that extracts the pixmap from the bitmap, and then calls SkEncodePixmap()\n */\nSK_API sk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality);\n\n#endif  // SkImageEncoder_DEFINED\n"
  },
  {
    "path": "include/core/SkImageFilter.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageFilter_DEFINED\n#define SkImageFilter_DEFINED\n\n#include \"../private/SkTArray.h\"\n#include \"../private/SkTemplates.h\"\n#include \"../private/SkMutex.h\"\n#include \"SkColorSpace.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkFlattenable.h\"\n#include \"SkMatrix.h\"\n#include \"SkRect.h\"\n\nclass GrContext;\nclass GrFragmentProcessor;\nclass SkColorFilter;\nclass SkColorSpaceXformer;\nstruct SkIPoint;\nclass SkSpecialImage;\nclass SkImageFilterCache;\nstruct SkImageFilterCacheKey;\n\n/**\n *  Base class for image filters. If one is installed in the paint, then\n *  all drawing occurs as usual, but it is as if the drawing happened into an\n *  offscreen (before the xfermode is applied). This offscreen bitmap will\n *  then be handed to the imagefilter, who in turn creates a new bitmap which\n *  is what will finally be drawn to the device (using the original xfermode).\n */\nclass SK_API SkImageFilter : public SkFlattenable {\npublic:\n    // Extra information about the output of a filter DAG. For now, this is just the color space\n    // (of the original requesting device). This is used when constructing intermediate rendering\n    // surfaces, so that we ensure we land in a surface that's similar/compatible to the final\n    // consumer of the DAG's output.\n    class OutputProperties {\n    public:\n        explicit OutputProperties(SkColorSpace* colorSpace) : fColorSpace(colorSpace) {}\n\n        SkColorSpace* colorSpace() const { return fColorSpace; }\n\n    private:\n        // This will be a pointer to the device's color space, and our lifetime is bounded by\n        // the device, so we can store a bare pointer.\n        SkColorSpace* fColorSpace;\n    };\n\n    class Context {\n    public:\n        Context(const SkMatrix& ctm, const SkIRect& clipBounds, SkImageFilterCache* cache,\n                const OutputProperties& outputProperties)\n            : fCTM(ctm)\n            , fClipBounds(clipBounds)\n            , fCache(cache)\n            , fOutputProperties(outputProperties)\n        {}\n\n        const SkMatrix& ctm() const { return fCTM; }\n        const SkIRect& clipBounds() const { return fClipBounds; }\n        SkImageFilterCache* cache() const { return fCache; }\n        const OutputProperties& outputProperties() const { return fOutputProperties; }\n\n        /**\n         *  Since a context can be build directly, its constructor has no chance to\n         *  \"return null\" if it's given invalid or unsupported inputs. Call this to\n         *  know of the the context can be used.\n         *\n         *  The SkImageFilterCache Key, for example, requires a finite ctm (no infinities\n         *  or NaN), so that test is part of isValid.\n         */\n        bool isValid() const { return fCTM.isFinite(); }\n\n    private:\n        SkMatrix               fCTM;\n        SkIRect                fClipBounds;\n        SkImageFilterCache*    fCache;\n        OutputProperties       fOutputProperties;\n    };\n\n    class CropRect {\n    public:\n        enum CropEdge {\n            kHasLeft_CropEdge   = 0x01,\n            kHasTop_CropEdge    = 0x02,\n            kHasWidth_CropEdge  = 0x04,\n            kHasHeight_CropEdge = 0x08,\n            kHasAll_CropEdge    = 0x0F,\n        };\n        CropRect() {}\n        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)\n            : fRect(rect), fFlags(flags) {}\n        uint32_t flags() const { return fFlags; }\n        const SkRect& rect() const { return fRect; }\n        void toString(SkString* str) const;\n\n        /**\n         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not\n         *  set, then the corresponding edge from imageBounds will be used. If \"embiggen\"\n         *  is true, the crop rect is allowed to enlarge the size of the rect, otherwise\n         *  it may only reduce the rect. Filters that can affect transparent black should\n         *  pass \"true\", while all other filters should pass \"false\".\n         *\n         *  Note: imageBounds is in \"device\" space, as the output cropped rectangle will be,\n         *  so the matrix is ignored for those. It is only applied the croprect's bounds.\n         */\n        void applyTo(const SkIRect& imageBounds, const SkMatrix& matrix, bool embiggen,\n                     SkIRect* cropped) const;\n\n    private:\n        SkRect fRect;\n        uint32_t fFlags;\n    };\n\n    enum TileUsage {\n        kPossible_TileUsage,    //!< the created device may be drawn tiled\n        kNever_TileUsage,       //!< the created device will never be drawn tiled\n    };\n\n    /**\n     *  Request a new filtered image to be created from the src image.\n     *\n     *  The context contains the environment in which the filter is occurring.\n     *  It includes the clip bounds, CTM and cache.\n     *\n     *  Offset is the amount to translate the resulting image relative to the\n     *  src when it is drawn. This is an out-param.\n     *\n     *  If the result image cannot be created, or the result would be\n     *  transparent black, return null, in which case the offset parameter\n     *  should be ignored by the caller.\n     *\n     *  TODO: Right now the imagefilters sometimes return empty result bitmaps/\n     *        specialimages. That doesn't seem quite right.\n     */\n    sk_sp<SkSpecialImage> filterImage(SkSpecialImage* src, const Context& context,\n                                      SkIPoint* offset) const;\n\n    enum MapDirection {\n        kForward_MapDirection,\n        kReverse_MapDirection,\n    };\n    /**\n     * Map a device-space rect recursively forward or backward through the\n     * filter DAG. kForward_MapDirection is used to determine which pixels of\n     * the destination canvas a source image rect would touch after filtering.\n     * kReverse_MapDirection is used to determine which rect of the source\n     * image would be required to fill the given rect (typically, clip bounds).\n     * Used for clipping and temp-buffer allocations, so the result need not\n     * be exact, but should never be smaller than the real answer. The default\n     * implementation recursively unions all input bounds, or returns the\n     * source rect if no inputs.\n     *\n     * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward\n     * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting\n     * answer may be incorrect.\n     */\n    SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,\n                         MapDirection, const SkIRect* inputRect = nullptr) const;\n\n#if SK_SUPPORT_GPU\n    static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,\n                                            std::unique_ptr<GrFragmentProcessor> fp,\n                                            const SkIRect& bounds,\n                                            const OutputProperties& outputProperties);\n#endif\n\n    /**\n     *  Returns whether this image filter is a color filter and puts the color filter into the\n     *  \"filterPtr\" parameter if it can. Does nothing otherwise.\n     *  If this returns false, then the filterPtr is unchanged.\n     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler\n     *  (i.e. it may not be set to NULL).\n     */\n    bool isColorFilterNode(SkColorFilter** filterPtr) const {\n        return this->onIsColorFilterNode(filterPtr);\n    }\n\n    // DEPRECATED : use isColorFilterNode() instead\n    bool asColorFilter(SkColorFilter** filterPtr) const {\n        return this->isColorFilterNode(filterPtr);\n    }\n\n    void removeKey(const SkImageFilterCacheKey& key) const;\n\n    /**\n     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely\n     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the\n     *  same way.\n     */\n    bool asAColorFilter(SkColorFilter** filterPtr) const;\n\n    /**\n     *  Returns the number of inputs this filter will accept (some inputs can\n     *  be NULL).\n     */\n    int countInputs() const { return fInputs.count(); }\n\n    /**\n     *  Returns the input filter at a given index, or NULL if no input is\n     *  connected.  The indices used are filter-specific.\n     */\n    SkImageFilter* getInput(int i) const {\n        SkASSERT(i < fInputs.count());\n        return fInputs[i].get();\n    }\n\n    /**\n     *  Returns whether any edges of the crop rect have been set. The crop\n     *  rect is set at construction time, and determines which pixels from the\n     *  input image will be processed, and which pixels in the output image will be allowed.\n     *  The size of the crop rect should be\n     *  used as the size of the destination image. The origin of this rect\n     *  should be used to offset access to the input images, and should also\n     *  be added to the \"offset\" parameter in onFilterImage.\n     */\n    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }\n\n    CropRect getCropRect() const { return fCropRect; }\n\n    // Default impl returns union of all input bounds.\n    virtual SkRect computeFastBounds(const SkRect& bounds) const;\n\n    // Can this filter DAG compute the resulting bounds of an object-space rectangle?\n    bool canComputeFastBounds() const;\n\n    /**\n     *  If this filter can be represented by another filter + a localMatrix, return that filter,\n     *  else return null.\n     */\n    sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix& matrix) const;\n\n    /**\n     *  ImageFilters can natively handle scaling and translate components in the CTM. Only some of\n     *  them can handle affine (or more complex) matrices. This call returns true iff the filter\n     *  and all of its (non-null) inputs can handle these more complex matrices.\n     */\n    bool canHandleComplexCTM() const;\n\n    /**\n     * Return an imagefilter which transforms its input by the given matrix.\n     */\n    static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,\n                                                 SkFilterQuality quality,\n                                                 sk_sp<SkImageFilter> input);\n\n    virtual void toString(SkString* str) const = 0;\n\n    static void InitializeFlattenables();\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkImageFilter_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkImageFilter_Type;\n    }\n\n    static sk_sp<SkImageFilter> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkImageFilter>(static_cast<SkImageFilter*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkImageFilter_Type, data, size, procs).release()));\n    }\n\nprotected:\n    class Common {\n    public:\n        /**\n         *  Attempt to unflatten the cropRect and the expected number of input filters.\n         *  If any number of input filters is valid, pass -1.\n         *  If this fails (i.e. corrupt buffer or contents) then return false and common will\n         *  be left uninitialized.\n         *  If this returns true, then inputCount() is the number of found input filters, each\n         *  of which may be NULL or a valid imagefilter.\n         */\n        bool unflatten(SkReadBuffer&, int expectedInputs);\n\n        const CropRect& cropRect() const { return fCropRect; }\n        int             inputCount() const { return fInputs.count(); }\n        sk_sp<SkImageFilter>* inputs() { return fInputs.begin(); }\n\n        sk_sp<SkImageFilter> getInput(int index) { return fInputs[index]; }\n\n    private:\n        CropRect fCropRect;\n        // most filters accept at most 2 input-filters\n        SkSTArray<2, sk_sp<SkImageFilter>, true> fInputs;\n    };\n\n    SkImageFilter(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);\n\n    ~SkImageFilter() override;\n\n    /**\n     *  Constructs a new SkImageFilter read from an SkReadBuffer object.\n     *\n     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.\n     *                       -1 can be used if the filter accepts any number of inputs.\n     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.\n     */\n    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);\n\n    void flatten(SkWriteBuffer&) const override;\n\n    const CropRect* getCropRectIfSet() const {\n        return this->cropRectIsSet() ? &fCropRect : nullptr;\n    }\n\n    /**\n     *  This is the virtual which should be overridden by the derived class\n     *  to perform image filtering.\n     *\n     *  src is the original primitive bitmap. If the filter has a connected\n     *  input, it should recurse on that input and use that in place of src.\n     *\n     *  The matrix is the current matrix on the canvas.\n     *\n     *  Offset is the amount to translate the resulting image relative to the\n     *  src when it is drawn. This is an out-param.\n     *\n     *  If the result image cannot be created (either because of error or if, say, the result\n     *  is entirely clipped out), this should return nullptr.\n     *  Callers that affect transparent black should explicitly handle nullptr\n     *  results and press on. In the error case this behavior will produce a better result\n     *  than nothing and is necessary for the clipped out case.\n     *  If the return value is nullptr then offset should be ignored.\n     */\n    virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&,\n                                                SkIPoint* offset) const = 0;\n\n    /**\n     * This function recurses into its inputs with the given rect (first\n     * argument), calls filterBounds() with the given map direction on each,\n     * and returns the union of those results. If a derived class has special\n     * recursion requirements (e.g., it has an input which does not participate\n     * in bounds computation), it can be overridden here.\n     * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward\n     * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting\n     * answer may be incorrect.\n     *\n     * Note that this function is *not* responsible for mapping the rect for\n     * this node's filter bounds requirements (i.e., calling\n     * onFilterNodeBounds()); that is handled by filterBounds().\n     */\n    virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,\n                                   MapDirection, const SkIRect* inputRect) const;\n\n    /**\n     * Performs a forwards or reverse mapping of the given rect to accommodate\n     * this filter's margin requirements. kForward_MapDirection is used to\n     * determine the destination pixels which would be touched by filtering\n     * the given source rect (e.g., given source bitmap bounds,\n     * determine the optimal bounds of the filtered offscreen bitmap).\n     * kReverse_MapDirection is used to determine which pixels of the\n     * input(s) would be required to fill the given destination rect\n     * (e.g., clip bounds). NOTE: these operations may not be the\n     * inverse of the other. For example, blurring expands the given rect\n     * in both forward and reverse directions. Unlike\n     * onFilterBounds(), this function is non-recursive.\n     * In kReverse mode, 'inputRect' will be the device space bounds of the input pixels. In\n     * kForward mode, 'inputRect' should always be null. If 'inputRect' is null in kReverse mode\n     * the resulting answer may be incorrect.\n     */\n    virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                                       MapDirection, const SkIRect* inputRect) const;\n\n    // Helper function which invokes filter processing on the input at the\n    // specified \"index\". If the input is null, it returns \"src\" and leaves\n    // \"offset\" untouched. If the input is non-null, it\n    // calls filterImage() on that input, and returns the result.\n    sk_sp<SkSpecialImage> filterInput(int index,\n                                      SkSpecialImage* src,\n                                      const Context&,\n                                      SkIPoint* offset) const;\n\n    /**\n     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a\n     *  colorfilter w/o CropRect constraints.\n     */\n    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {\n        return false;\n    }\n\n    /**\n     *  Override this to describe the behavior of your subclass - as a leaf node. The caller will\n     *  take care of calling your inputs (and return false if any of them could not handle it).\n     */\n    virtual bool onCanHandleComplexCTM() const { return false; }\n\n    /** Given a \"srcBounds\" rect, computes destination bounds for this filter.\n     *  \"dstBounds\" are computed by transforming the crop rect by the context's\n     *  CTM, applying it to the initial bounds, and intersecting the result with\n     *  the context's clip bounds.  \"srcBounds\" (if non-null) are computed by\n     *  intersecting the initial bounds with \"dstBounds\", to ensure that we never\n     *  sample outside of the crop rect (this restriction may be relaxed in the\n     *  future).\n     */\n    bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;\n\n    /** A variant of the above call which takes the original source bitmap and\n     *  source offset. If the resulting crop rect is not entirely contained by\n     *  the source bitmap's bounds, it creates a new bitmap in \"result\" and\n     *  pads the edges with transparent black. In that case, the srcOffset is\n     *  modified to be the same as the bounds, since no further adjustment is\n     *  needed by the caller. This version should only be used by filters\n     *  which are not capable of processing a smaller source bitmap into a\n     *  larger destination.\n     */\n    sk_sp<SkSpecialImage> applyCropRectAndPad(const Context&, SkSpecialImage* src,\n                                              SkIPoint* srcOffset, SkIRect* bounds) const;\n\n    /**\n     *  Creates a modified Context for use when recursing up the image filter DAG.\n     *  The clip bounds are adjusted to accommodate any margins that this\n     *  filter requires by calling this node's\n     *  onFilterNodeBounds(..., kReverse_MapDirection).\n     */\n    Context mapContext(const Context& ctx) const;\n\n#if SK_SUPPORT_GPU\n    /**\n     *  Returns a version of the passed-in image (possibly the original), that is in a colorspace\n     *  with the same gamut as the one from the OutputProperties. This allows filters that do many\n     *  texture samples to guarantee that any color space conversion has happened before running.\n     */\n    static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src, const OutputProperties&);\n#endif\n\n    /**\n     *  Returns an image filter transformed into a new color space via the |xformer|.\n     */\n    sk_sp<SkImageFilter> makeColorSpace(SkColorSpaceXformer* xformer) const {\n        return this->onMakeColorSpace(xformer);\n    }\n    virtual sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const = 0;\n\n    sk_sp<SkImageFilter> refMe() const {\n        return sk_ref_sp(const_cast<SkImageFilter*>(this));\n    }\n\n    // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample\n    // will wrap around to the other side) we must preserve the far side of the src along that\n    // axis (e.g., if we will sample beyond the left edge of the src, the right side must be\n    // preserved for the repeat sampling to work).\n    static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,\n                                             const SkIVector& filterOffset,\n                                             const SkISize& filterSize,\n                                             const SkIRect& originalSrcBounds);\n\nprivate:\n    // For makeColorSpace().\n    friend class SkColorSpaceXformer;\n\n    friend class SkGraphics;\n\n    static void PurgeCache();\n\n    void init(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);\n\n    bool usesSrcInput() const { return fUsesSrcInput; }\n    virtual bool affectsTransparentBlack() const { return false; }\n\n    SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;\n\n    bool fUsesSrcInput;\n    CropRect fCropRect;\n    uint32_t fUniqueID; // Globally unique\n\n    typedef SkFlattenable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkImageGenerator.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageGenerator_DEFINED\n#define SkImageGenerator_DEFINED\n\n#include \"SkBitmap.h\"\n#include \"SkColor.h\"\n#include \"SkImage.h\"\n#include \"SkImageInfo.h\"\n#include \"SkYUVSizeInfo.h\"\n\nclass GrContext;\nclass GrContextThreadSafeProxy;\nclass GrTextureProxy;\nclass GrSamplerState;\nclass SkBitmap;\nclass SkData;\nclass SkMatrix;\nclass SkPaint;\nclass SkPicture;\n\nclass SK_API SkImageGenerator : public SkNoncopyable {\npublic:\n    /**\n     *  The PixelRef which takes ownership of this SkImageGenerator\n     *  will call the image generator's destructor.\n     */\n    virtual ~SkImageGenerator() { }\n\n    uint32_t uniqueID() const { return fUniqueID; }\n\n    /**\n     *  Return a ref to the encoded (i.e. compressed) representation\n     *  of this data.\n     *\n     *  If non-NULL is returned, the caller is responsible for calling\n     *  unref() on the data when it is finished.\n     */\n    sk_sp<SkData> refEncodedData() {\n        return this->onRefEncodedData();\n    }\n\n    /**\n     *  Return the ImageInfo associated with this generator.\n     */\n    const SkImageInfo& getInfo() const { return fInfo; }\n\n    /**\n     *  Can this generator be used to produce images that will be drawable to the specified context\n     *  (or to CPU, if context is nullptr)?\n     */\n    bool isValid(GrContext* context) const {\n        return this->onIsValid(context);\n    }\n\n    /**\n     *  Decode into the given pixels, a block of memory of size at\n     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *\n     *  bytesPerPixel)\n     *\n     *  Repeated calls to this function should give the same results,\n     *  allowing the PixelRef to be immutable.\n     *\n     *  @param info A description of the format\n     *         expected by the caller.  This can simply be identical\n     *         to the info returned by getInfo().\n     *\n     *         This contract also allows the caller to specify\n     *         different output-configs, which the implementation can\n     *         decide to support or not.\n     *\n     *         A size that does not match getInfo() implies a request\n     *         to scale. If the generator cannot perform this scale,\n     *         it will return false.\n     *\n     *         kIndex_8_SkColorType is not supported.\n     *\n     *  @return true on success.\n     */\n    struct Options {\n        Options()\n            : fBehavior(SkTransferFunctionBehavior::kIgnore)\n        {}\n\n        SkTransferFunctionBehavior fBehavior;\n    };\n    bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options* options);\n\n    /**\n     *  Simplified version of getPixels() that uses the default Options.\n     */\n    bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);\n\n    /**\n     *  If decoding to YUV is supported, this returns true.  Otherwise, this\n     *  returns false and does not modify any of the parameters.\n     *\n     *  @param sizeInfo   Output parameter indicating the sizes and required\n     *                    allocation widths of the Y, U, and V planes.\n     *  @param colorSpace Output parameter.\n     */\n    bool queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const;\n\n    /**\n     *  Returns true on success and false on failure.\n     *  This always attempts to perform a full decode.  If the client only\n     *  wants size, it should call queryYUV8().\n     *\n     *  @param sizeInfo   Needs to exactly match the values returned by the\n     *                    query, except the WidthBytes may be larger than the\n     *                    recommendation (but not smaller).\n     *  @param planes     Memory for each of the Y, U, and V planes.\n     */\n    bool getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]);\n\n#if SK_SUPPORT_GPU\n    /**\n     *  If the generator can natively/efficiently return its pixels as a GPU image (backed by a\n     *  texture) this will return that image. If not, this will return NULL.\n     *\n     *  This routine also supports retrieving only a subset of the pixels. That subset is specified\n     *  by the following rectangle:\n     *\n     *      subset = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height())\n     *\n     *  If subset is not contained inside the generator's bounds, this returns false.\n     *\n     *      whole = SkIRect::MakeWH(getInfo().width(), getInfo().height())\n     *      if (!whole.contains(subset)) {\n     *          return false;\n     *      }\n     *\n     *  Regarding the GrContext parameter:\n     *\n     *  It must be non-NULL. The generator should only succeed if:\n     *  - its internal context is the same\n     *  - it can somehow convert its texture into one that is valid for the provided context.\n     *\n     *  If the willNeedMipMaps flag is true, the generator should try to create a TextureProxy that\n     *  at least has the mip levels allocated and the base layer filled in. If this is not possible,\n     *  the generator is allowed to return a non mipped proxy, but this will have some additional\n     *  overhead in later allocating mips and copying of the base layer.\n     */\n    sk_sp<GrTextureProxy> generateTexture(GrContext*, const SkImageInfo& info,\n                                          const SkIPoint& origin,\n                                          SkTransferFunctionBehavior behavior,\n                                          bool willNeedMipMaps);\n#endif\n\n    /**\n     *  If the default image decoder system can interpret the specified (encoded) data, then\n     *  this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way\n     *  the caller is still responsible for managing their ownership of the data.\n     */\n    static std::unique_ptr<SkImageGenerator> MakeFromEncoded(sk_sp<SkData>);\n\n    /** Return a new image generator backed by the specified picture.  If the size is empty or\n     *  the picture is NULL, this returns NULL.\n     *  The optional matrix and paint arguments are passed to drawPicture() at rasterization\n     *  time.\n     */\n    static std::unique_ptr<SkImageGenerator> MakeFromPicture(const SkISize&, sk_sp<SkPicture>,\n                                                             const SkMatrix*, const SkPaint*,\n                                                             SkImage::BitDepth,\n                                                             sk_sp<SkColorSpace>);\n\nprotected:\n    static constexpr int kNeedNewImageUniqueID = 0;\n\n    SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);\n\n    virtual sk_sp<SkData> onRefEncodedData() { return nullptr; }\n    virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }\n    virtual bool onIsValid(GrContext*) const { return true; }\n    virtual bool onQueryYUV8(SkYUVSizeInfo*, SkYUVColorSpace*) const { return false; }\n    virtual bool onGetYUV8Planes(const SkYUVSizeInfo&, void*[3] /*planes*/) { return false; }\n\n#if SK_SUPPORT_GPU\n    enum class TexGenType {\n        kNone,           //image generator does not implement onGenerateTexture\n        kCheap,          //onGenerateTexture is implemented and it is fast (does not render offscreen)\n        kExpensive,      //onGenerateTexture is implemented and it is relatively slow\n    };\n\n    virtual TexGenType onCanGenerateTexture() const { return TexGenType::kNone; }\n    virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,\n                                                    SkTransferFunctionBehavior,\n                                                    bool willNeedMipMaps);  // returns nullptr\n#endif\n\nprivate:\n    const SkImageInfo fInfo;\n    const uint32_t fUniqueID;\n\n    friend class SkImage_Lazy;\n\n    // This is our default impl, which may be different on different platforms.\n    // It is called from NewFromEncoded() after it has checked for any runtime factory.\n    // The SkData will never be NULL, as that will have been checked by NewFromEncoded.\n    static std::unique_ptr<SkImageGenerator> MakeFromEncodedImpl(sk_sp<SkData>);\n};\n\n#endif  // SkImageGenerator_DEFINED\n"
  },
  {
    "path": "include/core/SkImageInfo.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageInfo_DEFINED\n#define SkImageInfo_DEFINED\n\n#include \"SkColorSpace.h\"\n#include \"SkMath.h\"\n#include \"SkRect.h\"\n#include \"SkSize.h\"\n#include \"../private/SkTFitsIn.h\"\n\nclass SkReadBuffer;\nclass SkWriteBuffer;\n\n/** \\enum SkImageInfo::SkAlphaType\n    Describes how to interpret the alpha component of a pixel. A pixel may\n    be opaque, or alpha, describing multiple levels of transparency.\n\n    In simple blending, alpha weights the draw color and the destination\n    color to create a new color. If alpha describes a weight from zero to one:\n\n    new color = draw color * alpha + destination color * (1 - alpha)\n\n    In practice alpha is encoded in two or more bits, where 1.0 equals all bits set.\n\n    RGB may have alpha included in each component value; the stored\n    value is the original RGB multiplied by alpha. Premultiplied color\n    components improve performance.\n*/\nenum SkAlphaType {\n    kUnknown_SkAlphaType,                          //!< uninitialized\n    kOpaque_SkAlphaType,                           //!< pixel is opaque\n    kPremul_SkAlphaType,                           //!< pixel components are premultiplied by alpha\n    kUnpremul_SkAlphaType,                         //!< pixel components are independent of alpha\n    kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value\n};\n\n/** Returns true if SkAlphaType equals kOpaque_SkAlphaType. kOpaque_SkAlphaType is a\n    hint that the SkColorType is opaque, or that all alpha values are set to\n    their 1.0 equivalent. If SkAlphaType is kOpaque_SkAlphaType, and SkColorType is not\n    opaque, then the result of drawing any pixel with a alpha value less than\n    1.0 is undefined.\n\n    @param at  one of:\n               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n               kUnpremul_SkAlphaType\n    @return    true if at equals kOpaque_SkAlphaType\n*/\nstatic inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {\n    return kOpaque_SkAlphaType == at;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n/** Temporary macro that allows us to add new color types without breaking Chrome compile. */\n#define SK_EXTENDED_COLOR_TYPES\n\n/** \\enum SkImageInfo::SkColorType\n    Describes how pixel bits encode color. A pixel may be an alpha mask, a\n    grayscale, RGB, or ARGB.\n\n    kN32_SkColorType selects the native 32-bit ARGB format. On Little_Endian\n    processors, pixels containing 8-bit ARGB components pack into 32-bit\n    kBGRA_8888_SkColorType. On Big_Endian processors, pixels pack into 32-bit\n    kRGBA_8888_SkColorType.\n*/\nenum SkColorType {\n    kUnknown_SkColorType,      //!< uninitialized\n    kAlpha_8_SkColorType,      //!< pixel with alpha in 8-bit byte\n    kRGB_565_SkColorType,      //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word\n    kARGB_4444_SkColorType,    //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word\n    kRGBA_8888_SkColorType,    //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word\n    kRGB_888x_SkColorType,     //!< pixel with 8 bits each for red, green, blue; in 32-bit word\n    kBGRA_8888_SkColorType,    //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word\n    kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word\n    kRGB_101010x_SkColorType,  //!< pixel with 10 bits each for red, green, blue; in 32-bit word\n    kGray_8_SkColorType,       //!< pixel with grayscale level in 8-bit byte\n    kRGBA_F16_SkColorType,   //!< pixel with half floats for red, green, blue, alpha; in 64-bit word\n    kLastEnum_SkColorType     = kRGBA_F16_SkColorType,//!< last valid value\n\n#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)\n    kN32_SkColorType          = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding\n\n#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)\n    kN32_SkColorType          = kRGBA_8888_SkColorType,//!< native ARGB 32-bit encoding\n\n#else\n    #error \"SK_*32_SHIFT values must correspond to BGRA or RGBA byte order\"\n#endif\n};\n\n/** Returns the number of bytes required to store a pixel, including unused padding.\n    Returns zero if ct is kUnknown_SkColorType or invalid.\n\n    @param ct  one of:\n               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n               kGray_8_SkColorType, kRGBA_F16_SkColorType\n    @return    bytes per pixel\n*/\nSK_API int SkColorTypeBytesPerPixel(SkColorType ct);\n\n/** Returns true if SkColorType always decodes alpha to 1.0, making the pixel\n    fully opaque. If true, SkColorType does not reserve bits to encode alpha.\n\n    @param ct  one of:\n               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n               kGray_8_SkColorType, kRGBA_F16_SkColorType\n    @return    true if alpha is always set to 1.0\n*/\nSK_API bool SkColorTypeIsAlwaysOpaque(SkColorType ct);\n\n/** Returns true if canonical can be set to a valid SkAlphaType for colorType. If\n    there is more than one valid canonical SkAlphaType, set to alphaType, if valid.\n    If true is returned and canonical is not nullptr, store valid SkAlphaType.\n\n    Returns false only if alphaType is kUnknown_SkAlphaType, color type is not\n    kUnknown_SkColorType, and SkColorType is not always opaque. If false is returned,\n    canonical is ignored.\n\n    For kUnknown_SkColorType: set canonical to kUnknown_SkAlphaType and return true.\n    For kAlpha_8_SkColorType: set canonical to kPremul_SkAlphaType or\n    kOpaque_SkAlphaType and return true if alphaType is not kUnknown_SkAlphaType.\n    For kRGB_565_SkColorType, kRGB_888x_SkColorType, kRGB_101010x_SkColorType, and\n    kGray_8_SkColorType: set canonical to kOpaque_SkAlphaType and return true.\n    For kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,\n    kRGBA_1010102_SkColorType, and kRGBA_F16_SkColorType: set canonical to alphaType\n    and return true if alphaType is not kUnknown_SkAlphaType.\n\n    @param colorType  one of:\n                      kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                      kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                      kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                      kGray_8_SkColorType, kRGBA_F16_SkColorType\n    @param alphaType  one of:\n                      kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                      kUnpremul_SkAlphaType\n    @param canonical  storage for SkAlphaType\n    @return           true if valid SkAlphaType can be associated with colorType\n*/\nSK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,\n                                         SkAlphaType* canonical = nullptr);\n\n/** \\enum SkImageInfo::SkYUVColorSpace\n    Describes color range of YUV pixels. The color mapping from YUV to RGB varies\n    depending on the source. YUV pixels may be generated by JPEG images, standard\n    video streams, or high definition video streams. Each has its own mapping from\n    YUV and RGB.\n\n    JPEG YUV values encode the full range of 0 to 255 for all three components.\n    Video YUV values range from 16 to 235 for all three components. Details of\n    encoding and conversion to RGB are described in YCbCr color space.\n*/\nenum SkYUVColorSpace {\n    kJPEG_SkYUVColorSpace,                               //!< describes full range\n    kRec601_SkYUVColorSpace,                             //!< describes SDTV range\n    kRec709_SkYUVColorSpace,                             //!< describes HDTV range\n    kLastEnum_SkYUVColorSpace = kRec709_SkYUVColorSpace, //!< last valid value\n};\n\n/** \\struct SkImageInfo\n    Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface\n    can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and\n    SkPixmap, but not from SkImage and SkSurface. For example, SkImage and SkSurface\n    implementations may defer pixel depth, so may not completely specify SkImageInfo.\n\n    SkImageInfo contains dimensions, the pixel integral width and height. It encodes\n    how pixel bits describe alpha, transparency; color components red, blue,\n    and green; and SkColorSpace, the range and linearity of colors.\n*/\nstruct SK_API SkImageInfo {\npublic:\n\n    /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,\n        a width and height of zero, and no SkColorSpace.\n\n        @return  empty SkImageInfo\n    */\n    SkImageInfo()\n        : fColorSpace(nullptr)\n        , fWidth(0)\n        , fHeight(0)\n        , fColorType(kUnknown_SkColorType)\n        , fAlphaType(kUnknown_SkAlphaType)\n    {}\n\n    /** Creates SkImageInfo from integral dimensions width and height, SkColorType ct,\n        SkAlphaType at, and optionally SkColorSpace cs.\n\n        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace\n        defaults to sRGB, mapping into SkSurface SkColorSpace.\n\n        Parameters are not validated to see if their values are legal, or that the\n        combination is supported.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @param ct      one of:\n                       kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                       kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                       kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                       kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param at      one of:\n                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                       kUnpremul_SkAlphaType\n        @param cs      range of colors; may be nullptr\n        @return        created SkImageInfo\n    */\n    static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,\n                            sk_sp<SkColorSpace> cs = nullptr) {\n        return SkImageInfo(width, height, ct, at, std::move(cs));\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,\n        SkAlphaType at, and optionally SkColorSpace cs. kN32_SkColorType will equal either\n        kBGRA_8888_SkColorType or kRGBA_8888_SkColorType, whichever is optimal.\n\n        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace\n        defaults to sRGB, mapping into SkSurface SkColorSpace.\n\n        Parameters are not validated to see if their values are legal, or that the\n        combination is supported.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @param at      one of:\n                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                       kUnpremul_SkAlphaType\n        @param cs      range of colors; may be nullptr\n        @return        created SkImageInfo\n    */\n    static SkImageInfo MakeN32(int width, int height, SkAlphaType at,\n                               sk_sp<SkColorSpace> cs = nullptr) {\n        return Make(width, height, kN32_SkColorType, at, cs);\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,\n        SkAlphaType at, with sRGB SkColorSpace.\n\n        Parameters are not validated to see if their values are legal, or that the\n        combination is supported.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @param at      one of:\n                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                       kUnpremul_SkAlphaType\n        @return        created SkImageInfo\n    */\n    static SkImageInfo MakeS32(int width, int height, SkAlphaType at);\n\n    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,\n        kPremul_SkAlphaType, with optional SkColorSpace.\n\n        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace\n        defaults to sRGB, mapping into SkSurface SkColorSpace.\n\n        Parameters are not validated to see if their values are legal, or that the\n        combination is supported.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @param cs      range of colors; may be nullptr\n        @return        created SkImageInfo\n    */\n    static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) {\n        return Make(width, height, kN32_SkColorType, kPremul_SkAlphaType, cs);\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,\n        kPremul_SkAlphaType, with SkColorSpace set to nullptr.\n\n        If SkImageInfo is part of drawing source: SkColorSpace defaults to sRGB, mapping\n        into SkSurface SkColorSpace.\n\n        Parameters are not validated to see if their values are legal, or that the\n        combination is supported.\n\n        @param size  width and height, each must be zero or greater\n        @return      created SkImageInfo\n    */\n    static SkImageInfo MakeN32Premul(const SkISize& size) {\n        return MakeN32Premul(size.width(), size.height());\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height, kAlpha_8_SkColorType,\n        kPremul_SkAlphaType, with SkColorSpace set to nullptr.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @return        created SkImageInfo\n    */\n    static SkImageInfo MakeA8(int width, int height) {\n        return Make(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height, kUnknown_SkColorType,\n        kUnknown_SkAlphaType, with SkColorSpace set to nullptr.\n\n        Returned SkImageInfo as part of source does not draw, and as part of destination\n        can not be drawn to.\n\n        @param width   pixel column count; must be zero or greater\n        @param height  pixel row count; must be zero or greater\n        @return        created SkImageInfo\n    */\n    static SkImageInfo MakeUnknown(int width, int height) {\n        return Make(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr);\n    }\n\n    /** Creates SkImageInfo from integral dimensions width and height set to zero,\n        kUnknown_SkColorType, kUnknown_SkAlphaType, with SkColorSpace set to nullptr.\n\n        Returned SkImageInfo as part of source does not draw, and as part of destination\n        can not be drawn to.\n\n        @return  created SkImageInfo\n    */\n    static SkImageInfo MakeUnknown() {\n        return MakeUnknown(0, 0);\n    }\n\n    /** Returns pixel count in each row.\n\n        @return  pixel width\n    */\n    int width() const { return fWidth; }\n\n    /** Returns pixel row count.\n\n        @return  pixel height\n    */\n    int height() const { return fHeight; }\n\n    /** Returns SkColorType, one of:\n        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n        kGray_8_SkColorType, kRGBA_F16_SkColorType.\n\n        @return  SkColorType\n    */\n    SkColorType colorType() const { return fColorType; }\n\n    /** Returns SkAlphaType, one of:\n        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n        kUnpremul_SkAlphaType.\n\n        @return  SkAlphaType\n    */\n    SkAlphaType alphaType() const { return fAlphaType; }\n\n    /** Returns SkColorSpace, the range of colors. The reference count of\n        SkColorSpace is unchanged. The returned SkColorSpace is immutable.\n\n        @return  SkColorSpace, or nullptr\n    */\n    SkColorSpace* colorSpace() const { return fColorSpace.get(); }\n\n    /** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer\n        tracks the number of objects sharing this SkColorSpace reference so the memory\n        is released when the owners destruct.\n\n        The returned SkColorSpace is immutable.\n\n        @return  SkColorSpace wrapped in a smart pointer\n    */\n    sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }\n\n    /** Returns if SkImageInfo describes an empty area of pixels by checking if either\n        width or height is zero or smaller.\n\n        @return  true if either dimension is zero or smaller\n    */\n    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }\n\n    /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their\n        alpha value is implicitly or explicitly 1.0. If true, and all pixels are\n        not opaque, Skia may draw incorrectly.\n\n        Does not check if SkColorType allows alpha, or if any pixel value has\n        transparency.\n\n        @return  true if SkAlphaType is kOpaque_SkAlphaType\n    */\n    bool isOpaque() const {\n        return SkAlphaTypeIsOpaque(fAlphaType);\n    }\n\n    /** Returns SkISize { width(), height() }.\n\n        @return  integral size of width() and height()\n    */\n    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }\n\n    /** Returns SkIRect { 0, 0, width(), height() }.\n\n        @return  integral rectangle from origin to width() and height()\n    */\n    SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }\n\n    /** Returns true if associated SkColorSpace is not nullptr, and SkColorSpace gamma\n        is approximately the same as sRGB.\n        This includes the\n\n        @return  true if SkColorSpace gamma is approximately the same as sRGB\n    */\n    bool gammaCloseToSRGB() const {\n        return fColorSpace && fColorSpace->gammaCloseToSRGB();\n    }\n\n    /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,\n        with dimensions set to width and height.\n\n        @param newWidth   pixel column count; must be zero or greater\n        @param newHeight  pixel row count; must be zero or greater\n        @return           created SkImageInfo\n    */\n    SkImageInfo makeWH(int newWidth, int newHeight) const {\n        return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace);\n    }\n\n    /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height,\n        with SkAlphaType set to newAlphaType.\n\n        Created SkImageInfo contains newAlphaType even if it is incompatible with\n        SkColorType, in which case SkAlphaType in SkImageInfo is ignored.\n\n        @param newAlphaType  one of:\n                             kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n                             kUnpremul_SkAlphaType\n        @return              created SkImageInfo\n    */\n    SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {\n        return Make(fWidth, fHeight, fColorType, newAlphaType, fColorSpace);\n    }\n\n    /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height,\n        with SkColorType set to newColorType.\n\n        @param newColorType  one of:\n                             kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                             kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                             kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                             kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @return              created SkImageInfo\n    */\n    SkImageInfo makeColorType(SkColorType newColorType) const {\n        return Make(fWidth, fHeight, newColorType, fAlphaType, fColorSpace);\n    }\n\n    /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height,\n        with SkColorSpace set to cs.\n\n        @param cs  range of colors; may be nullptr\n        @return    created SkImageInfo\n    */\n    SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {\n        return Make(fWidth, fHeight, fColorType, fAlphaType, std::move(cs));\n    }\n\n    /** Returns number of bytes per pixel required by SkColorType.\n        Returns zero if colorType( is kUnknown_SkColorType.\n\n        @return  bytes in pixel\n    */\n    int bytesPerPixel() const;\n\n    /** Returns bit shift converting row bytes to row pixels.\n        Returns zero for kUnknown_SkColorType.\n\n        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes\n    */\n    int shiftPerPixel() const;\n\n    /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which\n        specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit\n        in 31 bits.\n\n        @return  width() times bytesPerPixel() as unsigned 64-bit integer\n    */\n    uint64_t minRowBytes64() const {\n        return sk_64_mul(fWidth, this->bytesPerPixel());\n    }\n\n    /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which\n        specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit\n        in 31 bits.\n\n        @return  width() times bytesPerPixel() as signed 32-bit integer\n    */\n    size_t minRowBytes() const {\n        uint64_t minRowBytes = this->minRowBytes64();\n        if (!SkTFitsIn<int32_t>(minRowBytes)) {\n            return 0;\n        }\n        return SkTo<int32_t>(minRowBytes);\n    }\n\n    /** Returns byte offset of pixel from pixel base address.\n\n        Asserts in debug build if x or y is outside of bounds. Does not assert if\n        rowBytes is smaller than minRowBytes(), even though result may be incorrect.\n\n        @param x         column index, zero or greater, and less than width()\n        @param y         row index, zero or greater, and less than height()\n        @param rowBytes  size of pixel row or larger\n        @return          offset within pixel array\n    */\n    size_t computeOffset(int x, int y, size_t rowBytes) const;\n\n    /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,\n        SkAlphaType, and SkColorSpace are equivalent.\n\n        @param other  SkImageInfo to compare\n        @return       true if SkImageInfo equals other\n    */\n    bool operator==(const SkImageInfo& other) const {\n        return fWidth == other.fWidth && fHeight == other.fHeight &&\n               fColorType == other.fColorType && fAlphaType == other.fAlphaType &&\n               SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());\n    }\n\n    /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,\n        SkAlphaType, and SkColorSpace are not equivalent.\n\n        @param other  SkImageInfo to compare\n        @return       true if SkImageInfo is not equal to other\n    */\n    bool operator!=(const SkImageInfo& other) const {\n        return !(*this == other);\n    }\n\n    /** Returns storage required by pixel array, given SkImageInfo dimensions, SkColorType,\n        and rowBytes. rowBytes is assumed to be at least as large as minRowBytes().\n\n        Returns zero if height is zero.\n        Returns SK_MaxSizeT if answer exceeds the range of size_t.\n\n        @param rowBytes  size of pixel row or larger\n        @return          memory required by pixel buffer\n    */\n    size_t computeByteSize(size_t rowBytes) const;\n\n    /** Returns storage required by pixel array, given SkImageInfo dimensions, and\n        SkColorType. Uses minRowBytes() to compute bytes for pixel row.\n\n        Returns zero if height is zero.\n        Returns SK_MaxSizeT if answer exceeds the range of size_t.\n\n        @return  least memory required by pixel buffer\n    */\n    size_t computeMinByteSize() const {\n        return this->computeByteSize(this->minRowBytes());\n    }\n\n    /** Returns true if byteSize equals SK_MaxSizeT. computeByteSize() and\n        computeMinByteSize() return SK_MaxSizeT if size_t can not hold buffer size.\n\n        @param byteSize  result of computeByteSize() or computeMinByteSize()\n        @return          true if computeByteSize() or computeMinByteSize() result exceeds size_t\n    */\n    static bool ByteSizeOverflowed(size_t byteSize) {\n        return SK_MaxSizeT == byteSize;\n    }\n\n    /** Returns true if rowBytes is smaller than width times pixel size.\n\n        @param rowBytes  size of pixel row or larger\n        @return          true if rowBytes is large enough to contain pixel row\n    */\n    bool validRowBytes(size_t rowBytes) const {\n        uint64_t minRB = sk_64_mul(fWidth, this->bytesPerPixel());\n        return rowBytes >= minRB;\n    }\n\n    /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,\n        a width and height of zero, and no SkColorSpace.\n    */\n    void reset() {\n        fColorSpace = nullptr;\n        fWidth = 0;\n        fHeight = 0;\n        fColorType = kUnknown_SkColorType;\n        fAlphaType = kUnknown_SkAlphaType;\n    }\n\n    /** Asserts if internal values are illegal or inconsistent. Only available if\n        SK_DEBUG is defined at compile time.\n    */\n    SkDEBUGCODE(void validate() const;)\n\nprivate:\n    sk_sp<SkColorSpace> fColorSpace;\n    int                 fWidth;\n    int                 fHeight;\n    SkColorType         fColorType;\n    SkAlphaType         fAlphaType;\n\n    SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs)\n        : fColorSpace(std::move(cs))\n        , fWidth(width)\n        , fHeight(height)\n        , fColorType(ct)\n        , fAlphaType(at)\n    {}\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkMallocPixelRef.h",
    "content": "/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMallocPixelRef_DEFINED\n#define SkMallocPixelRef_DEFINED\n\n#include \"SkPixelRef.h\"\n\n/** We explicitly use the same allocator for our pixels that SkMask does,\n    so that we can freely assign memory allocated by one class to the other.\n*/\nclass SK_API SkMallocPixelRef : public SkPixelRef {\npublic:\n    /**\n     *  Return a new SkMallocPixelRef with the provided pixel storage, rowBytes,\n     *  and optional colortable. The caller is responsible for managing the\n     *  lifetime of the pixel storage buffer, as this pixelref will not try\n     *  to delete it.\n     *\n     *  Returns NULL on failure.\n     */\n    static sk_sp<SkPixelRef> MakeDirect(const SkImageInfo&, void* addr, size_t rowBytes);\n\n    /**\n     *  Return a new SkMallocPixelRef, automatically allocating storage for the\n     *  pixels. If rowBytes are 0, an optimal value will be chosen automatically.\n     *  If rowBytes is > 0, then it will be respected, or NULL will be returned\n     *  if rowBytes is invalid for the specified info.\n     *\n     *  This pixelref will ref() the specified colortable (if not NULL).\n     *\n     *  Returns NULL on failure.\n     */\n    static sk_sp<SkPixelRef> MakeAllocate(const SkImageInfo&, size_t rowBytes);\n\n    /**\n     *  Identical to MakeAllocate, except all pixel bytes are zeroed.\n     */\n    static sk_sp<SkPixelRef> MakeZeroed(const SkImageInfo&, size_t rowBytes);\n\n    /**\n     *  Return a new SkMallocPixelRef with the provided pixel storage,\n     *  rowBytes, and optional colortable. On destruction, ReleaseProc\n     *  will be called.\n     *\n     *  If ReleaseProc is NULL, the pixels will never be released. This\n     *  can be useful if the pixels were stack allocated. However, such an\n     *  SkMallocPixelRef must not live beyond its pixels (e.g. by copying\n     *  an SkBitmap pointing to it, or drawing to an SkPicture).\n     *\n     *  Returns NULL on failure.\n     */\n    typedef void (*ReleaseProc)(void* addr, void* context);\n    static sk_sp<SkPixelRef> MakeWithProc(const SkImageInfo& info, size_t rowBytes, void* addr,\n                                          ReleaseProc proc, void* context);\n\n    /**\n     *  Return a new SkMallocPixelRef that will use the provided\n     *  SkData, rowBytes, and optional colortable as pixel storage.\n     *  The SkData will be ref()ed and on destruction of the PielRef,\n     *  the SkData will be unref()ed.\n     *\n     *  Returns NULL on failure.\n     */\n    static sk_sp<SkPixelRef> MakeWithData(const SkImageInfo&, size_t rowBytes, sk_sp<SkData> data);\n\nprotected:\n    ~SkMallocPixelRef() override;\n\nprivate:\n    // Uses alloc to implement NewAllocate or NewZeroed.\n    static sk_sp<SkPixelRef> MakeUsing(void*(*alloc)(size_t),\n                                       const SkImageInfo&,\n                                       size_t rowBytes);\n\n    ReleaseProc fReleaseProc;\n    void*       fReleaseProcContext;\n\n    SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, ReleaseProc proc, void* context);\n\n    typedef SkPixelRef INHERITED;\n};\n\n\n#endif\n"
  },
  {
    "path": "include/core/SkMaskFilter.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMaskFilter_DEFINED\n#define SkMaskFilter_DEFINED\n\n#include \"SkBlurTypes.h\"\n#include \"SkCoverageMode.h\"\n#include \"SkFlattenable.h\"\n#include \"SkScalar.h\"\n\nclass SkMatrix;\nstruct SkRect;\nclass SkString;\n\n/** \\class SkMaskFilter\n\n    SkMaskFilter is the base class for object that perform transformations on\n    the mask before drawing it. An example subclass is Blur.\n*/\nclass SK_API SkMaskFilter : public SkFlattenable {\npublic:\n    /** Create a blur maskfilter.\n     *  @param style     The SkBlurStyle to use\n     *  @param sigma     Standard deviation of the Gaussian blur to apply. Must be > 0.\n     *  @param occluder  The rect for which no pixels need be drawn (b.c. it will be overdrawn\n     *                   with some opaque object. This is just a hint which backends are free to\n     *                   ignore.\n     *  @param respectCTM if true the blur's sigma is modified by the CTM.\n     *  @return The new blur maskfilter\n     */\n    static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma, const SkRect& occluder,\n                                        bool respectCTM = true);\n    static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma,\n                                        bool respectCTM = true);\n\n    /**\n     *  Construct a maskfilter whose effect is to first apply the inner filter and then apply\n     *  the outer filter to the result of the inner's. Returns nullptr on failure.\n     */\n    static sk_sp<SkMaskFilter> MakeCompose(sk_sp<SkMaskFilter> outer, sk_sp<SkMaskFilter> inner);\n\n    /**\n     *  Compose two maskfilters together using a coverage mode. Returns nullptr on failure.\n     */\n    static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB,\n                                           SkCoverageMode mode);\n\n    /**\n     *  Construct a maskfilter with an additional transform.\n     *\n     *  Note: unlike shader local matrices, this transform composes next to the CTM.\n     *\n     *    TotalMatrix = CTM x MaskFilterMatrix x (optional/downstream) ShaderLocalMatrix\n     */\n    sk_sp<SkMaskFilter> makeWithMatrix(const SkMatrix&) const;\n\n    virtual void toString(SkString* str) const = 0;\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkMaskFilter_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkMaskFilter_Type;\n    }\n\n    static sk_sp<SkMaskFilter> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkMaskFilter>(static_cast<SkMaskFilter*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkMaskFilter_Type, data, size, procs).release()));\n    }\n\nprivate:\n    static void InitializeFlattenables();\n    friend class SkFlattenable;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkMath.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkMath_DEFINED\n#define SkMath_DEFINED\n\n#include \"SkTypes.h\"\n\n// 64bit -> 32bit utilities\n\n// Handy util that can be passed two ints, and will automatically promote to\n// 64bits before the multiply, so the caller doesn't have to remember to cast\n// e.g. (int64_t)a * b;\nstatic inline int64_t sk_64_mul(int64_t a, int64_t b) {\n    return a * b;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n *  Computes numer1 * numer2 / denom in full 64 intermediate precision.\n *  It is an error for denom to be 0. There is no special handling if\n *  the result overflows 32bits.\n */\nstatic inline int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom) {\n    SkASSERT(denom);\n\n    int64_t tmp = sk_64_mul(numer1, numer2) / denom;\n    return SkTo<int32_t>(tmp);\n}\n\n/**\n *  Return the integer square root of value, with a bias of bitBias\n */\nint32_t SkSqrtBits(int32_t value, int bitBias);\n\n/** Return the integer square root of n, treated as a SkFixed (16.16)\n */\n#define SkSqrt32(n)         SkSqrtBits(n, 15)\n\n/**\n *  Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches)\n */\nstatic inline int SkClampPos(int value) {\n    return value & ~(value >> 31);\n}\n\n/** Given an integer and a positive (max) integer, return the value\n *  pinned against 0 and max, inclusive.\n *  @param value    The value we want returned pinned between [0...max]\n *  @param max      The positive max value\n *  @return 0 if value < 0, max if value > max, else value\n */\nstatic inline int SkClampMax(int value, int max) {\n    // ensure that max is positive\n    SkASSERT(max >= 0);\n    if (value < 0) {\n        value = 0;\n    }\n    if (value > max) {\n        value = max;\n    }\n    return value;\n}\n\n/**\n *  Returns true if value is a power of 2. Does not explicitly check for\n *  value <= 0.\n */\ntemplate <typename T> constexpr inline bool SkIsPow2(T value) {\n    return (value & (value - 1)) == 0;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n *  Return a*b/((1 << shift) - 1), rounding any fractional bits.\n *  Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8\n */\nstatic inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) {\n    SkASSERT(a <= 32767);\n    SkASSERT(b <= 32767);\n    SkASSERT(shift > 0 && shift <= 8);\n    unsigned prod = a*b + (1 << (shift - 1));\n    return (prod + (prod >> shift)) >> shift;\n}\n\n/**\n *  Return a*b/255, rounding any fractional bits.\n *  Only valid if a and b are unsigned and <= 32767.\n */\nstatic inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {\n    SkASSERT(a <= 32767);\n    SkASSERT(b <= 32767);\n    unsigned prod = a*b + 128;\n    return (prod + (prod >> 8)) >> 8;\n}\n\n/**\n * Stores numer/denom and numer%denom into div and mod respectively.\n */\ntemplate <typename In, typename Out>\ninline void SkTDivMod(In numer, In denom, Out* div, Out* mod) {\n#ifdef SK_CPU_ARM32\n    // If we wrote this as in the else branch, GCC won't fuse the two into one\n    // divmod call, but rather a div call followed by a divmod.  Silly!  This\n    // version is just as fast as calling __aeabi_[u]idivmod manually, but with\n    // prettier code.\n    //\n    // This benches as around 2x faster than the code in the else branch.\n    const In d = numer/denom;\n    *div = static_cast<Out>(d);\n    *mod = static_cast<Out>(numer-d*denom);\n#else\n    // On x86 this will just be a single idiv.\n    *div = static_cast<Out>(numer/denom);\n    *mod = static_cast<Out>(numer%denom);\n#endif\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkMatrix.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkMatrix_DEFINED\n#define SkMatrix_DEFINED\n\n#include \"SkRect.h\"\n\nstruct SkRSXform;\nstruct SkPoint3;\nclass SkString;\n\n/** \\class SkMatrix\n    SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping\n    SkPoint and vectors with translation, scaling, skewing, rotation, and\n    perspective.\n\n    SkMatrix elements are in row major order. SkMatrix does not have a constructor,\n    so it must be explicitly initialized. setIdentity() initializes SkMatrix\n    so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll()\n    initializes all SkMatrix elements with the corresponding mapping.\n\n    SkMatrix includes a hidden variable that classifies the type of matrix to\n    improve performance. SkMatrix is not thread safe unless getType() is called first.\n*/\nSK_BEGIN_REQUIRE_DENSE\nclass SK_API SkMatrix {\npublic:\n\n    /** Sets SkMatrix to scale by (sx, sy). Returned matrix is:\n\n            | sx  0  0 |\n            |  0 sy  0 |\n            |  0  0  1 |\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n        @return    SkMatrix with scale\n    */\n    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {\n        SkMatrix m;\n        m.setScale(sx, sy);\n        return m;\n    }\n\n    /** Sets SkMatrix to scale by (scale, scale). Returned matrix is:\n\n            | scale   0   0 |\n            |   0   scale 0 |\n            |   0     0   1 |\n\n        @param scale  horizontal and vertical scale factor\n        @return       SkMatrix with scale\n    */\n    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {\n        SkMatrix m;\n        m.setScale(scale, scale);\n        return m;\n    }\n\n    /** Sets SkMatrix to translate by (dx, dy). Returned matrix is:\n\n            | 1 0 dx |\n            | 0 1 dy |\n            | 0 0  1 |\n\n        @param dx  horizontal translation\n        @param dy  vertical translation\n        @return    SkMatrix with translation\n    */\n    static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {\n        SkMatrix m;\n        m.setTranslate(dx, dy);\n        return m;\n    }\n\n    /** Sets SkMatrix to:\n\n            | scaleX  skewX transX |\n            |  skewY scaleY transY |\n            |  pers0  pers1  pers2 |\n\n        @param scaleX  horizontal scale factor\n        @param skewX   horizontal skew factor\n        @param transX  horizontal translation\n        @param skewY   vertical skew factor\n        @param scaleY  vertical scale factor\n        @param transY  vertical translation\n        @param pers0   input x perspective factor\n        @param pers1   input y perspective factor\n        @param pers2   perspective scale factor\n        @return        SkMatrix constructed from parameters\n    */\n    static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,\n                                                  SkScalar skewY,  SkScalar scaleY, SkScalar transY,\n                                                  SkScalar pers0, SkScalar pers1, SkScalar pers2) {\n        SkMatrix m;\n        m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);\n        return m;\n    }\n\n    /** \\enum SkMatrix::TypeMask\n        Enum of bit fields for mask returned by getType().\n        Used to identify the complexity of SkMatrix, to optimize performance.\n    */\n    enum TypeMask {\n        kIdentity_Mask    = 0,    //!< identity SkMatrix; all bits clear\n        kTranslate_Mask   = 0x01, //!< translation SkMatrix\n        kScale_Mask       = 0x02, //!< scale SkMatrix\n        kAffine_Mask      = 0x04, //!< skew or rotate SkMatrix\n        kPerspective_Mask = 0x08, //!< perspective SkMatrix\n    };\n\n    /** Returns a bit field describing the transformations the matrix may\n        perform. The bit field is computed conservatively, so it may include\n        false positives. For example, when kPerspective_Mask is set, all\n        other bits are set.\n\n        @return  kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,\n                 kAffine_Mask, kPerspective_Mask\n    */\n    TypeMask getType() const {\n        if (fTypeMask & kUnknown_Mask) {\n            fTypeMask = this->computeTypeMask();\n        }\n        // only return the public masks\n        return (TypeMask)(fTypeMask & 0xF);\n    }\n\n    /** Returns true if SkMatrix is identity.  Identity matrix is:\n\n            | 1 0 0 |\n            | 0 1 0 |\n            | 0 0 1 |\n\n        @return  true if SkMatrix has no effect\n    */\n    bool isIdentity() const {\n        return this->getType() == 0;\n    }\n\n    /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity,\n        contain only scale elements, only translate elements, or both. SkMatrix form is:\n\n            | scale-x    0    translate-x |\n            |    0    scale-y translate-y |\n            |    0       0         1      |\n\n        @return  true if SkMatrix is identity; or scales, translates, or both\n    */\n    bool isScaleTranslate() const {\n        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));\n    }\n\n    /** Returns true if SkMatrix is identity, or translates. SkMatrix form is:\n\n            | 1 0 translate-x |\n            | 0 1 translate-y |\n            | 0 0      1      |\n\n        @return  true if SkMatrix is identity, or translates\n    */\n    bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); }\n\n    /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,\n        or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all\n        cases, SkMatrix may also have translation. SkMatrix form is either:\n\n            | scale-x    0    translate-x |\n            |    0    scale-y translate-y |\n            |    0       0         1      |\n\n        or\n\n            |    0     rotate-x translate-x |\n            | rotate-y    0     translate-y |\n            |    0        0          1      |\n\n        for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.\n\n        Also called preservesAxisAlignment(); use the one that provides better inline\n        documentation.\n\n        @return  true if SkMatrix maps one SkRect into another\n    */\n    bool rectStaysRect() const {\n        if (fTypeMask & kUnknown_Mask) {\n            fTypeMask = this->computeTypeMask();\n        }\n        return (fTypeMask & kRectStaysRect_Mask) != 0;\n    }\n\n    /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,\n        or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all\n        cases, SkMatrix may also have translation. SkMatrix form is either:\n\n            | scale-x    0    translate-x |\n            |    0    scale-y translate-y |\n            |    0       0         1      |\n\n        or\n\n            |    0     rotate-x translate-x |\n            | rotate-y    0     translate-y |\n            |    0        0          1      |\n\n        for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.\n\n        Also called rectStaysRect(); use the one that provides better inline\n        documentation.\n\n        @return  true if SkMatrix maps one SkRect into another\n    */\n    bool preservesAxisAlignment() const { return this->rectStaysRect(); }\n\n    /** Returns true if the matrix contains perspective elements. SkMatrix form is:\n\n            |       --            --              --          |\n            |       --            --              --          |\n            | perspective-x  perspective-y  perspective-scale |\n\n        where perspective-x or perspective-y is non-zero, or perspective-scale is\n        not one. All other elements may have any value.\n\n        @return  true if SkMatrix is in most general form\n    */\n    bool hasPerspective() const {\n        return SkToBool(this->getPerspectiveTypeMaskOnly() &\n                        kPerspective_Mask);\n    }\n\n    /** Returns true if SkMatrix contains only translation, rotation, reflection, and\n        uniform scale.\n        Returns false if SkMatrix contains different scales, skewing, perspective, or\n        degenerate forms that collapse to a line or point.\n\n        Describes that the SkMatrix makes rendering with and without the matrix are\n        visually alike; a transformed circle remains a circle. Mathematically, this is\n        referred to as similarity of a Euclidean_Space, or a similarity transformation.\n\n        Preserves right angles, keeping the arms of the angle equal lengths.\n\n        @param tol  to be deprecated\n        @return     true if SkMatrix only rotates, uniformly scales, translates\n    */\n    bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;\n\n    /** Returns true if SkMatrix contains only translation, rotation, reflection, and\n        scale. Scale may differ along rotated axes.\n        Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse\n        to a line or point.\n\n        Preserves right angles, but not requiring that the arms of the angle\n        retain equal lengths.\n\n        @param tol  to be deprecated\n        @return     true if SkMatrix only rotates, scales, translates\n    */\n    bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;\n\n    /** SkMatrix organizes its values in row order. These members correspond to\n        each value in SkMatrix.\n    */\n    static constexpr int kMScaleX = 0; //!< horizontal scale factor\n    static constexpr int kMSkewX  = 1; //!< horizontal skew factor\n    static constexpr int kMTransX = 2; //!< horizontal translation\n    static constexpr int kMSkewY  = 3; //!< vertical skew factor\n    static constexpr int kMScaleY = 4; //!< vertical scale factor\n    static constexpr int kMTransY = 5; //!< vertical translation\n    static constexpr int kMPersp0 = 6; //!< input x perspective factor\n    static constexpr int kMPersp1 = 7; //!< input y perspective factor\n    static constexpr int kMPersp2 = 8; //!< perspective bias\n\n    /** Affine arrays are in column major order to match the matrix used by\n        PDF and XPS.\n    */\n    static constexpr int kAScaleX = 0; //!< horizontal scale factor\n    static constexpr int kASkewY  = 1; //!< vertical skew factor\n    static constexpr int kASkewX  = 2; //!< horizontal skew factor\n    static constexpr int kAScaleY = 3; //!< vertical scale factor\n    static constexpr int kATransX = 4; //!< horizontal translation\n    static constexpr int kATransY = 5; //!< vertical translation\n\n    /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is\n        defined.\n\n        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,\n                      kMPersp0, kMPersp1, kMPersp2\n        @return       value corresponding to index\n    */\n    SkScalar operator[](int index) const {\n        SkASSERT((unsigned)index < 9);\n        return fMat[index];\n    }\n\n    /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is\n        defined.\n\n        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,\n                      kMPersp0, kMPersp1, kMPersp2\n        @return       value corresponding to index\n    */\n    SkScalar get(int index) const {\n        SkASSERT((unsigned)index < 9);\n        return fMat[index];\n    }\n\n    /** Returns scale factor multiplied by x input, contributing to x output.\n        With mapPoints(), scales SkPoint along the x-axis.\n\n        @return  horizontal scale factor\n    */\n    SkScalar getScaleX() const { return fMat[kMScaleX]; }\n\n    /** Returns scale factor multiplied by y input, contributing to y output.\n        With mapPoints(), scales SkPoint along the y-axis.\n\n        @return  vertical scale factor\n    */\n    SkScalar getScaleY() const { return fMat[kMScaleY]; }\n\n    /** Returns scale factor multiplied by x input, contributing to y output.\n        With mapPoints(), skews SkPoint along the y-axis.\n        Skew x and y together can rotate SkPoint.\n\n        @return  vertical skew factor\n    */\n    SkScalar getSkewY() const { return fMat[kMSkewY]; }\n\n    /** Returns scale factor multiplied by y input, contributing to x output.\n        With mapPoints(), skews SkPoint along the x-axis.\n        Skew x and y together can rotate SkPoint.\n\n        @return  horizontal scale factor\n    */\n    SkScalar getSkewX() const { return fMat[kMSkewX]; }\n\n    /** Returns translation contributing to x output.\n        With mapPoints(), moves SkPoint along the x-axis.\n\n        @return  horizontal translation factor\n    */\n    SkScalar getTranslateX() const { return fMat[kMTransX]; }\n\n    /** Returns translation contributing to y output.\n        With mapPoints(), moves SkPoint along the y-axis.\n\n        @return  vertical translation factor\n    */\n    SkScalar getTranslateY() const { return fMat[kMTransY]; }\n\n    /** Returns factor scaling input x relative to input y.\n\n        @return  input x perspective factor\n    */\n    SkScalar getPerspX() const { return fMat[kMPersp0]; }\n\n    /** Returns factor scaling input y relative to input x.\n\n        @return  input y perspective factor\n    */\n    SkScalar getPerspY() const { return fMat[kMPersp1]; }\n\n    /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is\n        defined. Clears internal cache anticipating that caller will change SkMatrix value.\n\n        Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix\n        value must be followed by dirtyMatrixTypeCache().\n\n        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,\n                      kMPersp0, kMPersp1, kMPersp2\n        @return       writable value corresponding to index\n    */\n    SkScalar& operator[](int index) {\n        SkASSERT((unsigned)index < 9);\n        this->setTypeMask(kUnknown_Mask);\n        return fMat[index];\n    }\n\n    /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is\n        defined. Safer than operator[]; internal cache is always maintained.\n\n        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,\n                      kMPersp0, kMPersp1, kMPersp2\n        @param value  scalar to store in SkMatrix\n    */\n    void set(int index, SkScalar value) {\n        SkASSERT((unsigned)index < 9);\n        fMat[index] = value;\n        this->setTypeMask(kUnknown_Mask);\n    }\n\n    /** Sets horizontal scale factor.\n\n        @param v  horizontal scale factor to store\n    */\n    void setScaleX(SkScalar v) { this->set(kMScaleX, v); }\n\n    /** Sets vertical scale factor.\n\n        @param v  vertical scale factor to store\n    */\n    void setScaleY(SkScalar v) { this->set(kMScaleY, v); }\n\n    /** Sets vertical skew factor.\n\n        @param v  vertical skew factor to store\n    */\n    void setSkewY(SkScalar v) { this->set(kMSkewY, v); }\n\n    /** Sets horizontal skew factor.\n\n        @param v  horizontal skew factor to store\n    */\n    void setSkewX(SkScalar v) { this->set(kMSkewX, v); }\n\n    /** Sets horizontal translation.\n\n        @param v  horizontal translation to store\n    */\n    void setTranslateX(SkScalar v) { this->set(kMTransX, v); }\n\n    /** Sets vertical translation.\n\n        @param v  vertical translation to store\n    */\n    void setTranslateY(SkScalar v) { this->set(kMTransY, v); }\n\n    /** Sets input x perspective factor, which causes mapXY() to vary input x inversely\n        proportional to input y.\n\n        @param v  perspective factor\n    */\n    void setPerspX(SkScalar v) { this->set(kMPersp0, v); }\n\n    /** Sets input y perspective factor, which causes mapXY() to vary input y inversely\n        proportional to input x.\n\n        @param v  perspective factor\n    */\n    void setPerspY(SkScalar v) { this->set(kMPersp1, v); }\n\n    /** Sets all values from parameters. Sets matrix to:\n\n            | scaleX  skewX transX |\n            |  skewY scaleY transY |\n            | persp0 persp1 persp2 |\n\n        @param scaleX  horizontal scale factor to store\n        @param skewX   horizontal skew factor to store\n        @param transX  horizontal translation to store\n        @param skewY   vertical skew factor to store\n        @param scaleY  vertical scale factor to store\n        @param transY  vertical translation to store\n        @param persp0  input x perspective factor to store\n        @param persp1  input y perspective factor to store\n        @param persp2  perspective scale factor to store\n    */\n    void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,\n                SkScalar skewY,  SkScalar scaleY, SkScalar transY,\n                SkScalar persp0, SkScalar persp1, SkScalar persp2) {\n        fMat[kMScaleX] = scaleX;\n        fMat[kMSkewX]  = skewX;\n        fMat[kMTransX] = transX;\n        fMat[kMSkewY]  = skewY;\n        fMat[kMScaleY] = scaleY;\n        fMat[kMTransY] = transY;\n        fMat[kMPersp0] = persp0;\n        fMat[kMPersp1] = persp1;\n        fMat[kMPersp2] = persp2;\n        this->setTypeMask(kUnknown_Mask);\n    }\n\n    /** Copies nine scalar values contained by SkMatrix into buffer, in member value\n        ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,\n        kMPersp0, kMPersp1, kMPersp2.\n\n        @param buffer  storage for nine scalar values\n    */\n    void get9(SkScalar buffer[9]) const {\n        memcpy(buffer, fMat, 9 * sizeof(SkScalar));\n    }\n\n    /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order:\n        kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,\n        kMPersp2.\n\n        Sets matrix to:\n\n            | buffer[0] buffer[1] buffer[2] |\n            | buffer[3] buffer[4] buffer[5] |\n            | buffer[6] buffer[7] buffer[8] |\n\n        In the future, set9 followed by get9 may not return the same values. Since SkMatrix\n        maps non-homogeneous coordinates, scaling all nine values produces an equivalent\n        transformation, possibly improving precision.\n\n        @param buffer  nine scalar values\n    */\n    void set9(const SkScalar buffer[9]);\n\n    /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:\n\n            | 1 0 0 |\n            | 0 1 0 |\n            | 0 0 1 |\n\n        Also called setIdentity(); use the one that provides better inline\n        documentation.\n    */\n    void reset();\n\n    /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:\n\n            | 1 0 0 |\n            | 0 1 0 |\n            | 0 0 1 |\n\n        Also called reset(); use the one that provides better inline\n        documentation.\n    */\n    void setIdentity() { this->reset(); }\n\n    /** Sets SkMatrix to translate by (dx, dy).\n\n        @param dx  horizontal translation\n        @param dy  vertical translation\n    */\n    void setTranslate(SkScalar dx, SkScalar dy);\n\n    /** Sets SkMatrix to translate by (v.fX, v.fY).\n\n        @param v  vector containing horizontal and vertical translation\n    */\n    void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }\n\n    /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py).\n        The pivot point is unchanged when mapped with SkMatrix.\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0).\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n    */\n    void setScale(SkScalar sx, SkScalar sy);\n\n    /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py).\n        The pivot point is unchanged when mapped with SkMatrix.\n\n        Positive degrees rotates clockwise.\n\n        @param degrees  angle of axes relative to upright axes\n        @param px       pivot x\n        @param py       pivot y\n    */\n    void setRotate(SkScalar degrees, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0).\n        Positive degrees rotates clockwise.\n\n        @param degrees  angle of axes relative to upright axes\n    */\n    void setRotate(SkScalar degrees);\n\n    /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py).\n        The pivot point is unchanged when mapped with SkMatrix.\n\n        Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).\n        Vector length specifies scale.\n\n        @param sinValue  rotation vector x component\n        @param cosValue  rotation vector y component\n        @param px        pivot x\n        @param py        pivot y\n    */\n    void setSinCos(SkScalar sinValue, SkScalar cosValue,\n                   SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).\n\n        Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).\n        Vector length specifies scale.\n\n        @param sinValue  rotation vector x component\n        @param cosValue  rotation vector y component\n    */\n    void setSinCos(SkScalar sinValue, SkScalar cosValue);\n\n    /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form.\n\n        Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative\n        to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled\n        by vector, then translated by (rsxForm.fTx, rsxForm.fTy).\n\n        @param rsxForm  compressed SkRSXform matrix\n        @return         reference to SkMatrix\n    */\n    SkMatrix& setRSXform(const SkRSXform& rsxForm);\n\n    /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py).\n        The pivot point is unchanged when mapped with SkMatrix.\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0).\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n    */\n    void setSkew(SkScalar kx, SkScalar ky);\n\n    /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this.\n\n        Given:\n\n                | A B C |      | J K L |\n            a = | D E F |, b = | M N O |\n                | G H I |      | P Q R |\n\n        sets SkMatrix to:\n\n                    | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |\n            a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |\n                    | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |\n\n        @param a  SkMatrix on left side of multiply expression\n        @param b  SkMatrix on right side of multiply expression\n    */\n    void setConcat(const SkMatrix& a, const SkMatrix& b);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy).\n        This can be thought of as moving the point to be mapped before applying SkMatrix.\n\n        Given:\n\n                     | A B C |               | 1 0 dx |\n            Matrix = | D E F |,  T(dx, dy) = | 0 1 dy |\n                     | G H I |               | 0 0  1 |\n\n        sets SkMatrix to:\n\n                                 | A B C | | 1 0 dx |   | A B A*dx+B*dy+C |\n            Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |\n                                 | G H I | | 0 0  1 |   | G H G*dx+H*dy+I |\n\n        @param dx  x translation before applying SkMatrix\n        @param dy  y translation before applying SkMatrix\n    */\n    void preTranslate(SkScalar dx, SkScalar dy);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)\n        about pivot point (px, py).\n        This can be thought of as scaling about a pivot point before applying SkMatrix.\n\n        Given:\n\n                     | A B C |                       | sx  0 dx |\n            Matrix = | D E F |,  S(sx, sy, px, py) = |  0 sy dy |\n                     | G H I |                       |  0  0  1 |\n\n        where\n\n            dx = px - sx * px\n            dy = py - sy * py\n\n        sets SkMatrix to:\n\n                                         | A B C | | sx  0 dx |   | A*sx B*sy A*dx+B*dy+C |\n            Matrix * S(sx, sy, px, py) = | D E F | |  0 sy dy | = | D*sx E*sy D*dx+E*dy+F |\n                                         | G H I | |  0  0  1 |   | G*sx H*sy G*dx+H*dy+I |\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)\n        about pivot point (0, 0).\n        This can be thought of as scaling about the origin before applying SkMatrix.\n\n        Given:\n\n                     | A B C |               | sx  0  0 |\n            Matrix = | D E F |,  S(sx, sy) = |  0 sy  0 |\n                     | G H I |               |  0  0  1 |\n\n        sets SkMatrix to:\n\n                                 | A B C | | sx  0  0 |   | A*sx B*sy C |\n            Matrix * S(sx, sy) = | D E F | |  0 sy  0 | = | D*sx E*sy F |\n                                 | G H I | |  0  0  1 |   | G*sx H*sy I |\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n    */\n    void preScale(SkScalar sx, SkScalar sy);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees\n        about pivot point (px, py).\n        This can be thought of as rotating about a pivot point before applying SkMatrix.\n\n        Positive degrees rotates clockwise.\n\n        Given:\n\n                     | A B C |                        | c -s dx |\n            Matrix = | D E F |,  R(degrees, px, py) = | s  c dy |\n                     | G H I |                        | 0  0  1 |\n\n        where\n\n            c  = cos(degrees)\n            s  = sin(degrees)\n            dx =  s * py + (1 - c) * px\n            dy = -s * px + (1 - c) * py\n\n        sets SkMatrix to:\n\n                                          | A B C | | c -s dx |   | Ac+Bs -As+Bc A*dx+B*dy+C |\n            Matrix * R(degrees, px, py) = | D E F | | s  c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |\n                                          | G H I | | 0  0  1 |   | Gc+Hs -Gs+Hc G*dx+H*dy+I |\n\n        @param degrees  angle of axes relative to upright axes\n        @param px       pivot x\n        @param py       pivot y\n    */\n    void preRotate(SkScalar degrees, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees\n        about pivot point (0, 0).\n        This can be thought of as rotating about the origin before applying SkMatrix.\n\n        Positive degrees rotates clockwise.\n\n        Given:\n\n                     | A B C |                        | c -s 0 |\n            Matrix = | D E F |,  R(degrees, px, py) = | s  c 0 |\n                     | G H I |                        | 0  0 1 |\n\n        where\n\n            c  = cos(degrees)\n            s  = sin(degrees)\n\n        sets SkMatrix to:\n\n                                          | A B C | | c -s 0 |   | Ac+Bs -As+Bc C |\n            Matrix * R(degrees, px, py) = | D E F | | s  c 0 | = | Dc+Es -Ds+Ec F |\n                                          | G H I | | 0  0 1 |   | Gc+Hs -Gs+Hc I |\n\n        @param degrees  angle of axes relative to upright axes\n    */\n    void preRotate(SkScalar degrees);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)\n        about pivot point (px, py).\n        This can be thought of as skewing about a pivot point before applying SkMatrix.\n\n        Given:\n\n                     | A B C |                       |  1 kx dx |\n            Matrix = | D E F |,  K(kx, ky, px, py) = | ky  1 dy |\n                     | G H I |                       |  0  0  1 |\n\n        where\n\n            dx = -kx * py\n            dy = -ky * px\n\n        sets SkMatrix to:\n\n                                         | A B C | |  1 kx dx |   | A+B*ky A*kx+B A*dx+B*dy+C |\n            Matrix * K(kx, ky, px, py) = | D E F | | ky  1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |\n                                         | G H I | |  0  0  1 |   | G+H*ky G*kx+H G*dx+H*dy+I |\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)\n        about pivot point (0, 0).\n        This can be thought of as skewing about the origin before applying SkMatrix.\n\n        Given:\n\n                     | A B C |               |  1 kx 0 |\n            Matrix = | D E F |,  K(kx, ky) = | ky  1 0 |\n                     | G H I |               |  0  0 1 |\n\n        sets SkMatrix to:\n\n                                 | A B C | |  1 kx 0 |   | A+B*ky A*kx+B C |\n            Matrix * K(kx, ky) = | D E F | | ky  1 0 | = | D+E*ky D*kx+E F |\n                                 | G H I | |  0  0 1 |   | G+H*ky G*kx+H I |\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n    */\n    void preSkew(SkScalar kx, SkScalar ky);\n\n    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other.\n        This can be thought of mapping by other before applying SkMatrix.\n\n        Given:\n\n                     | A B C |          | J K L |\n            Matrix = | D E F |, other = | M N O |\n                     | G H I |          | P Q R |\n\n        sets SkMatrix to:\n\n                             | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |\n            Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |\n                             | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |\n\n        @param other  SkMatrix on right side of multiply expression\n    */\n    void preConcat(const SkMatrix& other);\n\n    /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix.\n        This can be thought of as moving the point to be mapped after applying SkMatrix.\n\n        Given:\n\n                     | J K L |               | 1 0 dx |\n            Matrix = | M N O |,  T(dx, dy) = | 0 1 dy |\n                     | P Q R |               | 0 0  1 |\n\n        sets SkMatrix to:\n\n                                 | 1 0 dx | | J K L |   | J+dx*P K+dx*Q L+dx*R |\n            T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |\n                                 | 0 0  1 | | P Q R |   |      P      Q      R |\n\n        @param dx  x translation after applying SkMatrix\n        @param dy  y translation after applying SkMatrix\n    */\n    void postTranslate(SkScalar dx, SkScalar dy);\n\n    /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point\n        (px, py), multiplied by SkMatrix.\n        This can be thought of as scaling about a pivot point after applying SkMatrix.\n\n        Given:\n\n                     | J K L |                       | sx  0 dx |\n            Matrix = | M N O |,  S(sx, sy, px, py) = |  0 sy dy |\n                     | P Q R |                       |  0  0  1 |\n\n        where\n\n            dx = px - sx * px\n            dy = py - sy * py\n\n        sets SkMatrix to:\n\n                                         | sx  0 dx | | J K L |   | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |\n            S(sx, sy, px, py) * Matrix = |  0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |\n                                         |  0  0  1 | | P Q R |   |         P         Q         R |\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point\n        (0, 0), multiplied by SkMatrix.\n        This can be thought of as scaling about the origin after applying SkMatrix.\n\n        Given:\n\n                     | J K L |               | sx  0  0 |\n            Matrix = | M N O |,  S(sx, sy) = |  0 sy  0 |\n                     | P Q R |               |  0  0  1 |\n\n        sets SkMatrix to:\n\n                                 | sx  0  0 | | J K L |   | sx*J sx*K sx*L |\n            S(sx, sy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |\n                                 |  0  0  1 | | P Q R |   |    P    Q    R |\n\n        @param sx  horizontal scale factor\n        @param sy  vertical scale factor\n    */\n    void postScale(SkScalar sx, SkScalar sy);\n\n    /** Sets SkMatrix to SkMatrix constructed from scaling by (1/divx, 1/divy) about pivot point (px, py), multiplied by SkMatrix.\n\n        Returns false if either divx or divy is zero.\n\n        Given:\n\n                     | J K L |                   | sx  0  0 |\n            Matrix = | M N O |,  I(divx, divy) = |  0 sy  0 |\n                     | P Q R |                   |  0  0  1 |\n\n        where\n\n            sx = 1 / divx\n            sy = 1 / divy\n\n        sets SkMatrix to:\n\n                                     | sx  0  0 | | J K L |   | sx*J sx*K sx*L |\n            I(divx, divy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |\n                                     |  0  0  1 | | P Q R |   |    P    Q    R |\n\n        @param divx  integer divisor for inverse scale in x\n        @param divy  integer divisor for inverse scale in y\n        @return      true on successful scale\n    */\n    bool postIDiv(int divx, int divy);\n\n    /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point\n        (px, py), multiplied by SkMatrix.\n        This can be thought of as rotating about a pivot point after applying SkMatrix.\n\n        Positive degrees rotates clockwise.\n\n        Given:\n\n                     | J K L |                        | c -s dx |\n            Matrix = | M N O |,  R(degrees, px, py) = | s  c dy |\n                     | P Q R |                        | 0  0  1 |\n\n        where\n\n            c  = cos(degrees)\n            s  = sin(degrees)\n            dx =  s * py + (1 - c) * px\n            dy = -s * px + (1 - c) * py\n\n        sets SkMatrix to:\n\n                                          |c -s dx| |J K L|   |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|\n            R(degrees, px, py) * Matrix = |s  c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|\n                                          |0  0  1| |P Q R|   |         P          Q          R|\n\n        @param degrees  angle of axes relative to upright axes\n        @param px       pivot x\n        @param py       pivot y\n    */\n    void postRotate(SkScalar degrees, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point\n        (0, 0), multiplied by SkMatrix.\n        This can be thought of as rotating about the origin after applying SkMatrix.\n\n        Positive degrees rotates clockwise.\n\n        Given:\n\n                     | J K L |                        | c -s 0 |\n            Matrix = | M N O |,  R(degrees, px, py) = | s  c 0 |\n                     | P Q R |                        | 0  0 1 |\n\n        where\n\n            c  = cos(degrees)\n            s  = sin(degrees)\n\n        sets SkMatrix to:\n\n                                          | c -s dx | | J K L |   | cJ-sM cK-sN cL-sO |\n            R(degrees, px, py) * Matrix = | s  c dy | | M N O | = | sJ+cM sK+cN sL+cO |\n                                          | 0  0  1 | | P Q R |   |     P     Q     R |\n\n        @param degrees  angle of axes relative to upright axes\n    */\n    void postRotate(SkScalar degrees);\n\n    /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point\n        (px, py), multiplied by SkMatrix.\n        This can be thought of as skewing about a pivot point after applying SkMatrix.\n\n        Given:\n\n                     | J K L |                       |  1 kx dx |\n            Matrix = | M N O |,  K(kx, ky, px, py) = | ky  1 dy |\n                     | P Q R |                       |  0  0  1 |\n\n        where\n\n            dx = -kx * py\n            dy = -ky * px\n\n        sets SkMatrix to:\n\n                                         | 1 kx dx| |J K L|   |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|\n            K(kx, ky, px, py) * Matrix = |ky  1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|\n                                         | 0  0  1| |P Q R|   |          P           Q           R|\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n        @param px  pivot x\n        @param py  pivot y\n    */\n    void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);\n\n    /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point\n        (0, 0), multiplied by SkMatrix.\n        This can be thought of as skewing about the origin after applying SkMatrix.\n\n        Given:\n\n                     | J K L |               |  1 kx 0 |\n            Matrix = | M N O |,  K(kx, ky) = | ky  1 0 |\n                     | P Q R |               |  0  0 1 |\n\n        sets SkMatrix to:\n\n                                 |  1 kx 0 | | J K L |   | J+kx*M K+kx*N L+kx*O |\n            K(kx, ky) * Matrix = | ky  1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |\n                                 |  0  0 1 | | P Q R |   |      P      Q      R |\n\n        @param kx  horizontal skew factor\n        @param ky  vertical skew factor\n    */\n    void postSkew(SkScalar kx, SkScalar ky);\n\n    /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix.\n        This can be thought of mapping by other after applying SkMatrix.\n\n        Given:\n\n                     | J K L |           | A B C |\n            Matrix = | M N O |,  other = | D E F |\n                     | P Q R |           | G H I |\n\n        sets SkMatrix to:\n\n                             | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |\n            other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |\n                             | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |\n\n        @param other  SkMatrix on left side of multiply expression\n    */\n    void postConcat(const SkMatrix& other);\n\n    /** \\enum SkMatrix::ScaleToFit\n        ScaleToFit describes how SkMatrix is constructed to map one SkRect to another.\n        ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling,\n        or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies\n        how SkMatrix maps to the side or center of the destination SkRect.\n    */\n    enum ScaleToFit {\n        kFill_ScaleToFit,   //!< scales in x and y to fill destination SkRect\n        kStart_ScaleToFit,  //!< scales and aligns to left and top\n        kCenter_ScaleToFit, //!< scales and aligns to center\n        kEnd_ScaleToFit,    //!< scales and aligns to right and bottom\n    };\n\n    /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether\n        mapping completely fills dst or preserves the aspect ratio, and how to align\n        src within dst. Returns false if src is empty, and sets SkMatrix to identity.\n        Returns true if dst is empty, and sets SkMatrix to:\n\n            | 0 0 0 |\n            | 0 0 0 |\n            | 0 0 1 |\n\n        @param src  SkRect to map from\n        @param dst  SkRect to map to\n        @param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,\n                    kCenter_ScaleToFit, kEnd_ScaleToFit\n        @return     true if SkMatrix can represent SkRect mapping\n    */\n    bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);\n\n    /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects\n        whether mapping completely fills dst or preserves the aspect ratio, and how to\n        align src within dst. Returns the identity SkMatrix if src is empty. If dst is\n        empty, returns SkMatrix set to:\n\n            | 0 0 0 |\n            | 0 0 0 |\n            | 0 0 1 |\n\n        @param src  SkRect to map from\n        @param dst  SkRect to map to\n        @param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,\n                    kCenter_ScaleToFit, kEnd_ScaleToFit\n        @return     SkMatrix mapping src to dst\n    */\n    static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {\n        SkMatrix m;\n        m.setRectToRect(src, dst, stf);\n        return m;\n    }\n\n    /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less.\n\n        If count is zero, sets SkMatrix to identity and returns true.\n        If count is one, sets SkMatrix to translate and returns true.\n        If count is two or more, sets SkMatrix to map SkPoint if possible; returns false\n        if SkMatrix cannot be constructed. If count is four, SkMatrix may include\n        perspective.\n\n        @param src    SkPoint to map from\n        @param dst    SkPoint to map to\n        @param count  number of SkPoint in src and dst\n        @return       true if SkMatrix was constructed successfully\n    */\n    bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);\n\n    /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted.\n        Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix\n        maps from destination to source. If SkMatrix can not be inverted, inverse is\n        unchanged.\n\n        @param inverse  storage for inverted SkMatrix; may be nullptr\n        @return         true if SkMatrix can be inverted\n    */\n    bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {\n        // Allow the trivial case to be inlined.\n        if (this->isIdentity()) {\n            if (inverse) {\n                inverse->reset();\n            }\n            return true;\n        }\n        return this->invertNonIdentity(inverse);\n    }\n\n    /** Fills affine with identity values in column major order.\n        Sets affine to:\n\n            | 1 0 0 |\n            | 0 1 0 |\n\n        Affine 3x2 matrices in column major order are used by OpenGL and XPS.\n\n        @param affine  storage for 3x2 affine matrix\n    */\n    static void SetAffineIdentity(SkScalar affine[6]);\n\n    /** Fills affine in column major order. Sets affine to:\n\n            | scale-x  skew-x translate-x |\n            | skew-y  scale-y translate-y |\n\n        If SkMatrix contains perspective, returns false and leaves affine unchanged.\n\n        @param affine  storage for 3x2 affine matrix; may be nullptr\n        @return        true if SkMatrix does not contain perspective\n    */\n    bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;\n\n    /** Sets SkMatrix to affine values, passed in column major order. Given affine,\n        column, then row, as:\n\n            | scale-x  skew-x translate-x |\n            |  skew-y scale-y translate-y |\n\n        SkMatrix is set, row, then column, to:\n\n            | scale-x  skew-x translate-x |\n            |  skew-y scale-y translate-y |\n            |       0       0           1 |\n\n        @param affine  3x2 affine matrix\n    */\n    void setAffine(const SkScalar affine[6]);\n\n    /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater\n        length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given:\n\n                     | A B C |        | x |\n            Matrix = | D E F |,  pt = | y |\n                     | G H I |        | 1 |\n\n        where\n\n            for (i = 0; i < count; ++i) {\n                x = src[i].fX\n                y = src[i].fY\n            }\n\n        each dst SkPoint is computed as:\n\n                          |A B C| |x|                               Ax+By+C   Dx+Ey+F\n            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------\n                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I\n\n        src and dst may point to the same storage.\n\n        @param dst    storage for mapped SkPoint\n        @param src    SkPoint to transform\n        @param count  number of SkPoint to transform\n    */\n    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {\n        SkASSERT((dst && src && count > 0) || 0 == count);\n        // no partial overlap\n        SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);\n        this->getMapPtsProc()(*this, dst, src, count);\n    }\n\n    /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying\n        each SkPoint by SkMatrix. Given:\n\n                     | A B C |        | x |\n            Matrix = | D E F |,  pt = | y |\n                     | G H I |        | 1 |\n\n        where\n\n            for (i = 0; i < count; ++i) {\n                x = pts[i].fX\n                y = pts[i].fY\n            }\n\n        each resulting pts SkPoint is computed as:\n\n                          |A B C| |x|                               Ax+By+C   Dx+Ey+F\n            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------\n                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I\n\n        @param pts    storage for mapped SkPoint\n        @param count  number of SkPoint to transform\n    */\n    void mapPoints(SkPoint pts[], int count) const {\n        this->mapPoints(pts, pts, count);\n    }\n\n    /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or\n        greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given:\n\n                     | A B C |         | x |\n            Matrix = | D E F |,  src = | y |\n                     | G H I |         | z |\n\n        each resulting dst SkPoint is computed as:\n\n                           |A B C| |x|\n            Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|\n                           |G H I| |z|\n\n        @param dst    storage for mapped SkPoint3 array\n        @param src    SkPoint3 array to transform\n        @param count  items in SkPoint3 array to transform\n    */\n    void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;\n\n    /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:\n\n                     | A B C |        | x |\n            Matrix = | D E F |,  pt = | y |\n                     | G H I |        | 1 |\n\n        result is computed as:\n\n                          |A B C| |x|                               Ax+By+C   Dx+Ey+F\n            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------\n                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I\n\n        @param x       x-coordinate of SkPoint to map\n        @param y       y-coordinate of SkPoint to map\n        @param result  storage for mapped SkPoint\n    */\n    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {\n        SkASSERT(result);\n        this->getMapXYProc()(*this, x, y, result);\n    }\n\n    /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:\n\n                     | A B C |        | x |\n            Matrix = | D E F |,  pt = | y |\n                     | G H I |        | 1 |\n\n        result is computed as:\n\n                          |A B C| |x|                               Ax+By+C   Dx+Ey+F\n            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------\n                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I\n\n        @param x  x-coordinate of SkPoint to map\n        @param y  y-coordinate of SkPoint to map\n        @return   mapped SkPoint\n    */\n    SkPoint mapXY(SkScalar x, SkScalar y) const {\n        SkPoint result;\n        this->getMapXYProc()(*this, x, y, &result);\n        return result;\n    }\n\n    /** Maps src vector array of length count to vector SkPoint array of equal or greater\n        length. Vectors are mapped by multiplying each vector by SkMatrix, treating\n        SkMatrix translation as zero. Given:\n\n                     | A B 0 |         | x |\n            Matrix = | D E 0 |,  src = | y |\n                     | G H I |         | 1 |\n\n        where\n\n            for (i = 0; i < count; ++i) {\n                x = src[i].fX\n                y = src[i].fY\n            }\n\n        each dst vector is computed as:\n\n                           |A B 0| |x|                            Ax+By     Dx+Ey\n            Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------\n                           |G H I| |1|                           Gx+Hy+I   Gx+Hy+I\n\n        src and dst may point to the same storage.\n\n        @param dst    storage for mapped vectors\n        @param src    vectors to transform\n        @param count  number of vectors to transform\n    */\n    void mapVectors(SkVector dst[], const SkVector src[], int count) const;\n\n    /** Maps vecs vector array of length count in place, multiplying each vector by\n        SkMatrix, treating SkMatrix translation as zero. Given:\n\n                     | A B 0 |         | x |\n            Matrix = | D E 0 |,  vec = | y |\n                     | G H I |         | 1 |\n\n        where\n\n            for (i = 0; i < count; ++i) {\n                x = vecs[i].fX\n                y = vecs[i].fY\n            }\n\n        each result vector is computed as:\n\n                           |A B 0| |x|                            Ax+By     Dx+Ey\n            Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------\n                           |G H I| |1|                           Gx+Hy+I   Gx+Hy+I\n\n        @param vecs   vectors to transform, and storage for mapped vectors\n        @param count  number of vectors to transform\n    */\n    void mapVectors(SkVector vecs[], int count) const {\n        this->mapVectors(vecs, vecs, count);\n    }\n\n    /** Maps vector (x, y) to result. Vector is mapped by multiplying by SkMatrix,\n        treating SkMatrix translation as zero. Given:\n\n                     | A B 0 |         | dx |\n            Matrix = | D E 0 |,  vec = | dy |\n                     | G H I |         |  1 |\n\n        each result vector is computed as:\n\n                       |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy\n        Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------\n                       |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I\n\n        @param dx      x-coordinate of vector to map\n        @param dy      y-coordinate of vector to map\n        @param result  storage for mapped vector\n    */\n    void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {\n        SkVector vec = { dx, dy };\n        this->mapVectors(result, &vec, 1);\n    }\n\n    /** Returns vector (x, y) multiplied by SkMatrix, treating SkMatrix translation as zero.\n        Given:\n\n                     | A B 0 |         | dx |\n            Matrix = | D E 0 |,  vec = | dy |\n                     | G H I |         |  1 |\n\n        each result vector is computed as:\n\n                       |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy\n        Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------\n                       |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I\n\n        @param dx  x-coordinate of vector to map\n        @param dy  y-coordinate of vector to map\n        @return    mapped vector\n    */\n    SkVector mapVector(SkScalar dx, SkScalar dy) const {\n        SkVector vec = { dx, dy };\n        this->mapVectors(&vec, &vec, 1);\n        return vec;\n    }\n\n    /** Sets dst to bounds of src corners mapped by SkMatrix.\n        Returns true if mapped corners are dst corners.\n\n        Returned value is the same as calling rectStaysRect().\n\n        @param dst  storage for bounds of mapped SkPoint\n        @param src  SkRect to map\n        @return     true if dst is equivalent to mapped src\n    */\n    bool mapRect(SkRect* dst, const SkRect& src) const;\n\n    /** Sets rect to bounds of rect corners mapped by SkMatrix.\n        Returns true if mapped corners are computed rect corners.\n\n        Returned value is the same as calling rectStaysRect().\n\n        @param rect  rectangle to map, and storage for bounds of mapped corners\n        @return      true if result is equivalent to mapped src\n    */\n    bool mapRect(SkRect* rect) const {\n        return this->mapRect(rect, *rect);\n    }\n\n    /** Returns bounds of src corners mapped by SkMatrix.\n\n        @param src  rectangle to map\n        @return     mapped bounds\n    */\n    SkRect mapRect(const SkRect& src) const {\n        SkRect dst;\n        (void)this->mapRect(&dst, src);\n        return dst;\n    }\n\n    /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each\n        rect corner by SkMatrix. rect corner is processed in this order:\n        (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),\n        (rect.fLeft, rect.fBottom).\n\n        rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;\n        rect.fTop may be greater than or equal to rect.fBottom.\n\n        Given:\n\n                     | A B C |        | x |\n            Matrix = | D E F |,  pt = | y |\n                     | G H I |        | 1 |\n\n        where pt is initialized from each of (rect.fLeft, rect.fTop),\n        (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),\n        each dst SkPoint is computed as:\n\n                          |A B C| |x|                               Ax+By+C   Dx+Ey+F\n            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------\n                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I\n\n        @param dst   storage for mapped corner SkPoint\n        @param rect  SkRect to map\n    */\n    void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {\n        // This could potentially be faster if we only transformed each x and y of the rect once.\n        rect.toQuad(dst);\n        this->mapPoints(dst, 4);\n    }\n\n    /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains\n        elements other than scale or translate: asserts if SK_DEBUG is defined;\n        otherwise, results are undefined.\n\n        @param dst  storage for bounds of mapped SkPoint\n        @param src  SkRect to map\n    */\n    void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;\n\n    /** Returns geometric mean radius of ellipse formed by constructing circle of\n        size radius, and mapping constructed circle with SkMatrix. The result squared is\n        equal to the major axis length times the minor axis length.\n        Result is not meaningful if SkMatrix contains perspective elements.\n\n        @param radius  circle size to map\n        @return        average mapped radius\n    */\n    SkScalar mapRadius(SkScalar radius) const;\n\n    /** Returns true if a unit step in x at some y mapped through SkMatrix can be\n        represented by a constant vector. Returns true if getType() returns kIdentity_Mask,\n        or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask.\n\n        May return true if getType() returns kPerspective_Mask, but only when SkMatrix\n        does not include rotation or skewing along the y-axis.\n\n        @return  true if SkMatrix does not have complex perspective\n    */\n    bool isFixedStepInX() const;\n\n    /** Returns vector representing a unit step in x at y mapped through SkMatrix.\n        If isFixedStepInX() is false, returned value is undefined.\n\n        @param y  position of line parallel to x-axis\n        @return   vector advance of mapped unit step in x\n    */\n    SkVector fixedStepInX(SkScalar y) const;\n\n    /** Returns true if SkMatrix equals m, using an efficient comparison.\n\n        Returns false when the sign of zero values is the different; when one\n        matrix has positive zero value and the other has negative zero value.\n\n        Returns true even when both SkMatrix contain NaN.\n\n        NaN never equals any value, including itself. To improve performance, NaN values\n        are treated as bit patterns that are equal if their bit patterns are equal.\n\n        @param m  SkMatrix to compare\n        @return   true if m and SkMatrix are represented by identical bit patterns\n    */\n    bool cheapEqualTo(const SkMatrix& m) const {\n        return 0 == memcmp(fMat, m.fMat, sizeof(fMat));\n    }\n\n    /** Compares a and b; returns true if a and b are numerically equal. Returns true\n        even if sign of zero values are different. Returns false if either SkMatrix\n        contains NaN, even if the other SkMatrix also contains NaN.\n\n        @param a  SkMatrix to compare\n        @param b  SkMatrix to compare\n        @return   true if SkMatrix a and SkMatrix b are numerically equal\n    */\n    friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);\n\n    /** Compares a and b; returns true if a and b are not numerically equal. Returns false\n        even if sign of zero values are different. Returns true if either SkMatrix\n        contains NaN, even if the other SkMatrix also contains NaN.\n\n        @param a  SkMatrix to compare\n        @param b  SkMatrix to compare\n        @return   true if SkMatrix a and SkMatrix b are numerically not equal\n    */\n    friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {\n        return !(a == b);\n    }\n\n    /** Writes text representation of SkMatrix to standard output. Floating point values\n        are written with limited precision; it may not be possible to reconstruct\n        original SkMatrix from output.\n    */\n    void dump() const;\n\n    /** Creates string representation of SkMatrix. Floating point values\n        are written with limited precision; it may not be possible to reconstruct\n        original SkMatrix from output.\n\n        @param str  storage for string representation of SkMatrix\n    */\n    void toString(SkString* str) const;\n\n    /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and\n        skewing elements.\n        Returns -1 if scale factor overflows or SkMatrix contains perspective.\n\n        @return  minimum scale factor\n    */\n    SkScalar getMinScale() const;\n\n    /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and\n        skewing elements.\n        Returns -1 if scale factor overflows or SkMatrix contains perspective.\n\n        @return  maximum scale factor\n    */\n    SkScalar getMaxScale() const;\n\n    /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the\n        maximum scaling factor. Scaling factors are computed by decomposing\n        the SkMatrix scaling and skewing elements.\n\n        Returns true if scaleFactors are found; otherwise, returns false and sets\n        scaleFactors to undefined values.\n\n        @param scaleFactors  storage for minimum and maximum scale factors\n        @return              true if scale factors were computed correctly\n    */\n    bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;\n\n    /** Decomposes SkMatrix into scale components and whatever remains. Returns false if\n        SkMatrix could not be decomposed.\n\n        Sets scale to portion of SkMatrix that scales in x and y. Sets remaining to SkMatrix\n        with x and y scaling factored out. remaining may be passed as nullptr\n        to determine if SkMatrix can be decomposed without computing remainder.\n\n        Returns true if scale components are found. scale and remaining are\n        unchanged if SkMatrix contains perspective; scale factors are not finite, or\n        are nearly zero.\n\n        On success\n        Matrix = scale * Remaining\n\n        @param scale      x and y scaling factors; may be nullptr\n        @param remaining  SkMatrix without scaling; may be nullptr\n        @return           true if scale can be computed\n    */\n    bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;\n\n    /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to:\n\n            | 1 0 0 |\n            | 0 1 0 |\n            | 0 0 1 |\n\n        @return  const identity SkMatrix\n    */\n    static const SkMatrix& I();\n\n    /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set\n        to:\n\n            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |\n            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |\n            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |\n\n        @return  const invalid SkMatrix\n    */\n    static const SkMatrix& InvalidMatrix();\n\n    /** Returns SkMatrix a multiplied by SkMatrix b.\n\n        Given:\n\n                | A B C |      | J K L |\n            a = | D E F |, b = | M N O |\n                | G H I |      | P Q R |\n\n        sets SkMatrix to:\n\n                    | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |\n            a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |\n                    | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |\n\n        @param a  SkMatrix on left side of multiply expression\n        @param b  SkMatrix on right side of multiply expression\n        @return   SkMatrix computed from a times b\n    */\n    static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {\n        SkMatrix result;\n        result.setConcat(a, b);\n        return result;\n    }\n\n    /** Sets internal cache to unknown state. Use to force update after repeated\n        modifications to SkMatrix element reference returned by operator[](int index).\n    */\n    void dirtyMatrixTypeCache() {\n        this->setTypeMask(kUnknown_Mask);\n    }\n\n    /** Initializes SkMatrix with scale and translate elements.\n\n            | sx  0 tx |\n            |  0 sy ty |\n            |  0  0  1 |\n\n        @param sx  horizontal scale factor to store\n        @param sy  vertical scale factor to store\n        @param tx  horizontal translation to store\n        @param ty  vertical translation to store\n    */\n    void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {\n        fMat[kMScaleX] = sx;\n        fMat[kMSkewX]  = 0;\n        fMat[kMTransX] = tx;\n\n        fMat[kMSkewY]  = 0;\n        fMat[kMScaleY] = sy;\n        fMat[kMTransY] = ty;\n\n        fMat[kMPersp0] = 0;\n        fMat[kMPersp1] = 0;\n        fMat[kMPersp2] = 1;\n\n        unsigned mask = 0;\n        if (sx != 1 || sy != 1) {\n            mask |= kScale_Mask;\n        }\n        if (tx || ty) {\n            mask |= kTranslate_Mask;\n        }\n        this->setTypeMask(mask | kRectStaysRect_Mask);\n    }\n\n    /** Returns true if all elements of the matrix are finite. Returns false if any\n        element is infinity, or NaN.\n\n        @return  true if matrix has only finite elements\n    */\n    bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }\n\nprivate:\n    /** Set if the matrix will map a rectangle to another rectangle. This\n        can be true if the matrix is scale-only, or rotates a multiple of\n        90 degrees.\n\n        This bit will be set on identity matrices\n    */\n    static constexpr int kRectStaysRect_Mask = 0x10;\n\n    /** Set if the perspective bit is valid even though the rest of\n        the matrix is Unknown.\n    */\n    static constexpr int kOnlyPerspectiveValid_Mask = 0x40;\n\n    static constexpr int kUnknown_Mask = 0x80;\n\n    static constexpr int kORableMasks = kTranslate_Mask |\n                                        kScale_Mask |\n                                        kAffine_Mask |\n                                        kPerspective_Mask;\n\n    static constexpr int kAllMasks = kTranslate_Mask |\n                                     kScale_Mask |\n                                     kAffine_Mask |\n                                     kPerspective_Mask |\n                                     kRectStaysRect_Mask;\n\n    SkScalar         fMat[9];\n    mutable uint32_t fTypeMask;\n\n    static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);\n\n    uint8_t computeTypeMask() const;\n    uint8_t computePerspectiveTypeMask() const;\n\n    void setTypeMask(int mask) {\n        // allow kUnknown or a valid mask\n        SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||\n                 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)\n                 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));\n        fTypeMask = SkToU8(mask);\n    }\n\n    void orTypeMask(int mask) {\n        SkASSERT((mask & kORableMasks) == mask);\n        fTypeMask = SkToU8(fTypeMask | mask);\n    }\n\n    void clearTypeMask(int mask) {\n        // only allow a valid mask\n        SkASSERT((mask & kAllMasks) == mask);\n        fTypeMask = fTypeMask & ~mask;\n    }\n\n    TypeMask getPerspectiveTypeMaskOnly() const {\n        if ((fTypeMask & kUnknown_Mask) &&\n            !(fTypeMask & kOnlyPerspectiveValid_Mask)) {\n            fTypeMask = this->computePerspectiveTypeMask();\n        }\n        return (TypeMask)(fTypeMask & 0xF);\n    }\n\n    /** Returns true if we already know that the matrix is identity;\n        false otherwise.\n    */\n    bool isTriviallyIdentity() const {\n        if (fTypeMask & kUnknown_Mask) {\n            return false;\n        }\n        return ((fTypeMask & 0xF) == 0);\n    }\n\n    inline void updateTranslateMask() {\n        if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {\n            fTypeMask |= kTranslate_Mask;\n        } else {\n            fTypeMask &= ~kTranslate_Mask;\n        }\n    }\n\n    typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,\n                                 SkPoint* result);\n\n    static MapXYProc GetMapXYProc(TypeMask mask) {\n        SkASSERT((mask & ~kAllMasks) == 0);\n        return gMapXYProcs[mask & kAllMasks];\n    }\n\n    MapXYProc getMapXYProc() const {\n        return GetMapXYProc(this->getType());\n    }\n\n    typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],\n                                  const SkPoint src[], int count);\n\n    static MapPtsProc GetMapPtsProc(TypeMask mask) {\n        SkASSERT((mask & ~kAllMasks) == 0);\n        return gMapPtsProcs[mask & kAllMasks];\n    }\n\n    MapPtsProc getMapPtsProc() const {\n        return GetMapPtsProc(this->getType());\n    }\n\n    bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;\n\n    static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);\n    static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);\n    static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);\n\n    static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n    static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);\n\n    static const MapXYProc gMapXYProcs[];\n\n    static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);\n    static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);\n    static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);\n    static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],\n                               int count);\n    static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);\n\n    static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);\n\n    static const MapPtsProc gMapPtsProcs[];\n\n    // return the number of bytes written, whether or not buffer is null\n    size_t writeToMemory(void* buffer) const;\n    /**\n     * Reads data from the buffer parameter\n     *\n     * @param buffer Memory to read from\n     * @param length Amount of memory available in the buffer\n     * @return number of bytes read (must be a multiple of 4) or\n     *         0 if there was not enough memory available\n     */\n    size_t readFromMemory(const void* buffer, size_t length);\n\n    friend class SkPerspIter;\n    friend class SkMatrixPriv;\n    friend class SkReader32;\n    friend class SerializationTest;\n};\nSK_END_REQUIRE_DENSE\n\n#endif\n"
  },
  {
    "path": "include/core/SkMatrix44.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMatrix44_DEFINED\n#define SkMatrix44_DEFINED\n\n#include <atomic>\n\n#include \"SkMatrix.h\"\n#include \"SkScalar.h\"\n\n#ifdef SK_MSCALAR_IS_DOUBLE\n#ifdef SK_MSCALAR_IS_FLOAT\n    #error \"can't define MSCALAR both as DOUBLE and FLOAT\"\n#endif\n    typedef double SkMScalar;\n\n    static inline double SkFloatToMScalar(float x) {\n        return static_cast<double>(x);\n    }\n    static inline float SkMScalarToFloat(double x) {\n        return static_cast<float>(x);\n    }\n    static inline double SkDoubleToMScalar(double x) {\n        return x;\n    }\n    static inline double SkMScalarToDouble(double x) {\n        return x;\n    }\n    static inline double SkMScalarAbs(double x) {\n        return fabs(x);\n    }\n    static const SkMScalar SK_MScalarPI = 3.141592653589793;\n\n    #define SkMScalarFloor(x)           sk_double_floor(x)\n    #define SkMScalarCeil(x)            sk_double_ceil(x)\n    #define SkMScalarRound(x)           sk_double_round(x)\n\n    #define SkMScalarFloorToInt(x)      sk_double_floor2int(x)\n    #define SkMScalarCeilToInt(x)       sk_double_ceil2int(x)\n    #define SkMScalarRoundToInt(x)      sk_double_round2int(x)\n\n\n#elif defined SK_MSCALAR_IS_FLOAT\n#ifdef SK_MSCALAR_IS_DOUBLE\n    #error \"can't define MSCALAR both as DOUBLE and FLOAT\"\n#endif\n    typedef float SkMScalar;\n\n    static inline float SkFloatToMScalar(float x) {\n        return x;\n    }\n    static inline float SkMScalarToFloat(float x) {\n        return x;\n    }\n    static inline float SkDoubleToMScalar(double x) {\n        return sk_double_to_float(x);\n    }\n    static inline double SkMScalarToDouble(float x) {\n        return static_cast<double>(x);\n    }\n    static inline float SkMScalarAbs(float x) {\n        return sk_float_abs(x);\n    }\n    static const SkMScalar SK_MScalarPI = 3.14159265f;\n\n    #define SkMScalarFloor(x)           sk_float_floor(x)\n    #define SkMScalarCeil(x)            sk_float_ceil(x)\n    #define SkMScalarRound(x)           sk_float_round(x)\n\n    #define SkMScalarFloorToInt(x)      sk_float_floor2int(x)\n    #define SkMScalarCeilToInt(x)       sk_float_ceil2int(x)\n    #define SkMScalarRoundToInt(x)      sk_float_round2int(x)\n\n#endif\n\n#define SkIntToMScalar(n)       static_cast<SkMScalar>(n)\n\n#define SkMScalarToScalar(x)    SkMScalarToFloat(x)\n#define SkScalarToMScalar(x)    SkFloatToMScalar(x)\n\nstatic const SkMScalar SK_MScalar1 = 1;\n\n///////////////////////////////////////////////////////////////////////////////\n\nstruct SkVector4 {\n    SkScalar fData[4];\n\n    SkVector4() {\n        this->set(0, 0, 0, 1);\n    }\n    SkVector4(const SkVector4& src) {\n        memcpy(fData, src.fData, sizeof(fData));\n    }\n    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {\n        fData[0] = x;\n        fData[1] = y;\n        fData[2] = z;\n        fData[3] = w;\n    }\n\n    SkVector4& operator=(const SkVector4& src) {\n        memcpy(fData, src.fData, sizeof(fData));\n        return *this;\n    }\n\n    bool operator==(const SkVector4& v) {\n        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&\n               fData[2] == v.fData[2] && fData[3] == v.fData[3];\n    }\n    bool operator!=(const SkVector4& v) {\n        return !(*this == v);\n    }\n    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {\n        return fData[0] == x && fData[1] == y &&\n               fData[2] == z && fData[3] == w;\n    }\n\n    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {\n        fData[0] = x;\n        fData[1] = y;\n        fData[2] = z;\n        fData[3] = w;\n    }\n};\n\n/** \\class SkMatrix44\n\n    The SkMatrix44 class holds a 4x4 matrix.\n\n    SkMatrix44 is not thread safe unless you've first called SkMatrix44::getType().\n*/\nclass SK_API SkMatrix44 {\npublic:\n\n    enum Uninitialized_Constructor {\n        kUninitialized_Constructor\n    };\n    enum Identity_Constructor {\n        kIdentity_Constructor\n    };\n\n    SkMatrix44(Uninitialized_Constructor) {}\n\n    constexpr SkMatrix44(Identity_Constructor)\n        : fMat{{ 1, 0, 0, 0, },\n               { 0, 1, 0, 0, },\n               { 0, 0, 1, 0, },\n               { 0, 0, 0, 1, }}\n        , fTypeMask(kIdentity_Mask)\n    {}\n\n    SK_ATTR_DEPRECATED(\"use the constructors that take an enum\")\n    SkMatrix44() { this->setIdentity(); }\n\n    SkMatrix44(const SkMatrix44& src) {\n        memcpy(fMat, src.fMat, sizeof(fMat));\n        fTypeMask.store(src.fTypeMask, std::memory_order_relaxed);\n    }\n\n    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {\n        this->setConcat(a, b);\n    }\n\n    SkMatrix44& operator=(const SkMatrix44& src) {\n        if (&src != this) {\n            memcpy(fMat, src.fMat, sizeof(fMat));\n            fTypeMask.store(src.fTypeMask, std::memory_order_relaxed);\n        }\n        return *this;\n    }\n\n    bool operator==(const SkMatrix44& other) const;\n    bool operator!=(const SkMatrix44& other) const {\n        return !(other == *this);\n    }\n\n    /* When converting from SkMatrix44 to SkMatrix, the third row and\n     * column is dropped.  When converting from SkMatrix to SkMatrix44\n     * the third row and column remain as identity:\n     * [ a b c ]      [ a b 0 c ]\n     * [ d e f ]  ->  [ d e 0 f ]\n     * [ g h i ]      [ 0 0 1 0 ]\n     *                [ g h 0 i ]\n     */\n    SkMatrix44(const SkMatrix&);\n    SkMatrix44& operator=(const SkMatrix& src);\n    operator SkMatrix() const;\n\n    /**\n     *  Return a reference to a const identity matrix\n     */\n    static const SkMatrix44& I();\n\n    enum TypeMask {\n        kIdentity_Mask      = 0,\n        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation\n        kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1\n        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates\n        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective\n    };\n\n    /**\n     *  Returns a bitfield describing the transformations the matrix may\n     *  perform. The bitfield is computed conservatively, so it may include\n     *  false positives. For example, when kPerspective_Mask is true, all\n     *  other bits may be set to true even in the case of a pure perspective\n     *  transform.\n     */\n    inline TypeMask getType() const {\n        if (fTypeMask.load(std::memory_order_relaxed) & kUnknown_Mask) {\n            fTypeMask.store(this->computeTypeMask(), std::memory_order_relaxed);\n        }\n        SkASSERT(!(fTypeMask & kUnknown_Mask));\n        return (TypeMask)fTypeMask.load(std::memory_order_relaxed);\n    }\n\n    /**\n     *  Return true if the matrix is identity.\n     */\n    inline bool isIdentity() const {\n        return kIdentity_Mask == this->getType();\n    }\n\n    /**\n     *  Return true if the matrix contains translate or is identity.\n     */\n    inline bool isTranslate() const {\n        return !(this->getType() & ~kTranslate_Mask);\n    }\n\n    /**\n     *  Return true if the matrix only contains scale or translate or is identity.\n     */\n    inline bool isScaleTranslate() const {\n        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));\n    }\n\n    /**\n     *  Returns true if the matrix only contains scale or is identity.\n     */\n    inline bool isScale() const {\n            return !(this->getType() & ~kScale_Mask);\n    }\n\n    inline bool hasPerspective() const {\n        return SkToBool(this->getType() & kPerspective_Mask);\n    }\n\n    void setIdentity();\n    inline void reset() { this->setIdentity();}\n\n    /**\n     *  get a value from the matrix. The row,col parameters work as follows:\n     *  (0, 0)  scale-x\n     *  (0, 3)  translate-x\n     *  (3, 0)  perspective-x\n     */\n    inline SkMScalar get(int row, int col) const {\n        SkASSERT((unsigned)row <= 3);\n        SkASSERT((unsigned)col <= 3);\n        return fMat[col][row];\n    }\n\n    /**\n     *  set a value in the matrix. The row,col parameters work as follows:\n     *  (0, 0)  scale-x\n     *  (0, 3)  translate-x\n     *  (3, 0)  perspective-x\n     */\n    inline void set(int row, int col, SkMScalar value) {\n        SkASSERT((unsigned)row <= 3);\n        SkASSERT((unsigned)col <= 3);\n        fMat[col][row] = value;\n        this->dirtyTypeMask();\n    }\n\n    inline double getDouble(int row, int col) const {\n        return SkMScalarToDouble(this->get(row, col));\n    }\n    inline void setDouble(int row, int col, double value) {\n        this->set(row, col, SkDoubleToMScalar(value));\n    }\n    inline float getFloat(int row, int col) const {\n        return SkMScalarToFloat(this->get(row, col));\n    }\n    inline void setFloat(int row, int col, float value) {\n        this->set(row, col, SkFloatToMScalar(value));\n    }\n\n    /** These methods allow one to efficiently read matrix entries into an\n     *  array. The given array must have room for exactly 16 entries. Whenever\n     *  possible, they will try to use memcpy rather than an entry-by-entry\n     *  copy.\n     *\n     *  Col major indicates that consecutive elements of columns will be stored\n     *  contiguously in memory.  Row major indicates that consecutive elements\n     *  of rows will be stored contiguously in memory.\n     */\n    void asColMajorf(float[]) const;\n    void asColMajord(double[]) const;\n    void asRowMajorf(float[]) const;\n    void asRowMajord(double[]) const;\n\n    /** These methods allow one to efficiently set all matrix entries from an\n     *  array. The given array must have room for exactly 16 entries. Whenever\n     *  possible, they will try to use memcpy rather than an entry-by-entry\n     *  copy.\n     *\n     *  Col major indicates that input memory will be treated as if consecutive\n     *  elements of columns are stored contiguously in memory.  Row major\n     *  indicates that input memory will be treated as if consecutive elements\n     *  of rows are stored contiguously in memory.\n     */\n    void setColMajorf(const float[]);\n    void setColMajord(const double[]);\n    void setRowMajorf(const float[]);\n    void setRowMajord(const double[]);\n\n#ifdef SK_MSCALAR_IS_FLOAT\n    void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }\n    void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }\n#else\n    void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }\n    void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }\n#endif\n\n    /* This sets the top-left of the matrix and clears the translation and\n     * perspective components (with [3][3] set to 1).  m_ij is interpreted\n     * as the matrix entry at row = i, col = j. */\n    void set3x3(SkMScalar m_00, SkMScalar m_10, SkMScalar m_20,\n                SkMScalar m_01, SkMScalar m_11, SkMScalar m_21,\n                SkMScalar m_02, SkMScalar m_12, SkMScalar m_22);\n    void set3x3RowMajorf(const float[]);\n\n    void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);\n    void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);\n    void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);\n\n    void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);\n    void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);\n    void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);\n\n    inline void setScale(SkMScalar scale) {\n        this->setScale(scale, scale, scale);\n    }\n    inline void preScale(SkMScalar scale) {\n        this->preScale(scale, scale, scale);\n    }\n    inline void postScale(SkMScalar scale) {\n        this->postScale(scale, scale, scale);\n    }\n\n    void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,\n                               SkMScalar degrees) {\n        this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);\n    }\n\n    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,\n        it will be automatically resized.\n     */\n    void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,\n                        SkMScalar radians);\n    /** Rotate about the vector [x,y,z]. Does not check the length of the\n        vector, assuming it is unit-length.\n     */\n    void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,\n                            SkMScalar radians);\n\n    void setConcat(const SkMatrix44& a, const SkMatrix44& b);\n    inline void preConcat(const SkMatrix44& m) {\n        this->setConcat(*this, m);\n    }\n    inline void postConcat(const SkMatrix44& m) {\n        this->setConcat(m, *this);\n    }\n\n    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {\n        return SkMatrix44(a, b);\n    }\n\n    /** If this is invertible, return that in inverse and return true. If it is\n        not invertible, return false and leave the inverse parameter in an\n        unspecified state.\n     */\n    bool invert(SkMatrix44* inverse) const;\n\n    /** Transpose this matrix in place. */\n    void transpose();\n\n    /** Apply the matrix to the src vector, returning the new vector in dst.\n        It is legal for src and dst to point to the same memory.\n     */\n    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;\n    inline void mapScalars(SkScalar vec[4]) const {\n        this->mapScalars(vec, vec);\n    }\n\n    SK_ATTR_DEPRECATED(\"use mapScalars\")\n    void map(const SkScalar src[4], SkScalar dst[4]) const {\n        this->mapScalars(src, dst);\n    }\n\n    SK_ATTR_DEPRECATED(\"use mapScalars\")\n    void map(SkScalar vec[4]) const {\n        this->mapScalars(vec, vec);\n    }\n\n#ifdef SK_MSCALAR_IS_DOUBLE\n    void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;\n#elif defined SK_MSCALAR_IS_FLOAT\n    inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {\n        this->mapScalars(src, dst);\n    }\n#endif\n    inline void mapMScalars(SkMScalar vec[4]) const {\n        this->mapMScalars(vec, vec);\n    }\n\n    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {\n        SkVector4 dst;\n        m.mapScalars(src.fData, dst.fData);\n        return dst;\n    }\n\n    /**\n     *  map an array of [x, y, 0, 1] through the matrix, returning an array\n     *  of [x', y', z', w'].\n     *\n     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1\n     *  @param count    number of [x, y] pairs in src2\n     *  @param dst4     array of [x', y', z', w'] quads as the output.\n     */\n    void map2(const float src2[], int count, float dst4[]) const;\n    void map2(const double src2[], int count, double dst4[]) const;\n\n    /** Returns true if transformating an axis-aligned square in 2d by this matrix\n        will produce another 2d axis-aligned square; typically means the matrix\n        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90\n        degrees into a perpendicular plane collapses a square to a line, but\n        is still considered to be axis-aligned.\n\n        By default, tolerates very slight error due to float imprecisions;\n        a 90-degree rotation can still end up with 10^-17 of\n        \"non-axis-aligned\" result.\n     */\n    bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;\n\n    void dump() const;\n\n    double determinant() const;\n\nprivate:\n    /* This is indexed by [col][row]. */\n    SkMScalar                       fMat[4][4];\n    mutable std::atomic<unsigned>   fTypeMask;\n\n    static constexpr int kUnknown_Mask = 0x80;\n\n    static constexpr int kAllPublic_Masks = 0xF;\n\n    void as3x4RowMajorf(float[]) const;\n    void set3x4RowMajorf(const float[]);\n\n    SkMScalar transX() const { return fMat[3][0]; }\n    SkMScalar transY() const { return fMat[3][1]; }\n    SkMScalar transZ() const { return fMat[3][2]; }\n\n    SkMScalar scaleX() const { return fMat[0][0]; }\n    SkMScalar scaleY() const { return fMat[1][1]; }\n    SkMScalar scaleZ() const { return fMat[2][2]; }\n\n    SkMScalar perspX() const { return fMat[0][3]; }\n    SkMScalar perspY() const { return fMat[1][3]; }\n    SkMScalar perspZ() const { return fMat[2][3]; }\n\n    int computeTypeMask() const;\n\n    inline void dirtyTypeMask() {\n        fTypeMask.store(kUnknown_Mask, std::memory_order_relaxed);\n    }\n\n    inline void setTypeMask(int mask) {\n        SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));\n        fTypeMask.store(mask, std::memory_order_relaxed);\n    }\n\n    /**\n     *  Does not take the time to 'compute' the typemask. Only returns true if\n     *  we already know that this matrix is identity.\n     */\n    inline bool isTriviallyIdentity() const {\n        return 0 == fTypeMask.load(std::memory_order_relaxed);\n    }\n\n    inline const SkMScalar* values() const { return &fMat[0][0]; }\n\n    friend class SkColorSpace;\n    friend class SkColorSpace_XYZ;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkMetaData.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkMetaData_DEFINED\n#define SkMetaData_DEFINED\n\n#include \"SkScalar.h\"\n\nclass SkRefCnt;\n\nclass SK_API SkMetaData {\npublic:\n    /**\n     *  Used to manage the life-cycle of a ptr in the metadata. This is option\n     *  in setPtr, and is only invoked when either copying one metadata to\n     *  another, or when the metadata is destroyed.\n     *\n     *  setPtr(name, ptr, proc) {\n     *      fPtr = proc(ptr, true);\n     *  }\n     *\n     *  copy: A = B {\n     *      A.fPtr = B.fProc(B.fPtr, true);\n     *  }\n     *\n     *  ~SkMetaData {\n     *      fProc(fPtr, false);\n     *  }\n     */\n    typedef void* (*PtrProc)(void* ptr, bool doRef);\n\n    /**\n     *  Implements PtrProc for SkRefCnt pointers\n     */\n    static void* RefCntProc(void* ptr, bool doRef);\n\n    SkMetaData();\n    SkMetaData(const SkMetaData& src);\n    ~SkMetaData();\n\n    SkMetaData& operator=(const SkMetaData& src);\n\n    void reset();\n\n    bool findS32(const char name[], int32_t* value = nullptr) const;\n    bool findScalar(const char name[], SkScalar* value = nullptr) const;\n    const SkScalar* findScalars(const char name[], int* count,\n                                SkScalar values[] = nullptr) const;\n    const char* findString(const char name[]) const;\n    bool findPtr(const char name[], void** value = nullptr, PtrProc* = nullptr) const;\n    bool findBool(const char name[], bool* value = nullptr) const;\n    const void* findData(const char name[], size_t* byteCount = nullptr) const;\n\n    bool hasS32(const char name[], int32_t value) const {\n        int32_t v;\n        return this->findS32(name, &v) && v == value;\n    }\n    bool hasScalar(const char name[], SkScalar value) const {\n        SkScalar v;\n        return this->findScalar(name, &v) && v == value;\n    }\n    bool hasString(const char name[], const char value[]) const {\n        const char* v = this->findString(name);\n        return  (v == nullptr && value == nullptr) ||\n                (v != nullptr && value != nullptr && !strcmp(v, value));\n    }\n    bool hasPtr(const char name[], void* value) const {\n        void* v;\n        return this->findPtr(name, &v) && v == value;\n    }\n    bool hasBool(const char name[], bool value) const {\n        bool    v;\n        return this->findBool(name, &v) && v == value;\n    }\n    bool hasData(const char name[], const void* data, size_t byteCount) const {\n        size_t len;\n        const void* ptr = this->findData(name, &len);\n        return ptr && len == byteCount && !memcmp(ptr, data, len);\n    }\n\n    void setS32(const char name[], int32_t value);\n    void setScalar(const char name[], SkScalar value);\n    SkScalar* setScalars(const char name[], int count, const SkScalar values[] = nullptr);\n    void setString(const char name[], const char value[]);\n    void setPtr(const char name[], void* value, PtrProc proc = nullptr);\n    void setBool(const char name[], bool value);\n    // the data is copied from the input pointer.\n    void setData(const char name[], const void* data, size_t byteCount);\n\n    bool removeS32(const char name[]);\n    bool removeScalar(const char name[]);\n    bool removeString(const char name[]);\n    bool removePtr(const char name[]);\n    bool removeBool(const char name[]);\n    bool removeData(const char name[]);\n\n    // helpers for SkRefCnt\n    bool findRefCnt(const char name[], SkRefCnt** ptr = nullptr) {\n        return this->findPtr(name, reinterpret_cast<void**>(ptr));\n    }\n    bool hasRefCnt(const char name[], SkRefCnt* ptr) {\n        return this->hasPtr(name, ptr);\n    }\n    void setRefCnt(const char name[], SkRefCnt* ptr) {\n        this->setPtr(name, ptr, RefCntProc);\n    }\n    bool removeRefCnt(const char name[]) {\n        return this->removePtr(name);\n    }\n\n    enum Type {\n        kS32_Type,\n        kScalar_Type,\n        kString_Type,\n        kPtr_Type,\n        kBool_Type,\n        kData_Type,\n\n        kTypeCount\n    };\n\n    struct Rec;\n    class Iter;\n    friend class Iter;\n\n    class Iter {\n    public:\n        Iter() : fRec(nullptr) {}\n        Iter(const SkMetaData&);\n\n        /** Reset the iterator, so that calling next() will return the first\n            data element. This is done implicitly in the constructor.\n        */\n        void reset(const SkMetaData&);\n\n        /** Each time next is called, it returns the name of the next data element,\n            or null when there are no more elements. If non-null is returned, then the\n            element's type is returned (if not null), and the number of data values\n            is returned in count (if not null).\n        */\n        const char* next(Type*, int* count);\n\n    private:\n        Rec* fRec;\n    };\n\npublic:\n    struct Rec {\n        Rec*        fNext;\n        uint16_t    fDataCount; // number of elements\n        uint8_t     fDataLen;   // sizeof a single element\n        uint8_t     fType;\n\n        const void* data() const { return (this + 1); }\n        void*       data() { return (this + 1); }\n        const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }\n        char*       name() { return (char*)this->data() + fDataLen * fDataCount; }\n\n        static Rec* Alloc(size_t);\n        static void Free(Rec*);\n    };\n    Rec*    fRec;\n\n    const Rec* find(const char name[], Type) const;\n    void* set(const char name[], const void* data, size_t len, Type, int count);\n    bool remove(const char name[], Type);\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkMilestone.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SK_MILESTONE\n#define SK_MILESTONE 69\n#endif\n"
  },
  {
    "path": "include/core/SkMultiPictureDraw.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMultiPictureDraw_DEFINED\n#define SkMultiPictureDraw_DEFINED\n\n#include \"../private/SkTDArray.h\"\n#include \"SkMatrix.h\"\n\nclass SkCanvas;\nclass SkPaint;\nclass SkPicture;\n\n/** \\class SkMultiPictureDraw\n\n    The MultiPictureDraw object accepts several picture/canvas pairs and\n    then attempts to optimally draw the pictures into the canvases, sharing\n    as many resources as possible.\n*/\nclass SK_API SkMultiPictureDraw {\npublic:\n    /**\n     *  Create an object to optimize the drawing of multiple pictures.\n     *  @param reserve Hint for the number of add calls expected to be issued\n     */\n    SkMultiPictureDraw(int reserve = 0);\n    ~SkMultiPictureDraw() { this->reset(); }\n\n    /**\n     *  Add a canvas/picture pair for later rendering.\n     *  @param canvas   the canvas in which to draw picture\n     *  @param picture  the picture to draw into canvas\n     *  @param matrix   if non-NULL, applied to the CTM when drawing\n     *  @param paint    if non-NULL, draw picture to a temporary buffer\n     *                  and then apply the paint when the result is drawn\n     */\n    void add(SkCanvas* canvas,\n             const SkPicture* picture,\n             const SkMatrix* matrix = nullptr,\n             const SkPaint* paint = nullptr);\n\n    /**\n     *  Perform all the previously added draws. This will reset the state\n     *  of this object. If flush is true, all canvases are flushed after\n     *  draw.\n     */\n    void draw(bool flush = false);\n\n    /**\n     *  Abandon all buffered draws and reset to the initial state.\n     */\n    void reset();\n\nprivate:\n    struct DrawData {\n        SkCanvas*        fCanvas;\n        const SkPicture* fPicture; // reffed\n        SkMatrix         fMatrix;\n        SkPaint*         fPaint;   // owned\n\n        void init(SkCanvas*, const SkPicture*, const SkMatrix*, const SkPaint*);\n        void draw();\n\n        static void Reset(SkTDArray<DrawData>&);\n    };\n\n    SkTDArray<DrawData> fThreadSafeDrawData;\n    SkTDArray<DrawData> fGPUDrawData;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkOverdrawCanvas.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkOverdrawCanvas_DEFINED\n#define SkOverdrawCanvas_DEFINED\n\n#include \"SkCanvasVirtualEnforcer.h\"\n#include \"SkNWayCanvas.h\"\n\n/**\n *  Captures all drawing commands.  Rather than draw the actual content, this device\n *  increments the alpha channel of each pixel every time it would have been touched\n *  by a draw call.  This is useful for detecting overdraw.\n */\nclass SK_API SkOverdrawCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {\npublic:\n    /* Does not take ownership of canvas */\n    SkOverdrawCanvas(SkCanvas*);\n\n    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override;\n    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override;\n    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override;\n    void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,\n                          const SkPaint&) override;\n    void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,\n                           const SkPaint&) override;\n    void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;\n    void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,\n                     const SkPaint&) override;\n    void onDrawPaint(const SkPaint&) override;\n    void onDrawRect(const SkRect&, const SkPaint&) override;\n    void onDrawRegion(const SkRegion&, const SkPaint&) override;\n    void onDrawOval(const SkRect&, const SkPaint&) override;\n    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;\n    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;\n    void onDrawRRect(const SkRRect&, const SkPaint&) override;\n    void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override;\n    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;\n    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],\n                     int, SkBlendMode, const SkRect*, const SkPaint*) override;\n    void onDrawPath(const SkPath&, const SkPaint&) override;\n    void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override;\n    void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,\n                         SrcRectConstraint) override;\n    void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override;\n    void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, const SkPaint*) override;\n    void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override;\n    void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,\n                          SrcRectConstraint) override;\n    void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*) override;\n    void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,\n                             const SkPaint*) override;\n    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;\n    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;\n\n    void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override;\n    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;\n\nprivate:\n    void drawPosTextCommon(const void*, size_t, const SkScalar[], int, const SkPoint&,\n                           const SkPaint&);\n\n    inline SkPaint overdrawPaint(const SkPaint& paint);\n\n    SkPaint   fPaint;\n\n    typedef SkCanvasVirtualEnforcer<SkNWayCanvas> INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPaint.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPaint_DEFINED\n#define SkPaint_DEFINED\n\n#include \"SkBlendMode.h\"\n#include \"SkColor.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkMatrix.h\"\n#include \"SkRefCnt.h\"\n\nclass SkAutoDescriptor;\nclass SkColorFilter;\nclass SkData;\nclass SkDescriptor;\nclass SkDrawLooper;\nclass SkGlyph;\nstruct SkRect;\nclass SkGlyphCache;\nclass SkImageFilter;\nclass SkMaskFilter;\nclass SkPath;\nclass SkPathEffect;\nstruct SkPoint;\nclass SkShader;\nclass SkSurfaceProps;\nclass SkTextBlob;\nclass SkTypeface;\n\n/** \\class SkPaint\n    SkPaint controls options applied when drawing and measuring. SkPaint collects all\n    options outside of the SkCanvas clip and SkCanvas matrix.\n\n    Various options apply to text, strokes and fills, and images.\n\n    Some options may not be implemented on all platforms; in these cases, setting\n    the option has no effect. Some options are conveniences that duplicate SkCanvas\n    functionality; for instance, text size is identical to matrix scale.\n\n    SkPaint options are rarely exclusive; each option modifies a stage of the drawing\n    pipeline and multiple pipeline stages may be affected by a single SkPaint.\n\n    SkPaint collects effects and filters that describe single-pass and multiple-pass\n    algorithms that alter the drawing geometry, color, and transparency. For instance,\n    SkPaint does not directly implement dashing or blur, but contains the objects that do so.\n\n    The objects contained by SkPaint are opaque, and cannot be edited outside of the SkPaint\n    to affect it. The implementation is free to defer computations associated with the\n    SkPaint, or ignore them altogether. For instance, some GPU implementations draw all\n    SkPath geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag\n    is set in SkPaint.\n\n    SkPaint describes a single color, a single font, a single image quality, and so on.\n    Multiple colors are drawn either by using multiple paints or with objects like\n    SkShader attached to SkPaint.\n*/\nclass SK_API SkPaint {\npublic:\n\n    /** Constructs SkPaint with default values.\n\n        @return  default initialized SkPaint\n    */\n    SkPaint();\n\n    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,\n        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared\n        between the original paint and the copy. Objects containing SkRefCnt increment\n        their references by one.\n\n        The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,\n        SkDrawLooper, and SkImageFilter cannot be modified after they are created.\n        This prevents objects with SkRefCnt from being modified once SkPaint refers to them.\n\n        @param paint  original to copy\n        @return       shallow copy of paint\n    */\n    SkPaint(const SkPaint& paint);\n\n    /** Implements a move constructor to avoid increasing the reference counts\n        of objects referenced by the paint.\n\n        After the call, paint is undefined, and can be safely destructed.\n\n        @param paint  original to move\n        @return       content of paint\n    */\n    SkPaint(SkPaint&& paint);\n\n    /** Decreases SkPaint SkRefCnt of owned objects: SkTypeface, SkPathEffect, SkShader,\n        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter. If the\n        objects containing SkRefCnt go to zero, they are deleted.\n    */\n    ~SkPaint();\n\n    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,\n        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared\n        between the original paint and the copy. Objects containing SkRefCnt in the\n        prior destination are decreased by one, and the referenced objects are deleted if the\n        resulting count is zero. Objects containing SkRefCnt in the parameter paint\n        are increased by one. paint is unmodified.\n\n        @param paint  original to copy\n        @return       content of paint\n    */\n    SkPaint& operator=(const SkPaint& paint);\n\n    /** Moves the paint to avoid increasing the reference counts\n        of objects referenced by the paint parameter. Objects containing SkRefCnt in the\n        prior destination are decreased by one; those objects are deleted if the resulting count\n        is zero.\n\n        After the call, paint is undefined, and can be safely destructed.\n\n        @param paint  original to move\n        @return       content of paint\n    */\n    SkPaint& operator=(SkPaint&& paint);\n\n    /** Compares a and b, and returns true if a and b are equivalent. May return false\n        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,\n        SkDrawLooper, or SkImageFilter have identical contents but different pointers.\n\n        @param a  SkPaint to compare\n        @param b  SkPaint to compare\n        @return   true if SkPaint pair are equivalent\n    */\n    SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);\n\n    /** Compares a and b, and returns true if a and b are not equivalent. May return true\n        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,\n        SkDrawLooper, or SkImageFilter have identical contents but different pointers.\n\n        @param a  SkPaint to compare\n        @param b  SkPaint to compare\n        @return   true if SkPaint pair are not equivalent\n    */\n    friend bool operator!=(const SkPaint& a, const SkPaint& b) {\n        return !(a == b);\n    }\n\n    /** Returns a hash generated from SkPaint values and pointers.\n        Identical hashes guarantee that the paints are\n        equivalent, but differing hashes do not guarantee that the paints have differing\n        contents.\n\n        If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,\n        their hashes are also equal.\n\n        The hash returned is platform and implementation specific.\n\n        @return  a shallow hash\n    */\n    uint32_t getHash() const;\n\n    /** Sets all SkPaint contents to their initial values. This is equivalent to replacing\n        SkPaint with the result of SkPaint().\n    */\n    void reset();\n\n    /** \\enum SkPaint::Hinting\n        Hinting adjusts the glyph outlines so that the shape provides a uniform\n        look at a given point size on font engines that support it. Hinting may have a\n        muted effect or no effect at all depending on the platform.\n\n        The four levels roughly control corresponding features on platforms that use FreeType\n        as the font engine.\n    */\n    enum Hinting {\n        kNo_Hinting     = 0, //!< glyph outlines unchanged\n        kSlight_Hinting = 1, //!< minimal modification to improve constrast\n        kNormal_Hinting = 2, //!< glyph outlines modified to improve constrast\n        kFull_Hinting   = 3, //!< modifies glyph outlines for maximum constrast\n    };\n\n    /** Returns level of glyph outline adjustment.\n\n        @return  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting\n    */\n    Hinting getHinting() const {\n        return static_cast<Hinting>(fBitfields.fHinting);\n    }\n\n    /** Sets level of glyph outline adjustment.\n        Does not check for valid values of hintingLevel.\n\n        @param hintingLevel  one of: kNo_Hinting, kSlight_Hinting, kNormal_Hinting, kFull_Hinting\n    */\n    void setHinting(Hinting hintingLevel);\n\n    /** \\enum SkPaint::Flags\n        The bit values stored in Flags.\n        The default value for Flags, normally zero, can be changed at compile time\n        with a custom definition of SkPaintDefaults_Flags.\n        All flags can be read and written explicitly; Flags allows manipulating\n        multiple settings at once.\n    */\n    enum Flags {\n        kAntiAlias_Flag          = 0x01,   //!< mask for setting anti-alias\n        kDither_Flag             = 0x04,   //!< mask for setting dither\n        kFakeBoldText_Flag       = 0x20,   //!< mask for setting fake bold\n        kLinearText_Flag         = 0x40,   //!< mask for setting linear text\n        kSubpixelText_Flag       = 0x80,   //!< mask for setting subpixel text\n        kLCDRenderText_Flag      = 0x200,  //!< mask for setting LCD text\n        kEmbeddedBitmapText_Flag = 0x400,  //!< mask for setting font embedded bitmaps\n        kAutoHinting_Flag        = 0x800,  //!< mask for setting auto-hinting\n        kVerticalText_Flag       = 0x1000, //!< mask for setting vertical text\n        kAllFlags                = 0xFFFF, //!< mask of all Flags\n    };\n\n    #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    enum ReserveFlags {\n        kUnderlineText_ReserveFlag  = 0x08, //!< to be deprecated soon\n        kStrikeThruText_ReserveFlag = 0x10, //!< to be deprecated soon\n    };\n    #endif\n\n    /** Returns paint settings described by SkPaint::Flags. Each setting uses one\n        bit, and can be tested with SkPaint::Flags members.\n\n        @return  zero, one, or more bits described by SkPaint::Flags\n    */\n    uint32_t getFlags() const { return fBitfields.fFlags; }\n\n    /** Replaces SkPaint::Flags with flags, the union of the SkPaint::Flags members.\n        All SkPaint::Flags members may be cleared, or one or more may be set.\n\n        @param flags  union of SkPaint::Flags for SkPaint\n    */\n    void setFlags(uint32_t flags);\n\n    /** If true, pixels on the active edges of SkPath may be drawn with partial transparency.\n\n        Equivalent to getFlags() masked with kAntiAlias_Flag.\n\n        @return  kAntiAlias_Flag state\n    */\n    bool isAntiAlias() const {\n        return SkToBool(this->getFlags() & kAntiAlias_Flag);\n    }\n\n    /** Requests, but does not require, that SkPath edge pixels draw opaque or with\n        partial transparency.\n\n        Sets kAntiAlias_Flag if aa is true.\n        Clears kAntiAlias_Flag if aa is false.\n\n        @param aa  setting for kAntiAlias_Flag\n    */\n    void setAntiAlias(bool aa);\n\n    /** If true, color error may be distributed to smooth color transition.\n\n        Equivalent to getFlags() masked with kDither_Flag.\n\n        @return  kDither_Flag state\n    */\n    bool isDither() const {\n        return SkToBool(this->getFlags() & kDither_Flag);\n    }\n\n    /** Requests, but does not require, to distribute color error.\n\n        Sets kDither_Flag if dither is true.\n        Clears kDither_Flag if dither is false.\n\n        @param dither  setting for kDither_Flag\n    */\n    void setDither(bool dither);\n\n    /** If true, text is converted to SkPath before drawing and measuring.\n\n        Equivalent to getFlags() masked with kLinearText_Flag.\n\n        @return  kLinearText_Flag state\n    */\n    bool isLinearText() const {\n        return SkToBool(this->getFlags() & kLinearText_Flag);\n    }\n\n    /** If true, text is converted to SkPath before drawing and measuring.\n        By default, kLinearText_Flag is clear.\n\n        Sets kLinearText_Flag if linearText is true.\n        Clears kLinearText_Flag if linearText is false.\n\n        @param linearText  setting for kLinearText_Flag\n    */\n    void setLinearText(bool linearText);\n\n    /** If true, glyphs at different sub-pixel positions may differ on pixel edge coverage.\n\n        Equivalent to getFlags() masked with kSubpixelText_Flag.\n\n        @return  kSubpixelText_Flag state\n    */\n    bool isSubpixelText() const {\n        return SkToBool(this->getFlags() & kSubpixelText_Flag);\n    }\n\n    /** Requests, but does not require, that glyphs respect sub-pixel positioning.\n\n        Sets kSubpixelText_Flag if subpixelText is true.\n        Clears kSubpixelText_Flag if subpixelText is false.\n\n        @param subpixelText  setting for kSubpixelText_Flag\n    */\n    void setSubpixelText(bool subpixelText);\n\n    /** If true, glyphs may use LCD striping to improve glyph edges.\n\n        Returns true if SkPaint::Flags kLCDRenderText_Flag is set.\n\n        @return  kLCDRenderText_Flag state\n    */\n    bool isLCDRenderText() const {\n        return SkToBool(this->getFlags() & kLCDRenderText_Flag);\n    }\n\n    /** Requests, but does not require, that glyphs use LCD striping for glyph edges.\n\n        Sets kLCDRenderText_Flag if lcdText is true.\n        Clears kLCDRenderText_Flag if lcdText is false.\n\n        @param lcdText  setting for kLCDRenderText_Flag\n    */\n    void setLCDRenderText(bool lcdText);\n\n    /** If true, font engine may return glyphs from font bitmaps instead of from outlines.\n\n        Equivalent to getFlags() masked with kEmbeddedBitmapText_Flag.\n\n        @return  kEmbeddedBitmapText_Flag state\n    */\n    bool isEmbeddedBitmapText() const {\n        return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);\n    }\n\n    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.\n\n        Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.\n        Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.\n\n        @param useEmbeddedBitmapText  setting for kEmbeddedBitmapText_Flag\n    */\n    void setEmbeddedBitmapText(bool useEmbeddedBitmapText);\n\n    /** If true, and if SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting, and if\n        platform uses FreeType as the font manager, instruct the font manager to always hint\n        glyphs.\n\n        Equivalent to getFlags() masked with kAutoHinting_Flag.\n\n        @return  kAutoHinting_Flag state\n    */\n    bool isAutohinted() const {\n        return SkToBool(this->getFlags() & kAutoHinting_Flag);\n    }\n\n    /** If SkPaint::Hinting is set to kNormal_Hinting or kFull_Hinting and useAutohinter is set,\n        instruct the font manager to always hint glyphs.\n        auto-hinting has no effect if SkPaint::Hinting is set to kNo_Hinting or\n        kSlight_Hinting.\n\n        Only affects platforms that use FreeType as the font manager.\n\n        Sets kAutoHinting_Flag if useAutohinter is true.\n        Clears kAutoHinting_Flag if useAutohinter is false.\n\n        @param useAutohinter  setting for kAutoHinting_Flag\n    */\n    void setAutohinted(bool useAutohinter);\n\n    /** If true, glyphs are drawn top to bottom instead of left to right.\n\n        Equivalent to getFlags() masked with kVerticalText_Flag.\n\n        @return  kVerticalText_Flag state\n    */\n    bool isVerticalText() const {\n        return SkToBool(this->getFlags() & kVerticalText_Flag);\n    }\n\n    /** If true, text advance positions the next glyph below the previous glyph instead of to the\n        right of previous glyph.\n\n        Sets kVerticalText_Flag if vertical is true.\n        Clears kVerticalText_Flag if vertical is false.\n\n        @param verticalText  setting for kVerticalText_Flag\n    */\n    void setVerticalText(bool verticalText);\n\n    /** If true, approximate bold by increasing the stroke width when creating glyph bitmaps\n        from outlines.\n\n        Equivalent to getFlags() masked with kFakeBoldText_Flag.\n\n        @return  kFakeBoldText_Flag state\n    */\n    bool isFakeBoldText() const {\n        return SkToBool(this->getFlags() & kFakeBoldText_Flag);\n    }\n\n    /** Use increased stroke width when creating glyph bitmaps to approximate a bold typeface.\n\n        Sets kFakeBoldText_Flag if fakeBoldText is true.\n        Clears kFakeBoldText_Flag if fakeBoldText is false.\n\n        @param fakeBoldText  setting for kFakeBoldText_Flag\n    */\n    void setFakeBoldText(bool fakeBoldText);\n\n    /** Deprecated.\n    */\n    bool isDevKernText() const { return false; }\n\n    /** Deprecated.\n    */\n    void setDevKernText(bool) { }\n\n    /** Returns SkFilterQuality, the image filtering level. A lower setting\n        draws faster; a higher setting looks better when the image is scaled.\n\n        @return  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,\n                 kMedium_SkFilterQuality, kHigh_SkFilterQuality\n    */\n    SkFilterQuality getFilterQuality() const {\n        return (SkFilterQuality)fBitfields.fFilterQuality;\n    }\n\n    /** Sets SkFilterQuality, the image filtering level. A lower setting\n        draws faster; a higher setting looks better when the image is scaled.\n        Does not check to see if quality is valid.\n\n        @param quality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,\n                        kMedium_SkFilterQuality, kHigh_SkFilterQuality\n    */\n    void setFilterQuality(SkFilterQuality quality);\n\n    /** \\enum SkPaint::Style\n        Set Style to fill, stroke, or both fill and stroke geometry.\n        The stroke and fill\n        share all paint attributes; for instance, they are drawn with the same color.\n\n        Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and\n        a fill draw.\n    */\n    enum Style {\n        kFill_Style,          //!< set to fill geometry\n        kStroke_Style,        //!< set to stroke geometry\n        kStrokeAndFill_Style, //!< sets to stroke and fill geometry\n    };\n\n    /** May be used to verify that SkPaint::Style is a legal value.\n    */\n    static constexpr int kStyleCount = kStrokeAndFill_Style + 1;\n\n    /** Whether the geometry is filled, stroked, or filled and stroked.\n\n        @return  one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style\n    */\n    Style getStyle() const { return (Style)fBitfields.fStyle; }\n\n    /** Sets whether the geometry is filled, stroked, or filled and stroked.\n        Has no effect if style is not a legal SkPaint::Style value.\n\n        @param style  one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style\n    */\n    void setStyle(Style style);\n\n    /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.\n        Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract\n        a color component.\n\n        @return  unpremultiplied ARGB\n    */\n    SkColor getColor() const { return fColor; }\n\n    /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,\n        unpremultiplied, packing 8-bit components for alpha, red, blue, and green.\n\n        @param color  unpremultiplied ARGB\n    */\n    void setColor(SkColor color);\n\n    /** Retrieves alpha from the color used when stroking and filling.\n\n        @return  alpha ranging from zero, fully transparent, to 255, fully opaque\n    */\n    uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }\n\n    /** Replaces alpha, leaving RGB\n        unchanged. An out of range value triggers an assert in the debug\n        build. a is a value from zero to 255.\n        a set to zero makes color fully transparent; a set to 255 makes color\n        fully opaque.\n\n        @param a  alpha component of color\n    */\n    void setAlpha(U8CPU a);\n\n    /** Sets color used when drawing solid fills. The color components range from 0 to 255.\n        The color is unpremultiplied; alpha sets the transparency independent of RGB.\n\n        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)\n        @param r  amount of red, from no red (0) to full red (255)\n        @param g  amount of green, from no green (0) to full green (255)\n        @param b  amount of blue, from no blue (0) to full blue (255)\n    */\n    void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);\n\n    /** Returns the thickness of the pen used by SkPaint to\n        outline the shape.\n\n        @return  zero for hairline, greater than zero for pen thickness\n    */\n    SkScalar getStrokeWidth() const { return fWidth; }\n\n    /** Sets the thickness of the pen used by the paint to\n        outline the shape.\n        Has no effect if width is less than zero.\n\n        @param width  zero thickness for hairline; greater than zero for pen thickness\n    */\n    void setStrokeWidth(SkScalar width);\n\n    /** The limit at which a sharp corner is drawn beveled.\n\n        @return  zero and greater miter limit\n    */\n    SkScalar getStrokeMiter() const { return fMiterLimit; }\n\n    /** The limit at which a sharp corner is drawn beveled.\n        Valid values are zero and greater.\n        Has no effect if miter is less than zero.\n\n        @param miter  zero and greater miter limit\n    */\n    void setStrokeMiter(SkScalar miter);\n\n    /** \\enum SkPaint::Cap\n        Cap draws at the beginning and end of an open path contour.\n    */\n    enum Cap {\n        kButt_Cap,                  //!< no stroke extension\n        kRound_Cap,                 //!< adds circle\n        kSquare_Cap,                //!< adds square\n        kLast_Cap    = kSquare_Cap, //!< largest Cap value\n        kDefault_Cap = kButt_Cap,   //!< equivalent to kButt_Cap\n    };\n\n    /** May be used to verify that SkPaint::Cap is a legal value.\n    */\n    static constexpr int kCapCount = kLast_Cap + 1;\n\n    /** \\enum SkPaint::Join\n        Join specifies how corners are drawn when a shape is stroked. Join\n        affects the four corners of a stroked rectangle, and the connected segments in a\n        stroked path.\n\n        Choose miter join to draw sharp corners. Choose round join to draw a circle with a\n        radius equal to the stroke width on top of the corner. Choose bevel join to minimally\n        connect the thick strokes.\n\n        The fill path constructed to describe the stroked path respects the join setting but may\n        not contain the actual join. For instance, a fill path constructed with round joins does\n        not necessarily include circles at each connected segment.\n    */\n    enum Join {\n        kMiter_Join,                 //!< extends to miter limit\n        kRound_Join,                 //!< adds circle\n        kBevel_Join,                 //!< connects outside edges\n        kLast_Join    = kBevel_Join, //!< equivalent to the largest value for Join\n        kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join\n    };\n\n    /** May be used to verify that SkPaint::Join is a legal value.\n    */\n    static constexpr int kJoinCount = kLast_Join + 1;\n\n    /** The geometry drawn at the beginning and end of strokes.\n\n        @return  one of: kButt_Cap, kRound_Cap, kSquare_Cap\n    */\n    Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }\n\n    /** The geometry drawn at the beginning and end of strokes.\n\n        @param cap  one of: kButt_Cap, kRound_Cap, kSquare_Cap;\n                    has no effect if cap is not valid\n    */\n    void setStrokeCap(Cap cap);\n\n    /** The geometry drawn at the corners of strokes.\n\n        @return  one of: kMiter_Join, kRound_Join, kBevel_Join\n    */\n    Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }\n\n    /** The geometry drawn at the corners of strokes.\n\n        @param join  one of: kMiter_Join, kRound_Join, kBevel_Join;\n                     otherwise, has no effect\n    */\n    void setStrokeJoin(Join join);\n\n    /** The filled equivalent of the stroked path.\n\n        @param src       SkPath read to create a filled version\n        @param dst       resulting SkPath; may be the same as src, but may not be nullptr\n        @param cullRect  optional limit passed to SkPathEffect\n        @param resScale  if > 1, increase precision, else if (0 < res < 1) reduce precision\n                         to favor speed and size\n        @return          true if the path represents style fill, or false if it represents hairline\n    */\n    bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,\n                     SkScalar resScale = 1) const;\n\n    /** The filled equivalent of the stroked path.\n\n        Replaces dst with the src path modified by SkPathEffect and style stroke.\n        SkPathEffect, if any, is not culled. stroke width is created with default precision.\n\n        @param src  SkPath read to create a filled version\n        @param dst  resulting SkPath dst may be the same as src, but may not be nullptr\n        @return     true if the path represents style fill, or false if it represents hairline\n    */\n    bool getFillPath(const SkPath& src, SkPath* dst) const {\n        return this->getFillPath(src, dst, nullptr, 1);\n    }\n\n    /** Optional colors used when filling a path, such as a gradient.\n\n        Does not alter SkShader SkRefCnt.\n\n        @return  SkShader if previously set, nullptr otherwise\n    */\n    SkShader* getShader() const { return fShader.get(); }\n\n    /** Optional colors used when filling a path, such as a gradient.\n\n        Increases SkShader SkRefCnt by one.\n\n        @return  SkShader if previously set, nullptr otherwise\n    */\n    sk_sp<SkShader> refShader() const;\n\n    /** Optional colors used when filling a path, such as a gradient.\n\n        Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.\n        Increments shader SkRefCnt by one.\n\n        @param shader  how geometry is filled with color; if nullptr, color is used instead\n    */\n    void setShader(sk_sp<SkShader> shader);\n\n    /** Returns SkColorFilter if set, or nullptr.\n        Does not alter SkColorFilter SkRefCnt.\n\n        @return  SkColorFilter if previously set, nullptr otherwise\n    */\n    SkColorFilter* getColorFilter() const { return fColorFilter.get(); }\n\n    /** Returns SkColorFilter if set, or nullptr.\n        Increases SkColorFilter SkRefCnt by one.\n\n        @return  SkColorFilter if set, or nullptr\n    */\n    sk_sp<SkColorFilter> refColorFilter() const;\n\n    /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous\n        SkColorFilter. Pass nullptr to clear SkColorFilter.\n\n        Increments filter SkRefCnt by one.\n\n        @param colorFilter  SkColorFilter to apply to subsequent draw\n    */\n    void setColorFilter(sk_sp<SkColorFilter> colorFilter);\n\n    /** Returns SkBlendMode.\n        By default, returns SkBlendMode::kSrcOver.\n\n        @return  mode used to combine source color with destination color\n    */\n    SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }\n\n    /** Returns true if SkBlendMode is SkBlendMode::kSrcOver, the default.\n\n        @return  true if SkBlendMode is SkBlendMode::kSrcOver\n    */\n    bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }\n\n    /** Sets SkBlendMode to mode.\n        Does not check for valid input.\n\n        @param mode  SkBlendMode used to combine source color and destination\n    */\n    void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }\n\n    /** Returns SkPathEffect if set, or nullptr.\n        Does not alter SkPathEffect SkRefCnt.\n\n        @return  SkPathEffect if previously set, nullptr otherwise\n    */\n    SkPathEffect* getPathEffect() const { return fPathEffect.get(); }\n\n    /** Returns SkPathEffect if set, or nullptr.\n        Increases SkPathEffect SkRefCnt by one.\n\n        @return  SkPathEffect if previously set, nullptr otherwise\n    */\n    sk_sp<SkPathEffect> refPathEffect() const;\n\n    /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous\n        SkPathEffect. Pass nullptr to leave the path geometry unaltered.\n\n        Increments pathEffect SkRefCnt by one.\n\n        @param pathEffect  replace SkPath with a modification when drawn\n    */\n    void setPathEffect(sk_sp<SkPathEffect> pathEffect);\n\n    /** Returns SkMaskFilter if set, or nullptr.\n        Does not alter SkMaskFilter SkRefCnt.\n\n        @return  SkMaskFilter if previously set, nullptr otherwise\n    */\n    SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }\n\n    /** Returns SkMaskFilter if set, or nullptr.\n\n        Increases SkMaskFilter SkRefCnt by one.\n\n        @return  SkMaskFilter if previously set, nullptr otherwise\n    */\n    sk_sp<SkMaskFilter> refMaskFilter() const;\n\n    /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous\n        SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on\n        mask alpha unaltered.\n\n        Increments maskFilter SkRefCnt by one.\n\n        @param maskFilter  modifies clipping mask generated from drawn geometry\n    */\n    void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);\n\n    /** Returns SkTypeface if set, or nullptr.\n        Increments SkTypeface SkRefCnt by one.\n\n        @return  SkTypeface if previously set, nullptr otherwise\n    */\n    SkTypeface* getTypeface() const { return fTypeface.get(); }\n\n    /** Increases SkTypeface SkRefCnt by one.\n\n        @return  SkTypeface if previously set, nullptr otherwise\n    */\n    sk_sp<SkTypeface> refTypeface() const;\n\n    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.\n        Pass nullptr to clear SkTypeface and use the default typeface. Increments\n        typeface SkRefCnt by one.\n\n        @param typeface  font and style used to draw text\n    */\n    void setTypeface(sk_sp<SkTypeface> typeface);\n\n    /** Returns SkImageFilter if set, or nullptr.\n        Does not alter SkImageFilter SkRefCnt.\n\n        @return  SkImageFilter if previously set, nullptr otherwise\n    */\n    SkImageFilter* getImageFilter() const { return fImageFilter.get(); }\n\n    /** Returns SkImageFilter if set, or nullptr.\n        Increases SkImageFilter SkRefCnt by one.\n\n        @return  SkImageFilter if previously set, nullptr otherwise\n    */\n    sk_sp<SkImageFilter> refImageFilter() const;\n\n    /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous\n        SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect\n        on drawing.\n\n        Increments imageFilter SkRefCnt by one.\n\n        @param imageFilter  how SkImage is sampled when transformed\n    */\n    void setImageFilter(sk_sp<SkImageFilter> imageFilter);\n\n    /** Returns SkDrawLooper if set, or nullptr.\n        Does not alter SkDrawLooper SkRefCnt.\n\n        @return  SkDrawLooper if previously set, nullptr otherwise\n    */\n    SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }\n\n    /** Returns SkDrawLooper if set, or nullptr.\n        Increases SkDrawLooper SkRefCnt by one.\n\n        @return  SkDrawLooper if previously set, nullptr otherwise\n    */\n    sk_sp<SkDrawLooper> refDrawLooper() const;\n\n    /** Deprecated.\n        (see skbug.com/6259)\n    */\n    SkDrawLooper* getLooper() const { return fDrawLooper.get(); }\n\n    /** Sets SkDrawLooper to drawLooper, decreasing SkRefCnt of the previous\n        drawLooper.  Pass nullptr to clear SkDrawLooper and leave SkDrawLooper effect on\n        drawing unaltered.\n\n        Increments drawLooper SkRefCnt by one.\n\n        @param drawLooper  iterates through drawing one or more time, altering SkPaint\n    */\n    void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);\n\n    /** Deprecated.\n        (see skbug.com/6259)\n    */\n    void setLooper(sk_sp<SkDrawLooper> drawLooper);\n\n    /** \\enum SkPaint::Align\n        Align adjusts the text relative to the text position.\n        Align affects glyphs drawn with: SkCanvas::drawText, SkCanvas::drawPosText,\n        SkCanvas::drawPosTextH, SkCanvas::drawTextOnPath,\n        SkCanvas::drawTextOnPathHV, SkCanvas::drawTextRSXform, SkCanvas::drawTextBlob,\n        and SkCanvas::drawString;\n        as well as calls that place text glyphs like getTextWidths() and getTextPath().\n\n        The text position is set by the font for both horizontal and vertical text.\n        Typically, for horizontal text, the position is to the left side of the glyph on the\n        base line; and for vertical text, the position is the horizontal center of the glyph\n        at the caps height.\n\n        Align adjusts the glyph position to center it or move it to abut the position\n        using the metrics returned by the font.\n\n        Align defaults to kLeft_Align.\n    */\n    enum Align {\n        kLeft_Align,   //!< positions glyph by computed font offset\n        kCenter_Align, //!< centers line of glyphs by its width or height\n        kRight_Align,  //!< moves lines of glyphs by its width or height\n    };\n\n    /** May be used to verify that align is a legal value.\n    */\n    static constexpr int kAlignCount = 3;\n\n    /** Returns SkPaint::Align.\n        Returns kLeft_Align if SkPaint::Align has not been set.\n\n        @return  text placement relative to position\n    */\n    Align   getTextAlign() const { return (Align)fBitfields.fTextAlign; }\n\n    /** Sets SkPaint::Align to align.\n        Has no effect if align is an invalid value.\n\n        @param align  text placement relative to position\n    */\n    void    setTextAlign(Align align);\n\n    /** Returns text size in points.\n\n        @return  typographic height of text\n    */\n    SkScalar getTextSize() const { return fTextSize; }\n\n    /** Sets text size in points.\n        Has no effect if textSize is not greater than or equal to zero.\n\n        @param textSize  typographic height of text\n    */\n    void setTextSize(SkScalar textSize);\n\n    /** Returns text scale x.\n        Default value is 1.\n\n        @return  text horizontal scale\n    */\n    SkScalar getTextScaleX() const { return fTextScaleX; }\n\n    /** Sets text scale x.\n        Default value is 1.\n\n        @param scaleX  text horizontal scale\n    */\n    void setTextScaleX(SkScalar scaleX);\n\n    /** Returns text skew x.\n        Default value is zero.\n\n        @return  additional shear in x-axis relative to y-axis\n    */\n    SkScalar getTextSkewX() const { return fTextSkewX; }\n\n    /** Sets text skew x.\n        Default value is zero.\n\n        @param skewX  additional shear in x-axis relative to y-axis\n    */\n    void setTextSkewX(SkScalar skewX);\n\n    /** \\enum SkPaint::TextEncoding\n        TextEncoding determines whether text specifies character codes and their encoded\n        size, or glyph indices. Characters are encoded as specified by the Unicode standard.\n\n        Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.\n        All character code formats are able to represent all of Unicode, differing only\n        in the total storage required.\n\n        UTF-8 (RFC 3629) encodes each character as one or more 8-bit bytes.\n\n        UTF-16 (RFC 2781) encodes each character as one or two 16-bit words.\n\n        UTF-32 encodes each character as one 32-bit word.\n\n        font manager uses font data to convert character code points into glyph indices.\n        A glyph index is a 16-bit word.\n\n        TextEncoding is set to kUTF8_TextEncoding by default.\n    */\n    enum TextEncoding {\n        kUTF8_TextEncoding,    //!< uses bytes to represent UTF-8 or ASCII\n        kUTF16_TextEncoding,   //!< uses two byte words to represent most of Unicode\n        kUTF32_TextEncoding,   //!< uses four byte words to represent all of Unicode\n        kGlyphID_TextEncoding, //!< uses two byte words to represent glyph indices\n    };\n\n    /** Returns SkPaint::TextEncoding.\n        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.\n\n        @return  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or\n                 kGlyphID_TextEncoding\n    */\n    TextEncoding getTextEncoding() const {\n      return (TextEncoding)fBitfields.fTextEncoding;\n    }\n\n    /** Sets SkPaint::TextEncoding to encoding.\n        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.\n        Invalid values for encoding are ignored.\n\n        @param encoding  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or\n                         kGlyphID_TextEncoding\n    */\n    void setTextEncoding(TextEncoding encoding);\n\n    /** \\struct SkPaint::FontMetrics\n        FontMetrics is filled out by getFontMetrics(). FontMetrics contents reflect the values\n        computed by font manager using SkTypeface. Values are set to zero if they are\n        not available.\n\n        All vertical values relative to the baseline are given y-down. As such, zero is on the\n        baseline, negative values are above the baseline, and positive values are below the\n        baseline.\n\n        fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values\n        are valid, since their value may be zero.\n\n        fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values\n        are valid, since their value may be zero.\n    */\n    struct FontMetrics {\n\n        /** \\enum SkPaint::FontMetrics::FontMetricsFlags\n            FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;\n            the underline or strikeout metric may be valid and zero.\n            Fonts with embedded bitmaps may not have valid underline or strikeout metrics.\n        */\n        enum FontMetricsFlags {\n            kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid\n            kUnderlinePositionIsValid_Flag  = 1 << 1, //!< set if fUnderlinePosition is valid\n            kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid\n            kStrikeoutPositionIsValid_Flag  = 1 << 3, //!< set if fStrikeoutPosition is valid\n        };\n\n        uint32_t fFlags;              //!< is set to FontMetricsFlags when metrics are valid\n        SkScalar fTop;                //!< extent above baseline\n        SkScalar fAscent;             //!< distance to reserve above baseline\n        SkScalar fDescent;            //!< distance to reserve below baseline\n        SkScalar fBottom;             //!< extent below baseline\n        SkScalar fLeading;            //!< distance to add between lines\n        SkScalar fAvgCharWidth;       //!< average character width\n        SkScalar fMaxCharWidth;       //!< maximum character width\n        SkScalar fXMin;               //!< minimum x\n        SkScalar fXMax;               //!< maximum x\n        SkScalar fXHeight;            //!< height of lower-case 'x'\n        SkScalar fCapHeight;          //!< height of an upper-case letter\n        SkScalar fUnderlineThickness; //!< underline thickness\n        SkScalar fUnderlinePosition;  //!< underline position relative to baseline\n        SkScalar fStrikeoutThickness; //!< strikeout thickness\n        SkScalar fStrikeoutPosition;  //!< strikeout position relative to baseline\n\n        /** If SkPaint::FontMetrics has a valid underline thickness, return true, and set\n            thickness to that value. If the underline thickness is not valid,\n            return false, and ignore thickness.\n\n            @param thickness  storage for underline width\n            @return           true if font specifies underline width\n        */\n        bool hasUnderlineThickness(SkScalar* thickness) const {\n            if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {\n                *thickness = fUnderlineThickness;\n                return true;\n            }\n            return false;\n        }\n\n        /** If SkPaint::FontMetrics has a valid underline position, return true, and set\n            position to that value. If the underline position is not valid,\n            return false, and ignore position.\n\n            @param position  storage for underline position\n            @return          true if font specifies underline position\n        */\n        bool hasUnderlinePosition(SkScalar* position) const {\n            if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {\n                *position = fUnderlinePosition;\n                return true;\n            }\n            return false;\n        }\n\n        /** If SkPaint::FontMetrics has a valid strikeout thickness, return true, and set\n            thickness to that value. If the underline thickness is not valid,\n            return false, and ignore thickness.\n\n            @param thickness  storage for strikeout width\n            @return           true if font specifies strikeout width\n        */\n        bool hasStrikeoutThickness(SkScalar* thickness) const {\n            if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {\n                *thickness = fStrikeoutThickness;\n                return true;\n            }\n            return false;\n        }\n\n        /** If SkPaint::FontMetrics has a valid strikeout position, return true, and set\n            position to that value. If the underline position is not valid,\n            return false, and ignore position.\n\n            @param position  storage for strikeout position\n            @return          true if font specifies strikeout position\n        */\n        bool hasStrikeoutPosition(SkScalar* position) const {\n            if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {\n                *position = fStrikeoutPosition;\n                return true;\n            }\n            return false;\n        }\n\n    };\n\n    /** Returns SkPaint::FontMetrics associated with SkTypeface.\n        The return value is the recommended spacing between lines: the sum of metrics\n        descent, ascent, and leading.\n        If metrics is not nullptr, SkPaint::FontMetrics is copied to metrics.\n        Results are scaled by text size but does not take into account\n        dimensions required by text scale x, text skew x, fake bold,\n        style stroke, and SkPathEffect.\n        Results can be additionally scaled by scale; a scale of zero\n        is ignored.\n\n        @param metrics  storage for SkPaint::FontMetrics from SkTypeface; may be nullptr\n        @param scale    additional multiplier for returned values\n        @return         recommended spacing between lines\n    */\n    SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;\n\n    /** Returns the recommended spacing between lines: the sum of metrics\n        descent, ascent, and leading.\n        Result is scaled by text size but does not take into account\n        dimensions required by stroking and SkPathEffect.\n        Returns the same result as getFontMetrics().\n\n        @return  recommended spacing between lines\n    */\n    SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr, 0); }\n\n    /** Converts text into glyph indices.\n        Returns the number of glyph indices represented by text.\n        SkPaint::TextEncoding specifies how text represents characters or glyphs.\n        glyphs may be nullptr, to compute the glyph count.\n\n        Does not check text for valid character codes or valid glyph indices.\n\n        If byteLength equals zero, returns zero.\n        If byteLength includes a partial character, the partial character is ignored.\n\n        If SkPaint::TextEncoding is kUTF8_TextEncoding and\n        text contains an invalid UTF-8 sequence, zero is returned.\n\n        @param text        character storage encoded with SkPaint::TextEncoding\n        @param byteLength  length of character storage in bytes\n        @param glyphs      storage for glyph indices; may be nullptr\n        @return            number of glyphs represented by text of length byteLength\n    */\n    int textToGlyphs(const void* text, size_t byteLength,\n                     SkGlyphID glyphs[]) const;\n\n    /** Returns true if all text corresponds to a non-zero glyph index.\n        Returns false if any characters in text are not supported in\n        SkTypeface.\n\n        If SkPaint::TextEncoding is kGlyphID_TextEncoding,\n        returns true if all glyph indices in text are non-zero;\n        does not check to see if text contains valid glyph indices for SkTypeface.\n\n        Returns true if byteLength is zero.\n\n        @param text        array of characters or glyphs\n        @param byteLength  number of bytes in text array\n        @return            true if all text corresponds to a non-zero glyph index\n    */\n    bool containsText(const void* text, size_t byteLength) const;\n\n    /** Converts glyphs into text if possible.\n        Glyph values without direct Unicode equivalents are mapped to zero.\n        Uses the SkTypeface, but is unaffected\n        by SkPaint::TextEncoding; the text values returned are equivalent to kUTF32_TextEncoding.\n\n        Only supported on platforms that use FreeType as the font engine.\n\n        @param glyphs  array of indices into font\n        @param count   length of glyph array\n        @param text    storage for character codes, one per glyph\n    */\n    void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;\n\n    /** Returns the number of glyphs in text.\n        Uses SkPaint::TextEncoding to count the glyphs.\n        Returns the same result as textToGlyphs().\n\n        @param text        character storage encoded with SkPaint::TextEncoding\n        @param byteLength  length of character storage in bytes\n        @return            number of glyphs represented by text of length byteLength\n    */\n    int countText(const void* text, size_t byteLength) const;\n\n    /** Returns the advance width of text if kVerticalText_Flag is clear,\n        and the height of text if kVerticalText_Flag is set.\n        The advance is the normal distance to move before drawing additional text.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,\n        and text size, text scale x, text skew x, stroke width, and\n        SkPathEffect to scale the metrics and bounds.\n        Returns the bounding box of text if bounds is not nullptr.\n        The bounding box is computed as if the text was drawn at the origin.\n\n        @param text    character codes or glyph indices to be measured\n        @param length  number of bytes of text to measure\n        @param bounds  returns bounding box relative to (0, 0) if not nullptr\n        @return        advance width or height\n    */\n    SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;\n\n    /** Returns the advance width of text if kVerticalText_Flag is clear,\n        and the height of text if kVerticalText_Flag is set.\n        The advance is the normal distance to move before drawing additional text.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,\n        and text size to scale the metrics.\n        Does not scale the advance or bounds by fake bold or SkPathEffect.\n\n        @param text    character codes or glyph indices to be measured\n        @param length  number of bytes of text to measure\n        @return        advance width or height\n    */\n    SkScalar measureText(const void* text, size_t length) const {\n        return this->measureText(text, length, nullptr);\n    }\n\n    /** Returns the bytes of text that fit within maxWidth.\n        If kVerticalText_Flag is clear, the text fragment fits if its advance width is less than or\n        equal to maxWidth.\n        If kVerticalText_Flag is set, the text fragment fits if its advance height is less than or\n        equal to maxWidth.\n        Measures only while the advance is less than or equal to maxWidth.\n        Returns the advance or the text fragment in measuredWidth if it not nullptr.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,\n        and text size to scale the metrics.\n        Does not scale the advance or bounds by fake bold or SkPathEffect.\n\n        @param text           character codes or glyph indices to be measured\n        @param length         number of bytes of text to measure\n        @param maxWidth       advance limit; text is measured while advance is less than maxWidth\n        @param measuredWidth  returns the width of the text less than or equal to maxWidth\n        @return               bytes of text that fit, always less than or equal to length\n    */\n    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,\n                      SkScalar* measuredWidth = nullptr) const;\n\n    /** Retrieves the advance and bounds for each glyph in text, and returns\n        the glyph count in text.\n        Both widths and bounds may be nullptr.\n        If widths is not nullptr, widths must be an array of glyph count entries.\n        if bounds is not nullptr, bounds must be an array of glyph count entries.\n        If kVerticalText_Flag is clear, widths returns the horizontal advance.\n        If kVerticalText_Flag is set, widths returns the vertical advance.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,\n        and text size to scale the widths and bounds.\n        Does not scale the advance by fake bold or SkPathEffect.\n        Does include fake bold and SkPathEffect in the bounds.\n\n        @param text        character codes or glyph indices to be measured\n        @param byteLength  number of bytes of text to measure\n        @param widths      returns text advances for each glyph; may be nullptr\n        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr\n        @return            glyph count in text\n    */\n    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],\n                      SkRect bounds[] = nullptr) const;\n\n    /** Returns the geometry as SkPath equivalent to the drawn text.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        All of the glyph paths are stored in path.\n        Uses x, y, and SkPaint::Align to position path.\n\n        @param text    character codes or glyph indices\n        @param length  number of bytes of text\n        @param x       x-coordinate of the origin of the text\n        @param y       y-coordinate of the origin of the text\n        @param path    geometry of the glyphs\n    */\n    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,\n                     SkPath* path) const;\n\n    /** Returns the geometry as SkPath equivalent to the drawn text.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        All of the glyph paths are stored in path.\n        Uses pos array and SkPaint::Align to position path.\n        pos contains a position for each glyph.\n\n        @param text    character codes or glyph indices\n        @param length  number of bytes of text\n        @param pos     positions of each glyph\n        @param path    geometry of the glyphs\n    */\n    void getPosTextPath(const void* text, size_t length,\n                        const SkPoint pos[], SkPath* path) const;\n\n    /** Returns the number of intervals that intersect bounds.\n        bounds describes a pair of lines parallel to the text advance.\n        The return count is zero or a multiple of two, and is at most twice the number of glyphs in\n        the string.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        Uses x, y, and SkPaint::Align to position intervals.\n\n        Pass nullptr for intervals to determine the size of the interval array.\n\n        intervals are cached to improve performance for multiple calls.\n\n        @param text       character codes or glyph indices\n        @param length     number of bytes of text\n        @param x          x-coordinate of the origin of the text\n        @param y          y-coordinate of the origin of the text\n        @param bounds     lower and upper line parallel to the advance\n        @param intervals  returned intersections; may be nullptr\n        @return           number of intersections; may be zero\n    */\n    int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,\n                          const SkScalar bounds[2], SkScalar* intervals) const;\n\n    /** Returns the number of intervals that intersect bounds.\n        bounds describes a pair of lines parallel to the text advance.\n        The return count is zero or a multiple of two, and is at most twice the number of glyphs in\n        the string.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        Uses pos array and SkPaint::Align to position intervals.\n\n        Pass nullptr for intervals to determine the size of the interval array.\n\n        intervals are cached to improve performance for multiple calls.\n\n        @param text       character codes or glyph indices\n        @param length     number of bytes of text\n        @param pos        positions of each glyph\n        @param bounds     lower and upper line parallel to the advance\n        @param intervals  returned intersections; may be nullptr\n        @return           number of intersections; may be zero\n    */\n    int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],\n                             const SkScalar bounds[2], SkScalar* intervals) const;\n\n    /** Returns the number of intervals that intersect bounds.\n        bounds describes a pair of lines parallel to the text advance.\n        The return count is zero or a multiple of two, and is at most twice the number of glyphs in\n        the string.\n        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        Uses xpos array, constY, and SkPaint::Align to position intervals.\n\n        Pass nullptr for intervals to determine the size of the interval array.\n\n        intervals are cached to improve performance for multiple calls.\n\n        @param text       character codes or glyph indices\n        @param length     number of bytes of text\n        @param xpos       positions of each glyph in x\n        @param constY     position of each glyph in y\n        @param bounds     lower and upper line parallel to the advance\n        @param intervals  returned intersections; may be nullptr\n        @return           number of intersections; may be zero\n    */\n    int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],\n                              SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;\n\n    /** Returns the number of intervals that intersect bounds.\n        bounds describes a pair of lines parallel to the text advance.\n        The return count is zero or a multiple of two, and is at most twice the number of glyphs in\n        the string.\n        Uses SkTypeface to get the glyph paths,\n        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.\n        Uses run array and SkPaint::Align to position intervals.\n\n        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.\n\n        Pass nullptr for intervals to determine the size of the interval array.\n\n        intervals are cached to improve performance for multiple calls.\n\n        @param blob       glyphs, positions, and text paint attributes\n        @param bounds     lower and upper line parallel to the advance\n        @param intervals  returned intersections; may be nullptr\n        @return           number of intersections; may be zero\n    */\n    int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],\n                              SkScalar* intervals) const;\n\n    /** Returns the union of bounds of all glyphs.\n        Returned dimensions are computed by font manager from font data,\n        ignoring SkPaint::Hinting. Includes text size, text scale x,\n        and text skew x, but not fake bold or SkPathEffect.\n\n        If text size is large, text scale x is one, and text skew x is zero,\n        returns the same bounds as SkPaint::FontMetrics { FontMetrics::fXMin,\n        FontMetrics::fTop, FontMetrics::fXMax, FontMetrics::fBottom }.\n\n        @return  union of bounds of all glyphs\n    */\n    SkRect getFontBounds() const;\n\n    /** Returns true if SkPaint prevents all drawing;\n        otherwise, the SkPaint may or may not allow drawing.\n\n        Returns true if, for example, SkBlendMode combined with alpha computes a\n        new alpha of zero.\n\n        @return  true if SkPaint prevents all drawing\n    */\n    bool nothingToDraw() const;\n\n    /**     (to be made private)\n        Returns true if SkPaint does not include elements requiring extensive computation\n        to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect\n        always returns false.\n\n        @return  true if SkPaint allows for fast computation of bounds\n    */\n    bool canComputeFastBounds() const;\n\n    /**     (to be made private)\n        Only call this if canComputeFastBounds() returned true. This takes a\n        raw rectangle (the raw bounds of a shape), and adjusts it for stylistic\n        effects in the paint (e.g. stroking). If needed, it uses the storage\n        parameter. It returns the adjusted bounds that can then be used\n        for SkCanvas::quickReject tests.\n\n        The returned SkRect will either be orig or storage, thus the caller\n        should not rely on storage being set to the result, but should always\n        use the returned value. It is legal for orig and storage to be the same\n        SkRect.\n            For example:\n            if (!path.isInverseFillType() && paint.canComputeFastBounds()) {\n                SkRect storage;\n                if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {\n                    return; // do not draw the path\n                }\n            }\n            // draw the path\n\n        @param orig     geometry modified by SkPaint when drawn\n        @param storage  computed bounds of geometry; may not be nullptr\n        @return         fast computed bounds\n    */\n    const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {\n        // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.\n        SkASSERT(orig.isSorted());\n        SkPaint::Style style = this->getStyle();\n        // ultra fast-case: filling with no effects that affect geometry\n        if (kFill_Style == style) {\n            uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());\n            effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());\n            effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());\n            effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());\n            if (!effects) {\n                return orig;\n            }\n        }\n\n        return this->doComputeFastBounds(orig, storage, style);\n    }\n\n    /**     (to be made private)\n\n        @param orig     geometry modified by SkPaint when drawn\n        @param storage  computed bounds of geometry\n        @return         fast computed bounds\n    */\n    const SkRect& computeFastStrokeBounds(const SkRect& orig,\n                                          SkRect* storage) const {\n        return this->doComputeFastBounds(orig, storage, kStroke_Style);\n    }\n\n    /**     (to be made private)\n        Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to\n        account for additional width required by stroking orig, without\n        altering SkPaint::Style set to fill.\n\n        @param orig     geometry modified by SkPaint when drawn\n        @param storage  computed bounds of geometry\n        @param style    overrides SkPaint::Style\n        @return         fast computed bounds\n    */\n    const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,\n                                      Style style) const;\n\n    /** Creates string representation of SkPaint. The representation is read by\n        internal debugging tools.\n\n        @param str  storage for string representation of SkPaint\n    */\n    void toString(SkString* str) const;\n\nprivate:\n    typedef const SkGlyph& (*GlyphCacheProc)(SkGlyphCache*, const char**);\n\n    sk_sp<SkTypeface>     fTypeface;\n    sk_sp<SkPathEffect>   fPathEffect;\n    sk_sp<SkShader>       fShader;\n    sk_sp<SkMaskFilter>   fMaskFilter;\n    sk_sp<SkColorFilter>  fColorFilter;\n    sk_sp<SkDrawLooper>   fDrawLooper;\n    sk_sp<SkImageFilter>  fImageFilter;\n\n    SkScalar        fTextSize;\n    SkScalar        fTextScaleX;\n    SkScalar        fTextSkewX;\n    SkColor         fColor;\n    SkScalar        fWidth;\n    SkScalar        fMiterLimit;\n    uint32_t        fBlendMode; // just need 5-6 bits\n    union {\n        struct {\n            // all of these bitfields should add up to 32\n            unsigned        fFlags : 16;\n            unsigned        fTextAlign : 2;\n            unsigned        fCapType : 2;\n            unsigned        fJoinType : 2;\n            unsigned        fStyle : 2;\n            unsigned        fTextEncoding : 2;  // 3 values\n            unsigned        fHinting : 2;\n            unsigned        fFilterQuality : 2;\n            //unsigned      fFreeBits : 2;\n        } fBitfields;\n        uint32_t fBitfieldsUInt;\n    };\n\n    static GlyphCacheProc GetGlyphCacheProc(TextEncoding encoding,\n                                            bool needFullMetrics);\n\n    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,\n                          int* count, SkRect* bounds) const;\n\n    /*\n     * The luminance color is used to determine which Gamma Canonical color to map to.  This is\n     * really only used by backends which want to cache glyph masks, and need some way to know if\n     * they need to generate new masks based off a given color.\n     */\n    SkColor computeLuminanceColor() const;\n\n    /*  This is the size we use when we ask for a glyph's path. We then\n     *  post-transform it as we draw to match the request.\n     *  This is done to try to re-use cache entries for the path.\n     *\n     *  This value is somewhat arbitrary. In theory, it could be 1, since\n     *  we store paths as floats. However, we get the path from the font\n     *  scaler, and it may represent its paths as fixed-point (or 26.6),\n     *  so we shouldn't ask for something too big (might overflow 16.16)\n     *  or too small (underflow 26.6).\n     *\n     *  This value could track kMaxSizeForGlyphCache, assuming the above\n     *  constraints, but since we ask for unhinted paths, the two values\n     *  need not match per-se.\n     */\n    static constexpr int kCanonicalTextSizeForPaths  = 64;\n\n    static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);\n\n    // Set flags/hinting/textSize up to use for drawing text as paths.\n    // Returns scale factor to restore the original textSize, since will will\n    // have change it to kCanonicalTextSizeForPaths.\n    SkScalar setupForAsPaths();\n\n    static SkScalar MaxCacheSize2(SkScalar maxLimit);\n\n    friend class GrAtlasTextBlob;\n    friend class GrTextContext;\n    friend class GrGLPathRendering;\n    friend class GrPathRendering;\n    friend class GrTextUtils;\n    friend class SkAutoGlyphCacheNoGamma;\n    friend class SkCanonicalizePaint;\n    friend class SkCanvas;\n    friend class SkDraw;\n    friend class SkPaintPriv;\n    friend class SkPDFDevice;\n    friend class SkScalerContext;  // for computeLuminanceColor()\n    friend class SkTextBaseIter;\n    friend class SkTextBlobCacheDiffCanvas;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPath.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPath_DEFINED\n#define SkPath_DEFINED\n\n#include \"SkMatrix.h\"\n#include \"../private/SkPathRef.h\"\n\nclass SkAutoPathBoundsUpdate;\nclass SkData;\nclass SkRRect;\nclass SkWStream;\n\n/** \\class SkPath\n    SkPath contain geometry. SkPath may be empty, or contain one or more verbs that\n    outline a figure. SkPath always starts with a move verb to a Cartesian_Coordinate,\n    and may be followed by additional verbs that add lines or curves.\n    Adding a close verb makes the geometry into a continuous loop, a closed contour.\n    SkPath may contain any number of contours, each beginning with a move verb.\n\n    SkPath contours may contain only a move verb, or may also contain lines,\n    quadratic beziers, conics, and cubic beziers. SkPath contours may be open or\n    closed.\n\n    When used to draw a filled area, SkPath describes whether the fill is inside or\n    outside the geometry. SkPath also describes the winding rule used to fill\n    overlapping contours.\n\n    Internally, SkPath lazily computes metrics likes bounds and convexity. Call\n    SkPath::updateBoundsCache to make SkPath thread safe.\n*/\nclass SK_API SkPath {\npublic:\n\n    /** \\enum SkPath::Direction\n        Direction describes whether contour is clockwise or counterclockwise.\n        When SkPath contains multiple overlapping contours, Direction together with\n        FillType determines whether overlaps are filled or form holes.\n\n        Direction also determines how contour is measured. For instance, dashing\n        measures along SkPath to determine where to start and stop stroke; Direction\n        will change dashed results as it steps clockwise or counterclockwise.\n\n        Closed contours like SkRect, SkRRect, circle, and oval added with\n        kCW_Direction travel clockwise; the same added with kCCW_Direction\n        travel counterclockwise.\n    */\n    enum Direction {\n        kCW_Direction,  //!< contour travels clockwise\n        kCCW_Direction, //!< contour travels counterclockwise\n    };\n\n    /** By default, SkPath has no verbs, no SkPoint, and no weights.\n        SkPath::FillType is set to kWinding_FillType.\n\n        @return  empty SkPath\n    */\n    SkPath();\n\n    /** Copy constructor makes two paths identical by value. Internally, path and\n        the returned result share pointer values. The underlying verb array, SkPoint array\n        and weights are copied when modified.\n\n        Creating a SkPath copy is very efficient and never allocates memory.\n        SkPath are always copied by value from the interface; the underlying shared\n        pointers are not exposed.\n\n        @param path  SkPath to copy by value\n        @return      copy of SkPath\n    */\n    SkPath(const SkPath& path);\n\n    /** Releases ownership of any shared data and deletes data if SkPath is sole owner.\n    */\n    ~SkPath();\n\n    /** SkPath assignment makes two paths identical by value. Internally, assignment\n        shares pointer values. The underlying verb array, SkPoint array and weights\n        are copied when modified.\n\n        Copying SkPath by assignment is very efficient and never allocates memory.\n        SkPath are always copied by value from the interface; the underlying shared\n        pointers are not exposed.\n\n        @param path  verb array, SkPoint array, weights, and SkPath::FillType to copy\n        @return      SkPath copied by value\n    */\n    SkPath& operator=(const SkPath& path);\n\n    /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights\n        are equivalent.\n\n        @param a  SkPath to compare\n        @param b  SkPath to compare\n        @return   true if SkPath pair are equivalent\n    */\n    friend SK_API bool operator==(const SkPath& a, const SkPath& b);\n\n    /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights\n        are not equivalent.\n\n        @param a  SkPath to compare\n        @param b  SkPath to compare\n        @return   true if SkPath pair are not equivalent\n    */\n    friend bool operator!=(const SkPath& a, const SkPath& b) {\n        return !(a == b);\n    }\n\n    /** Return true if SkPath contain equal verbs and equal weights.\n        If SkPath contain one or more conics, the weights must match.\n\n        conicTo() may add different verbs depending on conic weight, so it is not\n        trivial to interpolate a pair of SkPath containing conics with different\n        conic weight values.\n\n        @param compare  SkPath to compare\n        @return         true if SkPath verb array and weights are equivalent\n    */\n    bool isInterpolatable(const SkPath& compare) const;\n\n    /** Interpolate between SkPath with SkPoint array of equal size.\n        Copy verb array and weights to out, and set out SkPoint array to a weighted\n        average of this SkPoint array and ending SkPoint array, using the formula: (Path Point * weight) + ending Point * (1 - weight).\n\n        weight is most useful when between zero (ending SkPoint array) and\n        one (this Point_Array); will work with values outside of this\n        range.\n\n        interpolate() returns false and leaves out unchanged if SkPoint array is not\n        the same size as ending SkPoint array. Call isInterpolatable() to check SkPath\n        compatibility prior to calling interpolate().\n\n        @param ending  SkPoint array averaged with this SkPoint array\n        @param weight  contribution of this SkPoint array, and\n                       one minus contribution of ending SkPoint array\n        @param out     SkPath replaced by interpolated averages\n        @return        true if SkPath contain same number of SkPoint\n    */\n    bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    /** To be deprecated soon.\n        Only valid for Android framework.\n    */\n    bool unique() const { return fPathRef->unique(); }\n#endif\n\n    /** \\enum SkPath::FillType\n        FillType selects the rule used to fill SkPath. SkPath set to kWinding_FillType\n        fills if the sum of contour edges is not zero, where clockwise edges add one, and\n        counterclockwise edges subtract one. SkPath set to kEvenOdd_FillType fills if the\n        number of contour edges is odd. Each FillType has an inverse variant that\n        reverses the rule:\n        kInverseWinding_FillType fills where the sum of contour edges is zero;\n        kInverseEvenOdd_FillType fills where the number of contour edges is even.\n    */\n    enum FillType {\n        kWinding_FillType,        //!< is enclosed by a non-zero sum of contour directions\n        kEvenOdd_FillType,        //!< is enclosed by an odd number of contours\n        kInverseWinding_FillType, //!< is enclosed by a zero sum of contour directions\n        kInverseEvenOdd_FillType, //!< is enclosed by an even number of contours\n    };\n\n    /** Returns FillType, the rule used to fill SkPath. FillType of a new SkPath is\n        kWinding_FillType.\n\n        @return  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,\n                 kInverseEvenOdd_FillType\n    */\n    FillType getFillType() const { return (FillType)fFillType; }\n\n    /** Sets FillType, the rule used to fill SkPath. While there is no check\n        that ft is legal, values outside of FillType are not supported.\n\n        @param ft  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,\n                   kInverseEvenOdd_FillType\n    */\n    void setFillType(FillType ft) {\n        fFillType = SkToU8(ft);\n    }\n\n    /** Returns if FillType describes area outside SkPath geometry. The inverse fill area\n        extends indefinitely.\n\n        @return  true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType\n    */\n    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }\n\n    /** Replace FillType with its inverse. The inverse of FillType describes the area\n        unmodified by the original FillType.\n    */\n    void toggleInverseFillType() {\n        fFillType ^= 2;\n    }\n\n    /** \\enum SkPath::Convexity\n        SkPath is convex if it contains one contour and contour loops no more than\n        360 degrees, and contour angles all have same Direction. Convex SkPath\n        may have better performance and require fewer resources on GPU surface.\n\n        SkPath is concave when either at least one Direction change is clockwise and\n        another is counterclockwise, or the sum of the changes in Direction is not 360\n        degrees.\n\n        Initially SkPath Convexity is kUnknown_Convexity. SkPath Convexity is computed\n        if needed by destination SkSurface.\n    */\n    enum Convexity : uint8_t {\n        kUnknown_Convexity, //!< indicates Convexity has not been determined\n        kConvex_Convexity,  //!< one contour made of a simple geometry without indentations\n        kConcave_Convexity, //!< more than one contour, or a geometry with indentations\n    };\n\n    /** Computes SkPath::Convexity if required, and returns stored value.\n        SkPath::Convexity is computed if stored value is kUnknown_Convexity,\n        or if SkPath has been altered since SkPath::Convexity was computed or set.\n\n        @return  computed or stored SkPath::Convexity\n    */\n    Convexity getConvexity() const {\n        for (Convexity convexity = fConvexity.load(); kUnknown_Convexity != convexity; ) {\n            return convexity;\n        }\n        return this->internalGetConvexity();\n    }\n\n    /** Returns last computed SkPath::Convexity, or kUnknown_Convexity if\n        SkPath has been altered since SkPath::Convexity was computed or set.\n\n        @return  stored SkPath::Convexity\n    */\n    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }\n\n    /** Stores convexity so that it is later returned by getConvexity() or getConvexityOrUnknown().\n        convexity may differ from getConvexity(), although setting an incorrect value may\n        cause incorrect or inefficient drawing.\n\n        If convexity is kUnknown_Convexity: getConvexity() will\n        compute SkPath::Convexity, and getConvexityOrUnknown() will return kUnknown_Convexity.\n\n        If convexity is kConvex_Convexity or kConcave_Convexity, getConvexity()\n        and getConvexityOrUnknown() will return convexity until the path is\n        altered.\n\n        @param convexity  one of: kUnknown_Convexity, kConvex_Convexity, or kConcave_Convexity\n    */\n    void setConvexity(Convexity convexity);\n\n    /** Computes SkPath::Convexity if required, and returns true if value is kConvex_Convexity.\n        If setConvexity() was called with kConvex_Convexity or kConcave_Convexity, and\n        the path has not been altered, SkPath::Convexity is not recomputed.\n\n        @return  true if SkPath::Convexity stored or computed is kConvex_Convexity\n    */\n    bool isConvex() const {\n        return kConvex_Convexity == this->getConvexity();\n    }\n\n    /** Returns true if this path is recognized as an oval or circle.\n\n        bounds receives bounds of oval.\n\n        bounds is unmodified if oval is not found.\n\n        @param bounds  storage for bounding SkRect of oval; may be nullptr\n        @return        true if SkPath is recognized as an oval or circle\n    */\n    bool isOval(SkRect* bounds) const;\n\n    /** Returns true if this path is recognized as a SkRRect (but not an oval/circle or rect).\n\n        rrect receives bounds of SkRRect.\n\n        rrect is unmodified if SkRRect is not found.\n\n        @param rrect  storage for bounding SkRect of SkRRect; may be nullptr\n        @return       true if SkPath contains only SkRRect\n    */\n    bool isRRect(SkRRect* rrect) const;\n\n    /** Sets SkPath to its initial state.\n        Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.\n        Internal storage associated with SkPath is released.\n    */\n    void reset();\n\n    /** Sets SkPath to its initial state, preserving internal storage.\n        Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.\n        Internal storage associated with SkPath is retained.\n\n        Use rewind() instead of reset() if SkPath storage will be reused and performance\n        is critical.\n    */\n    void rewind();\n\n    /** Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight.\n        SkPath() constructs empty SkPath; reset() and (rewind) make SkPath empty.\n\n        @return  true if the path contains no SkPath::Verb array\n    */\n    bool isEmpty() const {\n        SkDEBUGCODE(this->validate();)\n        return 0 == fPathRef->countVerbs();\n    }\n\n    /** Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked,\n        closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint.\n\n        @return  true if the last contour ends with a kClose_Verb\n    */\n    bool isLastContourClosed() const;\n\n    /** Returns true for finite SkPoint array values between negative SK_ScalarMax and\n        positive SK_ScalarMax. Returns false for any SkPoint array value of\n        SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.\n\n        @return  true if all SkPoint values are finite\n    */\n    bool isFinite() const {\n        SkDEBUGCODE(this->validate();)\n        return fPathRef->isFinite();\n    }\n\n    /** Returns true if the path is volatile; it will not be altered or discarded\n        by the caller after it is drawn. SkPath by default have volatile set false, allowing\n        SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface\n        may not speed repeated drawing.\n\n        @return  true if caller will alter SkPath after drawing\n    */\n    bool isVolatile() const {\n        return SkToBool(fIsVolatile);\n    }\n\n    /** Specify whether SkPath is volatile; whether it will be altered or discarded\n        by the caller after it is drawn. SkPath by default have volatile set false, allowing\n        SkBaseDevice to attach a cache of data which speeds repeated drawing.\n\n        Mark temporary paths, discarded or modified after use, as volatile\n        to inform SkBaseDevice that the path need not be cached.\n\n        Mark animating SkPath volatile to improve performance.\n        Mark unchanging SkPath non-volatile to improve repeated rendering.\n\n        raster surface SkPath draws are affected by volatile for some shadows.\n        GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.\n\n        @param isVolatile  true if caller will alter SkPath after drawing\n    */\n    void setIsVolatile(bool isVolatile) {\n        fIsVolatile = isVolatile;\n    }\n\n    /** Test if line between SkPoint pair is degenerate.\n        Line with no length or that moves a very short distance is degenerate; it is\n        treated as a point.\n\n        exact changes the equality test. If true, returns true only if p1 equals p2.\n        If false, returns true if p1 equals or nearly equals p2.\n\n        @param p1     line start point\n        @param p2     line end point\n        @param exact  if false, allow nearly equals\n        @return       true if line is degenerate; its length is effectively zero\n    */\n    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact);\n\n    /** Test if quad is degenerate.\n        Quad with no length or that moves a very short distance is degenerate; it is\n        treated as a point.\n\n        @param p1     quad start point\n        @param p2     quad control point\n        @param p3     quad end point\n        @param exact  if true, returns true only if p1, p2, and p3 are equal;\n                      if false, returns true if p1, p2, and p3 are equal or nearly equal\n        @return       true if quad is degenerate; its length is effectively zero\n    */\n    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,\n                                 const SkPoint& p3, bool exact);\n\n    /** Test if cubic is degenerate.\n        Cubic with no length or that moves a very short distance is degenerate; it is\n        treated as a point.\n\n        @param p1     cubic start point\n        @param p2     cubic control point 1\n        @param p3     cubic control point 2\n        @param p4     cubic end point\n        @param exact  if true, returns true only if p1, p2, p3, and p4 are equal;\n                      if false, returns true if p1, p2, p3, and p4 are equal or nearly equal\n        @return       true if cubic is degenerate; its length is effectively zero\n    */\n    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,\n                                  const SkPoint& p3, const SkPoint& p4, bool exact);\n\n    /** Returns true if SkPath contains only one line;\n        SkPath::Verb array has two entries: kMove_Verb, kLine_Verb.\n        If SkPath contains one line and line is not nullptr, line is set to\n        line start point and line end point.\n        Returns false if SkPath is not one line; line is unaltered.\n\n        @param line  storage for line. May be nullptr\n        @return      true if SkPath contains exactly one line\n    */\n    bool isLine(SkPoint line[2]) const;\n\n    /** Returns the number of points in SkPath.\n        SkPoint count is initially zero.\n\n        @return  SkPath SkPoint array length\n    */\n    int countPoints() const;\n\n    /** Returns SkPoint at index in SkPoint array. Valid range for index is\n        0 to countPoints() - 1.\n        Returns (0, 0) if index is out of range.\n\n        @param index  SkPoint array element selector\n        @return       SkPoint array value or (0, 0)\n    */\n    SkPoint getPoint(int index) const;\n\n    /** Returns number of points in SkPath. Up to max points are copied.\n        points may be nullptr; then, max must be zero.\n        If max is greater than number of points, excess points storage is unaltered.\n\n        @param points  storage for SkPath SkPoint array. May be nullptr\n        @param max     maximum to copy; must be greater than or equal to zero\n        @return        SkPath SkPoint array length\n    */\n    int getPoints(SkPoint points[], int max) const;\n\n    /** Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,\n        kCubic_Verb, and kClose_Verb; added to SkPath.\n\n        @return  length of verb array\n    */\n    int countVerbs() const;\n\n    /** Returns the number of verbs in the path. Up to max verbs are copied. The\n        verbs are copied as one byte per verb.\n\n        @param verbs  storage for verbs, may be nullptr\n        @param max    maximum number to copy into verbs\n        @return       the actual number of verbs in the path\n    */\n    int getVerbs(uint8_t verbs[], int max) const;\n\n    /** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other.\n        Cached state is also exchanged. swap() internally exchanges pointers, so\n        it is lightweight and does not allocate memory.\n\n        swap() usage has largely been replaced by operator=(const SkPath& path).\n        SkPath do not copy their content on assignment until they are written to,\n        making assignment as efficient as swap().\n\n        @param other  SkPath exchanged by value\n    */\n    void swap(SkPath& other);\n\n    /** Returns minimum and maximum x and y values of SkPoint array.\n        Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may\n        be larger or smaller than area affected when SkPath is drawn.\n\n        SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with\n        kMove_Verb that define empty contours.\n\n        @return  bounds of all SkPoint in SkPoint array\n    */\n    const SkRect& getBounds() const {\n        return fPathRef->getBounds();\n    }\n\n    /** Update internal bounds so that subsequent calls to getBounds() are instantaneous.\n        Unaltered copies of SkPath may also access cached bounds through getBounds().\n\n        For now, identical to calling getBounds() and ignoring the returned value.\n\n        Call to prepare SkPath subsequently drawn from multiple threads,\n        to avoid a race condition where each draw separately computes the bounds.\n    */\n    void updateBoundsCache() const {\n        // for now, just calling getBounds() is sufficient\n        this->getBounds();\n    }\n\n    /** Returns minimum and maximum x and y values of the lines and curves in SkPath.\n        Returns (0, 0, 0, 0) if SkPath contains no points.\n        Returned bounds width and height may be larger or smaller than area affected\n        when SkPath is drawn.\n\n        Includes SkPoint associated with kMove_Verb that define empty\n        contours.\n\n        Behaves identically to getBounds() when SkPath contains\n        only lines. If SkPath contains curves, computed bounds includes\n        the maximum extent of the quad, conic, or cubic; is slower than getBounds();\n        and unlike getBounds(), does not cache the result.\n\n        @return  tight bounds of curves in SkPath\n    */\n    SkRect computeTightBounds() const;\n\n    /** Returns true if rect is contained by SkPath.\n        May return false when rect is contained by SkPath.\n\n        For now, only returns true if SkPath has one contour and is convex.\n        rect may share points and edges with SkPath and be contained.\n        Returns true if rect is empty, that is, it has zero width or height; and\n        the SkPoint or line described by rect is contained by SkPath.\n\n        @param rect  SkRect, line, or SkPoint checked for containment\n        @return      true if rect is contained\n    */\n    bool conservativelyContainsRect(const SkRect& rect) const;\n\n    /** grows SkPath verb array and SkPoint array to contain extraPtCount additional SkPoint.\n        May improve performance and use less memory by\n        reducing the number and size of allocations when creating SkPath.\n\n        @param extraPtCount  number of additional SkPoint to allocate\n    */\n    void incReserve(unsigned extraPtCount);\n\n    /** Adds beginning of contour at SkPoint (x, y).\n\n        @param x  x-coordinate of contour start\n        @param y  y-coordinate of contour start\n    */\n    void moveTo(SkScalar x, SkScalar y);\n\n    /** Adds beginning of contour at SkPoint p.\n\n        @param p  contour start\n    */\n    void moveTo(const SkPoint& p) {\n        this->moveTo(p.fX, p.fY);\n    }\n\n    /** Adds beginning of contour relative to last point.\n        If SkPath is empty, starts contour at (dx, dy).\n        Otherwise, start contour at last point offset by (dx, dy).\n        Function name stands for \"relative move to\".\n\n        @param dx  offset from last point x to contour start x\n        @param dy  offset from last point y to contour start y\n    */\n    void rMoveTo(SkScalar dx, SkScalar dy);\n\n    /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is\n        kClose_Verb, last point is set to (0, 0) before adding line.\n\n        lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.\n        lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.\n\n        @param x  end of added line in x\n        @param y  end of added line in y\n    */\n    void lineTo(SkScalar x, SkScalar y);\n\n    /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is\n        kClose_Verb, last point is set to (0, 0) before adding line.\n\n        lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.\n        lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.\n\n        @param p  end SkPoint of added line\n    */\n    void lineTo(const SkPoint& p) {\n        this->lineTo(p.fX, p.fY);\n    }\n\n    /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is\n        kClose_Verb, last point is set to (0, 0) before adding line.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;\n        then appends kLine_Verb to verb array and line end to SkPoint array.\n        Line end is last point plus vector (dx, dy).\n        Function name stands for \"relative line to\".\n\n        @param dx  offset from last point x to line end x\n        @param dy  offset from last point y to line end y\n    */\n    void rLineTo(SkScalar dx, SkScalar dy);\n\n    /** Adds quad from last point towards (x1, y1), to (x2, y2).\n        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)\n        before adding quad.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;\n        then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)\n        to SkPoint array.\n\n        @param x1  control SkPoint of quad in x\n        @param y1  control SkPoint of quad in y\n        @param x2  end SkPoint of quad in x\n        @param y2  end SkPoint of quad in y\n    */\n    void quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);\n\n    /** Adds quad from last point towards SkPoint p1, to SkPoint p2.\n        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)\n        before adding quad.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;\n        then appends kQuad_Verb to verb array; and SkPoint p1, p2\n        to SkPoint array.\n\n        @param p1  control SkPoint of added quad\n        @param p2  end SkPoint of added quad\n    */\n    void quadTo(const SkPoint& p1, const SkPoint& p2) {\n        this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);\n    }\n\n    /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).\n        If SkPath is empty, or last SkPath::Verb\n        is kClose_Verb, last point is set to (0, 0) before adding quad.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,\n        if needed; then appends kQuad_Verb to verb array; and appends quad\n        control and quad end to SkPoint array.\n        Quad control is last point plus vector (dx1, dy1).\n        Quad end is last point plus vector (dx2, dy2).\n        Function name stands for \"relative quad to\".\n\n        @param dx1  offset from last point x to quad control x\n        @param dy1  offset from last point x to quad control y\n        @param dx2  offset from last point x to quad end x\n        @param dy2  offset from last point x to quad end y\n    */\n    void rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);\n\n    /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.\n        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)\n        before adding conic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.\n\n        If w is finite and not one, appends kConic_Verb to verb array;\n        and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.\n\n        If w is one, appends kQuad_Verb to verb array, and\n        (x1, y1), (x2, y2) to SkPoint array.\n\n        If w is not finite, appends kLine_Verb twice to verb array, and\n        (x1, y1), (x2, y2) to SkPoint array.\n\n        @param x1  control SkPoint of conic in x\n        @param y1  control SkPoint of conic in y\n        @param x2  end SkPoint of conic in x\n        @param y2  end SkPoint of conic in y\n        @param w   weight of added conic\n    */\n    void conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,\n                 SkScalar w);\n\n    /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.\n        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)\n        before adding conic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.\n\n        If w is finite and not one, appends kConic_Verb to verb array;\n        and SkPoint p1, p2 to SkPoint array; and w to conic weights.\n\n        If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2\n        to SkPoint array.\n\n        If w is not finite, appends kLine_Verb twice to verb array, and\n        SkPoint p1, p2 to SkPoint array.\n\n        @param p1  control SkPoint of added conic\n        @param p2  end SkPoint of added conic\n        @param w   weight of added conic\n    */\n    void conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {\n        this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);\n    }\n\n    /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),\n        weighted by w. If SkPath is empty, or last SkPath::Verb\n        is kClose_Verb, last point is set to (0, 0) before adding conic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,\n        if needed.\n\n        If w is finite and not one, next appends kConic_Verb to verb array,\n        and w is recorded as conic weight; otherwise, if w is one, appends\n        kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb\n        twice to verb array.\n\n        In all cases appends SkPoint control and end to SkPoint array.\n        control is last point plus vector (dx1, dy1).\n        end is last point plus vector (dx2, dy2).\n\n        Function name stands for \"relative conic to\".\n\n        @param dx1  offset from last point x to conic control x\n        @param dy1  offset from last point x to conic control y\n        @param dx2  offset from last point x to conic end x\n        @param dy2  offset from last point x to conic end y\n        @param w    weight of added conic\n    */\n    void rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,\n                  SkScalar w);\n\n    /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at\n        (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to\n        (0, 0) before adding cubic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;\n        then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)\n        to SkPoint array.\n\n        @param x1  first control SkPoint of cubic in x\n        @param y1  first control SkPoint of cubic in y\n        @param x2  second control SkPoint of cubic in x\n        @param y2  second control SkPoint of cubic in y\n        @param x3  end SkPoint of cubic in x\n        @param y3  end SkPoint of cubic in y\n    */\n    void cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,\n                 SkScalar x3, SkScalar y3);\n\n    /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at\n        SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to\n        (0, 0) before adding cubic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;\n        then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3\n        to SkPoint array.\n\n        @param p1  first control SkPoint of cubic\n        @param p2  second control SkPoint of cubic\n        @param p3  end SkPoint of cubic\n    */\n    void cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {\n        this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);\n    }\n\n    /** Adds cubic from last point towards vector (dx1, dy1), then towards\n        vector (dx2, dy2), to vector (dx3, dy3).\n        If SkPath is empty, or last SkPath::Verb\n        is kClose_Verb, last point is set to (0, 0) before adding cubic.\n\n        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,\n        if needed; then appends kCubic_Verb to verb array; and appends cubic\n        control and cubic end to SkPoint array.\n        Cubic control is last point plus vector (dx1, dy1).\n        Cubic end is last point plus vector (dx2, dy2).\n        Function name stands for \"relative cubic to\".\n\n        @param x1  offset from last point x to first cubic control x\n        @param y1  offset from last point x to first cubic control y\n        @param x2  offset from last point x to second cubic control x\n        @param y2  offset from last point x to second cubic control y\n        @param x3  offset from last point x to cubic end x\n        @param y3  offset from last point x to cubic end y\n    */\n    void rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,\n                  SkScalar x3, SkScalar y3);\n\n    /** Append arc to SkPath. Arc added is part of ellipse\n        bounded by oval, from startAngle through sweepAngle. Both startAngle and\n        sweepAngle are measured in degrees, where zero degrees is aligned with the\n        positive x-axis, and positive sweeps extends arc clockwise.\n\n        arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo\n        is false and SkPath is not empty. Otherwise, added contour begins with first point\n        of arc. Angles greater than -360 and less than 360 are treated modulo 360.\n\n        @param oval         bounds of ellipse containing arc\n        @param startAngle   starting angle of arc in degrees\n        @param sweepAngle   sweep, in degrees. Positive is clockwise; treated modulo 360\n        @param forceMoveTo  true to start a new contour with arc\n    */\n    void arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);\n\n    /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic\n        weighted to describe part of circle. Arc is contained by tangent from\n        last SkPath point (x0, y0) to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc\n        is part of circle sized to radius, positioned so it touches both tangent lines.\n\n        @param x1      x common to pair of tangents\n        @param y1      y common to pair of tangents\n        @param x2      x end of second tangent\n        @param y2      y end of second tangent\n        @param radius  distance from arc to circle center\n    */\n    void arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);\n\n    /** Append arc to SkPath, after appending line if needed. Arc is implemented by conic\n        weighted to describe part of circle. Arc is contained by tangent from\n        last SkPath point to p1, and tangent from p1 to p2. Arc\n        is part of circle sized to radius, positioned so it touches both tangent lines.\n\n        If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.\n        The length of vector from p1 to p2 does not affect arc.\n\n        Arc sweep is always less than 180 degrees. If radius is zero, or if\n        tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.\n\n        arcTo() appends at most one line and one conic.\n        arcTo() implements the functionality of PostScript_Arct and HTML_Canvas_ArcTo.\n\n        @param p1      SkPoint common to pair of tangents\n        @param p2      end of second tangent\n        @param radius  distance from arc to circle center\n    */\n    void arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {\n        this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);\n    }\n\n    /** \\enum SkPath::ArcSize\n        Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y).\n        ArcSize and Direction select one of the four oval parts.\n    */\n    enum ArcSize {\n        kSmall_ArcSize, //!< smaller of arc pair\n        kLarge_ArcSize, //!< larger of arc pair\n    };\n\n    /** Append arc to SkPath. Arc is implemented by one or more conics weighted to\n        describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc\n        curves from last SkPath SkPoint to (x, y), choosing one of four possible routes:\n        clockwise or counterclockwise, and smaller or larger.\n\n        Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if\n        either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii\n        (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but\n        too small.\n\n        arcTo() appends up to four conic curves.\n        arcTo() implements the functionality of svg arc, although SVG \"sweep-flag\" value\n        is opposite the integer value of sweep; SVG \"sweep-flag\" uses 1 for clockwise,\n        while kCW_Direction  cast to int is zero.\n\n        @param rx           radius in x before x-axis rotation\n        @param ry           radius in y before x-axis rotation\n        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise\n        @param largeArc     chooses smaller or larger arc\n        @param sweep        chooses clockwise or counterclockwise arc\n        @param x            end of arc\n        @param y            end of arc\n    */\n    void arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,\n               Direction sweep, SkScalar x, SkScalar y);\n\n    /** Append arc to SkPath. Arc is implemented by one or more conic weighted to describe part of oval\n        with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves from last SkPath SkPoint to\n        (xy.fX, xy.fY), choosing one of four possible routes: clockwise or counterclockwise,\n        and smaller or larger.\n\n        Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either radii are zero,\n        or if last SkPath SkPoint equals (x, y). arcTo() scales radii r to fit last SkPath SkPoint and\n        xy if both are greater than zero but too small to describe an arc.\n\n        arcTo() appends up to four conic curves.\n        arcTo() implements the functionality of svg arc, although SVG \"sweep-flag\" value is\n        opposite the integer value of sweep; SVG \"sweep-flag\" uses 1 for clockwise, while\n        kCW_Direction cast to int is zero.\n\n        @param r            radii in x and y before x-axis rotation\n        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise\n        @param largeArc     chooses smaller or larger arc\n        @param sweep        chooses clockwise or counterclockwise arc\n        @param xy           end of arc\n    */\n    void arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,\n               const SkPoint xy) {\n        this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);\n    }\n\n    /** Append arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or\n        more conic, weighted to describe part of oval with radii (rx, ry) rotated by\n        xAxisRotate degrees. Arc curves from last SkPath SkPoint (x0, y0) to end SkPoint:\n        (x0 + dx, y0 + dy), choosing one of four possible routes: clockwise or\n        counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint\n        is (0, 0).\n\n        Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint\n        if either radii are zero, or if last SkPath SkPoint equals end SkPoint.\n        arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are\n        greater than zero but too small to describe an arc.\n\n        arcTo() appends up to four conic curves.\n        arcTo() implements the functionality of svg arc, although SVG \"sweep-flag\" value is\n        opposite the integer value of sweep; SVG \"sweep-flag\" uses 1 for clockwise, while\n        kCW_Direction cast to int is zero.\n\n        @param rx           radius in x before x-axis rotation\n        @param ry           radius in y before x-axis rotation\n        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise\n        @param largeArc     chooses smaller or larger arc\n        @param sweep        chooses clockwise or counterclockwise arc\n        @param dx           x offset end of arc from last SkPath SkPoint\n        @param dy           y offset end of arc from last SkPath SkPoint\n    */\n    void rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,\n                Direction sweep, SkScalar dx, SkScalar dy);\n\n    /** Append kClose_Verb to SkPath. A closed contour connects the first and last SkPoint\n        with line, forming a continuous loop. Open and closed contour draw the same\n        with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws\n        SkPaint::Cap at contour start and end; closed contour draws\n        SkPaint::Join at contour start and end.\n\n        close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.\n    */\n    void close();\n\n    /** Returns true if fill is inverted and SkPath with fill represents area outside\n        of its geometric bounds.\n\n        @param fill  one of: kWinding_FillType, kEvenOdd_FillType,\n                     kInverseWinding_FillType, kInverseEvenOdd_FillType\n        @return      true if SkPath fills outside its bounds\n    */\n    static bool IsInverseFillType(FillType fill) {\n        static_assert(0 == kWinding_FillType, \"fill_type_mismatch\");\n        static_assert(1 == kEvenOdd_FillType, \"fill_type_mismatch\");\n        static_assert(2 == kInverseWinding_FillType, \"fill_type_mismatch\");\n        static_assert(3 == kInverseEvenOdd_FillType, \"fill_type_mismatch\");\n        return (fill & 2) != 0;\n    }\n\n    /** Returns equivalent SkPath::FillType representing SkPath fill inside its bounds.\n        .\n\n        @param fill  one of: kWinding_FillType, kEvenOdd_FillType,\n                     kInverseWinding_FillType, kInverseEvenOdd_FillType\n        @return      fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted\n    */\n    static FillType ConvertToNonInverseFillType(FillType fill) {\n        static_assert(0 == kWinding_FillType, \"fill_type_mismatch\");\n        static_assert(1 == kEvenOdd_FillType, \"fill_type_mismatch\");\n        static_assert(2 == kInverseWinding_FillType, \"fill_type_mismatch\");\n        static_assert(3 == kInverseEvenOdd_FillType, \"fill_type_mismatch\");\n        return (FillType)(fill & 1);\n    }\n\n    /** Approximates conic with quad array. Conic is constructed from start SkPoint p0,\n        control SkPoint p1, end SkPoint p2, and weight w.\n        Quad array is stored in pts; this storage is supplied by caller.\n        Maximum quad count is 2 to the pow2.\n        Every third point in array shares last SkPoint of previous quad and first SkPoint of\n        next quad. Maximum pts storage size is given by: (1 + 2 * (1 << pow2)) * sizeof(SkPoint).\n\n        Returns quad count used the approximation, which may be smaller\n        than the number requested.\n\n        conic weight determines the amount of influence conic control point has on the curve.\n        w less than one represents an elliptical section. w greater than one represents\n        a hyperbolic section. w equal to one represents a parabolic section.\n\n        Two quad curves are sufficient to approximate an elliptical conic with a sweep\n        of up to 90 degrees; in this case, set pow2 to one.\n\n        @param p0    conic start SkPoint\n        @param p1    conic control SkPoint\n        @param p2    conic end SkPoint\n        @param w     conic weight\n        @param pts   storage for quad array\n        @param pow2  quad count, as power of two, normally 0 to 5 (1 to 32 quad curves)\n        @return      number of quad curves written to pts\n    */\n    static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,\n                                   SkScalar w, SkPoint pts[], int pow2);\n\n    /** Returns true if SkPath is equivalent to SkRect when filled.\n        If false: rect, isClosed, and direction are unchanged.\n        If true: rect, isClosed, and direction are written to if not nullptr.\n\n        rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points\n        that do not alter the area drawn by the returned rect.\n\n        @param rect       storage for bounds of SkRect; may be nullptr\n        @param isClosed   storage set to true if SkPath is closed; may be nullptr\n        @param direction  storage set to SkRect direction; may be nullptr\n        @return           true if SkPath contains SkRect\n    */\n    bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const;\n\n    /** Returns true if SkPath is equivalent to nested SkRect pair when filled.\n        If false, rect and dirs are unchanged.\n        If true, rect and dirs are written to if not nullptr:\n        setting rect[0] to outer SkRect, and rect[1] to inner SkRect;\n        setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of inner\n        SkRect.\n\n        @param rect  storage for SkRect pair; may be nullptr\n        @param dirs  storage for SkPath::Direction pair; may be nullptr\n        @return      true if SkPath contains nested SkRect pair\n    */\n    bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const;\n\n    /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb,\n        starting with top-left corner of SkRect; followed by top-right, bottom-right,\n        and bottom-left if dir is kCW_Direction; or followed by bottom-left,\n        bottom-right, and top-right if dir is kCCW_Direction.\n\n        @param rect  SkRect to add as a closed contour\n        @param dir   SkPath::Direction to wind added contour\n    */\n    void addRect(const SkRect& rect, Direction dir = kCW_Direction);\n\n    /** Add SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb.\n        If dir is kCW_Direction, SkRect corners are added clockwise; if dir is\n        kCCW_Direction, SkRect corners are added counterclockwise.\n        start determines the first corner added.\n\n        @param rect   SkRect to add as a closed contour\n        @param dir    SkPath::Direction to wind added contour\n        @param start  initial corner of SkRect to add\n    */\n    void addRect(const SkRect& rect, Direction dir, unsigned start);\n\n    /** Add SkRect (left, top, right, bottom) to SkPath,\n        appending kMove_Verb, three kLine_Verb, and kClose_Verb,\n        starting with top-left corner of SkRect; followed by top-right, bottom-right,\n        and bottom-left if dir is kCW_Direction; or followed by bottom-left,\n        bottom-right, and top-right if dir is kCCW_Direction.\n\n        @param left    smaller x of SkRect\n        @param top     smaller y of SkRect\n        @param right   larger x of SkRect\n        @param bottom  larger y of SkRect\n        @param dir     SkPath::Direction to wind added contour\n    */\n    void addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,\n                 Direction dir = kCW_Direction);\n\n    /** Add oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.\n        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width\n        and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues\n        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.\n\n        @param oval  bounds of ellipse added\n        @param dir   SkPath::Direction to wind ellipse\n    */\n    void addOval(const SkRect& oval, Direction dir = kCW_Direction);\n\n    /** Add oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb.\n        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width\n        and half oval height. Oval begins at start and continues\n        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.\n\n        @param oval   bounds of ellipse added\n        @param dir    SkPath::Direction to wind ellipse\n        @param start  index of initial point of ellipse\n    */\n    void addOval(const SkRect& oval, Direction dir, unsigned start);\n\n    /** Add circle centered at (x, y) of size radius to SkPath, appending kMove_Verb,\n        four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing\n        clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.\n\n        Has no effect if radius is zero or negative.\n\n        @param x       center of circle\n        @param y       center of circle\n        @param radius  distance from center to edge\n        @param dir     SkPath::Direction to wind circle\n    */\n    void addCircle(SkScalar x, SkScalar y, SkScalar radius,\n                   Direction dir = kCW_Direction);\n\n    /** Append arc to SkPath, as the start of new contour. Arc added is part of ellipse\n        bounded by oval, from startAngle through sweepAngle. Both startAngle and\n        sweepAngle are measured in degrees, where zero degrees is aligned with the\n        positive x-axis, and positive sweeps extends arc clockwise.\n\n        If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly\n        zero, append oval instead of arc. Otherwise, sweepAngle values are treated\n        modulo 360, and arc may or may not draw depending on numeric rounding.\n\n        @param oval        bounds of ellipse containing arc\n        @param startAngle  starting angle of arc in degrees\n        @param sweepAngle  sweep, in degrees. Positive is clockwise; treated modulo 360\n    */\n    void addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);\n\n    /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds\n        equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If\n        dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and\n        winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left\n        of the upper-left corner and winds counterclockwise.\n\n        If either rx or ry is too large, rx and ry are scaled uniformly until the\n        corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends\n        SkRect rect to SkPath.\n\n        After appending, SkPath may be empty, or may contain: SkRect, oval, or RoundRect.\n\n        @param rect  bounds of SkRRect\n        @param rx    x-radius of rounded corners on the SkRRect\n        @param ry    y-radius of rounded corners on the SkRRect\n        @param dir   SkPath::Direction to wind SkRRect\n    */\n    void addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,\n                      Direction dir = kCW_Direction);\n\n    /** Append SkRRect to SkPath, creating a new closed contour. SkRRect has bounds\n        equal to rect; each corner is 90 degrees of an ellipse with radii from the\n        array.\n\n        @param rect   bounds of SkRRect\n        @param radii  array of 8 SkScalar values, a radius pair for each corner\n        @param dir    SkPath::Direction to wind SkRRect\n    */\n    void addRoundRect(const SkRect& rect, const SkScalar radii[],\n                      Direction dir = kCW_Direction);\n\n    /** Add rrect to SkPath, creating a new closed contour. If\n        dir is kCW_Direction, rrect starts at top-left of the lower-left corner and\n        winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left\n        of the upper-left corner and winds counterclockwise.\n\n        After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.\n\n        @param rrect  bounds and radii of rounded rectangle\n        @param dir    SkPath::Direction to wind SkRRect\n    */\n    void addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);\n\n    /** Add rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect\n        winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise.\n        start determines the first point of rrect to add.\n\n        @param rrect  bounds and radii of rounded rectangle\n        @param dir    SkPath::Direction to wind SkRRect\n        @param start  index of initial point of SkRRect\n    */\n    void addRRect(const SkRRect& rrect, Direction dir, unsigned start);\n\n    /** Add contour created from line array, adding (count - 1) line segments.\n        Contour added starts at pts[0], then adds a line for every additional SkPoint\n        in pts array. If close is true,appends kClose_Verb to SkPath, connecting\n        pts[count - 1] and pts[0].\n\n        If count is zero, append kMove_Verb to path.\n        Has no effect if count is less than one.\n\n        @param pts    array of line sharing end and start SkPoint\n        @param count  length of SkPoint array\n        @param close  true to add line connecting contour end and start\n    */\n    void addPoly(const SkPoint pts[], int count, bool close);\n\n    /** \\enum SkPath::AddPathMode\n        AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend\n        the last contour or start a new contour.\n    */\n    enum AddPathMode {\n        kAppend_AddPathMode, //!< appended to destination unaltered\n        kExtend_AddPathMode, //!< add line if prior contour is not closed\n    };\n\n    /** Append src to SkPath, offset by (dx, dy).\n\n        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are\n        added unaltered. If mode is kExtend_AddPathMode, add line before appending\n        verbs, SkPoint, and conic weights.\n\n        @param src   SkPath verbs, SkPoint, and conic weights to add\n        @param dx    offset added to src SkPoint array x coordinates\n        @param dy    offset added to src SkPoint array y coordinates\n        @param mode  kAppend_AddPathMode or kExtend_AddPathMode\n    */\n    void addPath(const SkPath& src, SkScalar dx, SkScalar dy,\n                 AddPathMode mode = kAppend_AddPathMode);\n\n    /** Append src to SkPath.\n\n        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are\n        added unaltered. If mode is kExtend_AddPathMode, add line before appending\n        verbs, SkPoint, and conic weights.\n\n        @param src   SkPath verbs, SkPoint, and conic weights to add\n        @param mode  kAppend_AddPathMode or kExtend_AddPathMode\n    */\n    void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {\n        SkMatrix m;\n        m.reset();\n        this->addPath(src, m, mode);\n    }\n\n    /** Append src to SkPath, transformed by matrix. Transformed curves may have different\n        verbs, SkPoint, and conic weights.\n\n        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are\n        added unaltered. If mode is kExtend_AddPathMode, add line before appending\n        verbs, SkPoint, and conic weights.\n\n        @param src     SkPath verbs, SkPoint, and conic weights to add\n        @param matrix  transform applied to src\n        @param mode    kAppend_AddPathMode or kExtend_AddPathMode\n    */\n    void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);\n\n    /** Append src to SkPath, from back to front.\n        Reversed src always appends a new contour to SkPath.\n\n        @param src  SkPath verbs, SkPoint, and conic weights to add\n    */\n    void reverseAddPath(const SkPath& src);\n\n    /** Offset SkPoint array by (dx, dy). Offset SkPath replaces dst.\n        If dst is nullptr, SkPath is replaced by offset data.\n\n        @param dx   offset added to SkPoint array x coordinates\n        @param dy   offset added to SkPoint array y coordinates\n        @param dst  overwritten, translated copy of SkPath; may be nullptr\n    */\n    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;\n\n    /** Offset SkPoint array by (dx, dy). SkPath is replaced by offset data.\n\n        @param dx  offset added to SkPoint array x coordinates\n        @param dy  offset added to SkPoint array y coordinates\n    */\n    void offset(SkScalar dx, SkScalar dy) {\n        this->offset(dx, dy, this);\n    }\n\n    /** Transform verb array, SkPoint array, and weight by matrix.\n        transform may change verbs and increase their number.\n        Transformed SkPath replaces dst; if dst is nullptr, original data\n        is replaced.\n\n        @param matrix  SkMatrix to apply to SkPath\n        @param dst     overwritten, transformed copy of SkPath; may be nullptr\n    */\n    void transform(const SkMatrix& matrix, SkPath* dst) const;\n\n    /** Transform verb array, SkPoint array, and weight by matrix.\n        transform may change verbs and increase their number.\n        SkPath is replaced by transformed data.\n\n        @param matrix  SkMatrix to apply to SkPath\n    */\n    void transform(const SkMatrix& matrix) {\n        this->transform(matrix, this);\n    }\n\n    /** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty,\n        storing (0, 0) if lastPt is not nullptr.\n\n        @param lastPt  storage for final SkPoint in SkPoint array; may be nullptr\n        @return        true if SkPoint array contains one or more SkPoint\n    */\n    bool getLastPt(SkPoint* lastPt) const;\n\n    /** Set last point to (x, y). If SkPoint array is empty, append kMove_Verb to\n        verb array and append (x, y) to SkPoint array.\n\n        @param x  set x-coordinate of last point\n        @param y  set y-coordinate of last point\n    */\n    void setLastPt(SkScalar x, SkScalar y);\n\n    /** Set the last point on the path. If SkPoint array is empty, append kMove_Verb to\n        verb array and append p to SkPoint array.\n\n        @param p  set value of last point\n    */\n    void setLastPt(const SkPoint& p) {\n        this->setLastPt(p.fX, p.fY);\n    }\n\n    /** \\enum SkPath::SegmentMask\n        SegmentMask constants correspond to each drawing Verb type in SkPath; for\n        instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set.\n    */\n    enum SegmentMask {\n        kLine_SegmentMask  = 1 << 0, //!< contains one or more lines\n        kQuad_SegmentMask  = 1 << 1, //!< contains one or more quads\n        kConic_SegmentMask = 1 << 2, //!< contains one or more conics\n        kCubic_SegmentMask = 1 << 3, //!< contains one or more cubics\n    };\n\n    /** Returns a mask, where each set bit corresponds to a SegmentMask constant\n        if SkPath contains one or more verbs of that type.\n        Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics.\n\n        getSegmentMasks() returns a cached result; it is very fast.\n\n        @return  SegmentMask bits or zero\n    */\n    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }\n\n    /** \\enum SkPath::Verb\n        Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight;\n        manage contour, and terminate SkPath.\n    */\n    enum Verb {\n        kMove_Verb,  //!< starts new contour at next SkPoint\n        kLine_Verb,  //!< adds line from last point to next SkPoint\n        kQuad_Verb,  //!< adds quad from last point\n        kConic_Verb, //!< adds conic from last point\n        kCubic_Verb, //!< adds cubic from last point\n        kClose_Verb, //!< closes contour\n        kDone_Verb,  //!< terminates SkPath\n    };\n\n    /** \\class SkPath::Iter\n        Iterates through verb array, and associated SkPoint array and conic weight.\n        Provides options to treat open contours as closed, and to ignore\n        degenerate data.\n    */\n    class SK_API Iter {\n    public:\n\n        /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns kDone_Verb.\n            Call setPath to initialize SkPath::Iter at a later time.\n\n            @return  SkPath::Iter of empty SkPath\n        */\n        Iter();\n\n        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.\n            If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each\n            open contour. path is not altered.\n\n            @param path        SkPath to iterate\n            @param forceClose  true if open contours generate kClose_Verb\n            @return            SkPath::Iter of path\n        */\n        Iter(const SkPath& path, bool forceClose);\n\n        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.\n            If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each\n            open contour. path is not altered.\n\n            @param path        SkPath to iterate\n            @param forceClose  true if open contours generate kClose_Verb\n        */\n        void setPath(const SkPath& path, bool forceClose);\n\n        /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter.\n            When verb array is exhausted, returns kDone_Verb.\n\n            Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.\n\n            If doConsumeDegenerates is true, skip consecutive kMove_Verb entries, returning\n            only the last in the series; and skip very small lines, quads, and conics; and\n            skip kClose_Verb following kMove_Verb.\n            if doConsumeDegenerates is true and exact is true, only skip lines, quads, and\n            conics with zero lengths.\n\n            @param pts                   storage for SkPoint data describing returned SkPath::Verb\n            @param doConsumeDegenerates  if true, skip degenerate verbs\n            @param exact                 skip zero length curves\n            @return                      next SkPath::Verb from verb array\n        */\n        Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false) {\n            if (doConsumeDegenerates) {\n                this->consumeDegenerateSegments(exact);\n            }\n            return this->doNext(pts);\n        }\n\n        /** Returns conic weight if next() returned kConic_Verb.\n\n            If next() has not been called, or next() did not return kConic_Verb,\n            result is undefined.\n\n            @return  conic weight for conic SkPoint returned by next()\n        */\n        SkScalar conicWeight() const { return *fConicWeights; }\n\n        /** Returns true if last kLine_Verb returned by next() was generated\n            by kClose_Verb. When true, the end point returned by next() is\n            also the start point of contour.\n\n            If next() has not been called, or next() did not return kLine_Verb,\n            result is undefined.\n\n            @return  true if last kLine_Verb was generated by kClose_Verb\n        */\n        bool isCloseLine() const { return SkToBool(fCloseLine); }\n\n        /** Returns true if subsequent calls to next() return kClose_Verb before returning\n            kMove_Verb. if true, contour SkPath::Iter is processing may end with kClose_Verb, or\n            SkPath::Iter may have been initialized with force close set to true.\n\n            @return  true if contour is closed\n        */\n        bool isClosedContour() const;\n\n    private:\n        const SkPoint*  fPts;\n        const uint8_t*  fVerbs;\n        const uint8_t*  fVerbStop;\n        const SkScalar* fConicWeights;\n        SkPoint         fMoveTo;\n        SkPoint         fLastPt;\n        SkBool8         fForceClose;\n        SkBool8         fNeedClose;\n        SkBool8         fCloseLine;\n        SkBool8         fSegmentState;\n\n        inline const SkPoint& cons_moveTo();\n        Verb autoClose(SkPoint pts[2]);\n        void consumeDegenerateSegments(bool exact);\n        Verb doNext(SkPoint pts[4]);\n\n    };\n\n    /** \\class SkPath::RawIter\n        Iterates through verb array, and associated SkPoint array and conic weight.\n        verb array, SkPoint array, and conic weight are returned unaltered.\n    */\n    class SK_API RawIter {\n    public:\n\n        /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb.\n            Call setPath to initialize SkPath::Iter at a later time.\n\n            @return  RawIter of empty SkPath\n        */\n        RawIter() {}\n\n        /** Sets RawIter to return elements of verb array, SkPoint array, and conic weight in path.\n\n            @param path  SkPath to iterate\n            @return      RawIter of path\n        */\n        RawIter(const SkPath& path) {\n            setPath(path);\n        }\n\n        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in path.\n\n            @param path  SkPath to iterate\n        */\n        void setPath(const SkPath& path) {\n            fRawIter.setPathRef(*path.fPathRef.get());\n        }\n\n        /** Returns next SkPath::Verb in verb array, and advances RawIter.\n            When verb array is exhausted, returns kDone_Verb.\n            Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.\n\n            @param pts  storage for SkPoint data describing returned SkPath::Verb\n            @return     next SkPath::Verb from verb array\n        */\n        Verb next(SkPoint pts[4]) {\n            return (Verb) fRawIter.next(pts);\n        }\n\n        /** Returns next SkPath::Verb, but does not advance RawIter.\n\n            @return  next SkPath::Verb from verb array\n        */\n        Verb peek() const {\n            return (Verb) fRawIter.peek();\n        }\n\n        /** Returns conic weight if next() returned kConic_Verb.\n\n            If next() has not been called, or next() did not return kConic_Verb,\n            result is undefined.\n\n            @return  conic weight for conic SkPoint returned by next()\n        */\n        SkScalar conicWeight() const {\n            return fRawIter.conicWeight();\n        }\n\n    private:\n        SkPathRef::Iter fRawIter;\n        friend class SkPath;\n\n    };\n\n    /** Returns true if the point (x, y) is contained by SkPath, taking into\n        account FillType.\n\n        @param x  x-coordinate of containment test\n        @param y  y-coordinate of containment test\n        @return   true if SkPoint is in SkPath\n    */\n    bool contains(SkScalar x, SkScalar y) const;\n\n    /** Writes text representation of SkPath to stream. If stream is nullptr, writes to\n        standard output. Set forceClose to true to get edges used to fill SkPath.\n        Set dumpAsHex true to generate exact binary representations\n        of floating point numbers used in SkPoint array and conic weights.\n\n        @param stream      writable SkWStream receiving SkPath text representation; may be nullptr\n        @param forceClose  true if missing kClose_Verb is output\n        @param dumpAsHex   true if SkScalar values are written as hexadecimal\n    */\n    void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const;\n\n    /** Writes text representation of SkPath to standard output. The representation may be\n        directly compiled as C++ code. Floating point values are written\n        with limited precision; it may not be possible to reconstruct original SkPath\n        from output.\n    */\n    void dump() const;\n\n    /** Writes text representation of SkPath to standard output. The representation may be\n        directly compiled as C++ code. Floating point values are written\n        in hexadecimal to preserve their exact bit pattern. The output reconstructs the\n        original SkPath.\n\n        Use instead of dump() when submitting\n    */\n    void dumpHex() const;\n\n    /** Writes SkPath to buffer, returning the number of bytes written.\n        Pass nullptr to obtain the storage size.\n\n        Writes SkPath::FillType, verb array, SkPoint array, conic weight, and\n        additionally writes computed information like SkPath::Convexity and bounds.\n\n        Use only be used in concert with readFromMemory();\n        the format used for SkPath in memory is not guaranteed.\n\n        @param buffer  storage for SkPath; may be nullptr\n        @return        size of storage required for SkPath; always a multiple of 4\n    */\n    size_t writeToMemory(void* buffer) const;\n\n    /** Write SkPath to buffer, returning the buffer written to, wrapped in SkData.\n\n        serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and\n        additionally writes computed information like SkPath::Convexity and bounds.\n\n        serialize() should only be used in concert with readFromMemory().\n        The format used for SkPath in memory is not guaranteed.\n\n        @return  SkPath data wrapped in SkData buffer\n    */\n    sk_sp<SkData> serialize() const;\n\n    /** Initializes SkPath from buffer of size length. Returns zero if the buffer is\n        data is inconsistent, or the length is too small.\n\n        Reads SkPath::FillType, verb array, SkPoint array, conic weight, and\n        additionally reads computed information like SkPath::Convexity and bounds.\n\n        Used only in concert with writeToMemory();\n        the format used for SkPath in memory is not guaranteed.\n\n        @param buffer  storage for SkPath\n        @param length  buffer size in bytes; must be multiple of 4\n        @return        number of bytes read, or zero on failure\n    */\n    size_t readFromMemory(const void* buffer, size_t length);\n\n    /** (see skbug.com/1762)\n        Returns a non-zero, globally unique value. A different value is returned\n        if verb array, SkPoint array, or conic weight changes.\n\n        Setting SkPath::FillType does not change generation id.\n\n        Each time the path is modified, a different generation id will be returned.\n        SkPath::FillType does affect generation id on Android framework.\n\n        @return  non-zero, globally unique value\n    */\n    uint32_t getGenerationID() const;\n\n#ifdef SK_SUPPORT_DIRECT_PATHREF_VALIDATION\n    /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if\n        internal values are out of range or internal storage does not match\n        array dimensions.\n\n        @return  true if SkPath data is consistent\n    */\n    bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }\n#else\n    bool isValid() const { return this->isValidImpl(); }\n    bool pathRefIsValid() const { return fPathRef->isValid(); }\n#endif\n\nprivate:\n    sk_sp<SkPathRef>                                     fPathRef;\n    int                                                  fLastMoveToIndex;\n    uint8_t                                              fFillType;\n    mutable SkAtomic<Convexity, sk_memory_order_relaxed> fConvexity;\n    mutable SkAtomic<uint8_t, sk_memory_order_relaxed>   fFirstDirection;// SkPathPriv::FirstDirection\n    SkBool8                                              fIsVolatile;\n    SkBool8                                              fIsBadForDAA = false;\n\n    /** Resets all fields other than fPathRef to their initial 'empty' values.\n     *  Assumes the caller has already emptied fPathRef.\n     *  On Android increments fGenerationID without reseting it.\n     */\n    void resetFields();\n\n    /** Sets all fields other than fPathRef to the values in 'that'.\n     *  Assumes the caller has already set fPathRef.\n     *  Doesn't change fGenerationID or fSourcePath on Android.\n     */\n    void copyFields(const SkPath& that);\n\n    size_t writeToMemoryAsRRect(void* buffer) const;\n    size_t readAsRRect(const void*, size_t);\n    size_t readFromMemory_LE3(const void*, size_t);\n    size_t readFromMemory_EQ4(const void*, size_t);\n\n    friend class Iter;\n    friend class SkPathPriv;\n    friend class SkPathStroker;\n\n    /*  Append, in reverse order, the first contour of path, ignoring path's\n        last point. If no moveTo() call has been made for this contour, the\n        first point is automatically set to (0,0).\n    */\n    void reversePathTo(const SkPath&);\n\n    // called before we add points for lineTo, quadTo, cubicTo, checking to see\n    // if we need to inject a leading moveTo first\n    //\n    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)\n    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)\n    //\n    inline void injectMoveToIfNeeded();\n\n    inline bool hasOnlyMoveTos() const;\n\n    Convexity internalGetConvexity() const;\n\n    /** Asserts if SkPath data is inconsistent.\n        Debugging check intended for internal use only.\n     */\n    SkDEBUGCODE(void validate() const { SkASSERT(this->isValidImpl()); } )\n    bool isValidImpl() const;\n    SkDEBUGCODE(void validateRef() const { fPathRef->validate(); } )\n\n    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,\n                       bool* isClosed, Direction* direction, SkRect* rect) const;\n\n    // called by stroker to see if all points (in the last contour) are equal and worthy of a cap\n    bool isZeroLengthSincePoint(int startPtIndex) const;\n\n    /** Returns if the path can return a bound at no cost (true) or will have to\n        perform some computation (false).\n     */\n    bool hasComputedBounds() const {\n        SkDEBUGCODE(this->validate();)\n        return fPathRef->hasComputedBounds();\n    }\n\n\n    // 'rect' needs to be sorted\n    void setBounds(const SkRect& rect) {\n        SkPathRef::Editor ed(&fPathRef);\n\n        ed.setBounds(rect);\n    }\n\n    void setPt(int index, SkScalar x, SkScalar y);\n\n    friend class SkAutoPathBoundsUpdate;\n    friend class SkAutoDisableOvalCheck;\n    friend class SkAutoDisableDirectionCheck;\n    friend class SkPathWriter;\n    friend class SkOpBuilder;\n    friend class SkBench_AddPathTest; // perf test reversePathTo\n    friend class PathTest_Private; // unit test reversePathTo\n    friend class ForceIsRRect_Private; // unit test isRRect\n    friend class FuzzPath; // for legacy access to validateRef\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPathEffect_DEFINED\n#define SkPathEffect_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkPath.h\"\n#include \"SkPoint.h\"\n#include \"SkRect.h\"\n\nclass SkPath;\nclass SkStrokeRec;\n\n/** \\class SkPathEffect\n\n    SkPathEffect is the base class for objects in the SkPaint that affect\n    the geometry of a drawing primitive before it is transformed by the\n    canvas' matrix and drawn.\n\n    Dashing is implemented as a subclass of SkPathEffect.\n*/\nclass SK_API SkPathEffect : public SkFlattenable {\npublic:\n    /**\n     *  Returns a patheffect that apples each effect (first and second) to the original path,\n     *  and returns a path with the sum of these.\n     *\n     *  result = first(path) + second(path)\n     *\n     */\n    static sk_sp<SkPathEffect> MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second);\n\n    /**\n     *  Returns a patheffect that applies the inner effect to the path, and then applies the\n     *  outer effect to the result of the inner's.\n     *\n     *  result = outer(inner(path))\n     */\n    static sk_sp<SkPathEffect> MakeCompose(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner);\n\n    /**\n     *  Given a src path (input) and a stroke-rec (input and output), apply\n     *  this effect to the src path, returning the new path in dst, and return\n     *  true. If this effect cannot be applied, return false and ignore dst\n     *  and stroke-rec.\n     *\n     *  The stroke-rec specifies the initial request for stroking (if any).\n     *  The effect can treat this as input only, or it can choose to change\n     *  the rec as well. For example, the effect can decide to change the\n     *  stroke's width or join, or the effect can change the rec from stroke\n     *  to fill (or fill to stroke) in addition to returning a new (dst) path.\n     *\n     *  If this method returns true, the caller will apply (as needed) the\n     *  resulting stroke-rec to dst and then draw.\n     */\n    virtual bool filterPath(SkPath* dst, const SkPath& src,\n                            SkStrokeRec*, const SkRect* cullR) const = 0;\n\n    /**\n     *  Compute a conservative bounds for its effect, given the src bounds.\n     *  The baseline implementation just assigns src to dst.\n     */\n    virtual void computeFastBounds(SkRect* dst, const SkRect& src) const;\n\n    /** \\class PointData\n\n        PointData aggregates all the information needed to draw the point\n        primitives returned by an 'asPoints' call.\n    */\n    class PointData {\n    public:\n        PointData()\n            : fFlags(0)\n            , fPoints(nullptr)\n            , fNumPoints(0) {\n            fSize.set(SK_Scalar1, SK_Scalar1);\n            // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets\n            // the kUseClip flag\n        }\n        ~PointData() {\n            delete [] fPoints;\n        }\n\n        // TODO: consider using passed-in flags to limit the work asPoints does.\n        // For example, a kNoPath flag could indicate don't bother generating\n        // stamped solutions.\n\n        // Currently none of these flags are supported.\n        enum PointFlags {\n            kCircles_PointFlag            = 0x01,   // draw points as circles (instead of rects)\n            kUsePath_PointFlag            = 0x02,   // draw points as stamps of the returned path\n            kUseClip_PointFlag            = 0x04,   // apply 'fClipRect' before drawing the points\n        };\n\n        uint32_t           fFlags;      // flags that impact the drawing of the points\n        SkPoint*           fPoints;     // the center point of each generated point\n        int                fNumPoints;  // number of points in fPoints\n        SkVector           fSize;       // the size to draw the points\n        SkRect             fClipRect;   // clip required to draw the points (if kUseClip is set)\n        SkPath             fPath;       // 'stamp' to be used at each point (if kUsePath is set)\n\n        SkPath             fFirst;      // If not empty, contains geometry for first point\n        SkPath             fLast;       // If not empty, contains geometry for last point\n    };\n\n    /**\n     *  Does applying this path effect to 'src' yield a set of points? If so,\n     *  optionally return the points in 'results'.\n     */\n    virtual bool asPoints(PointData* results, const SkPath& src,\n                          const SkStrokeRec&, const SkMatrix&,\n                          const SkRect* cullR) const;\n\n    /**\n     *  If the PathEffect can be represented as a dash pattern, asADash will return kDash_DashType\n     *  and None otherwise. If a non NULL info is passed in, the various DashInfo will be filled\n     *  in if the PathEffect can be a dash pattern. If passed in info has an fCount equal or\n     *  greater to that of the effect, it will memcpy the values of the dash intervals into the\n     *  info. Thus the general approach will be call asADash once with default info to get DashType\n     *  and fCount. If effect can be represented as a dash pattern, allocate space for the intervals\n     *  in info, then call asADash again with the same info and the intervals will get copied in.\n     */\n\n    enum DashType {\n        kNone_DashType, //!< ignores the info parameter\n        kDash_DashType, //!< fills in all of the info parameter\n    };\n\n    struct DashInfo {\n        DashInfo() : fIntervals(nullptr), fCount(0), fPhase(0) {}\n        DashInfo(SkScalar* intervals, int32_t count, SkScalar phase)\n            : fIntervals(intervals), fCount(count), fPhase(phase) {}\n\n        SkScalar*   fIntervals;         //!< Length of on/off intervals for dashed lines\n                                        //   Even values represent ons, and odds offs\n        int32_t     fCount;             //!< Number of intervals in the dash. Should be even number\n        SkScalar    fPhase;             //!< Offset into the dashed interval pattern\n                                        //   mod the sum of all intervals\n    };\n\n    virtual DashType asADash(DashInfo* info) const;\n\n    virtual void toString(SkString* str) const = 0;\n\n    static void InitializeFlattenables();\n\n    static SkFlattenable::Type GetFlattenableType() {\n        return kSkPathEffect_Type;\n    }\n\n    SkFlattenable::Type getFlattenableType() const override {\n        return kSkPathEffect_Type;\n    }\n\n    static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,\n                                          const SkDeserialProcs* procs = nullptr) {\n        return sk_sp<SkPathEffect>(static_cast<SkPathEffect*>(\n                                  SkFlattenable::Deserialize(\n                                  kSkPathEffect_Type, data, size, procs).release()));\n    }\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    /// Override for subclasses as appropriate.\n    virtual bool exposedInAndroidJavaAPI() const { return false; }\n#endif\n\nprotected:\n    SkPathEffect() {}\n\nprivate:\n    // illegal\n    SkPathEffect(const SkPathEffect&);\n    SkPathEffect& operator=(const SkPathEffect&);\n\n    typedef SkFlattenable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPathMeasure.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPathMeasure_DEFINED\n#define SkPathMeasure_DEFINED\n\n#include \"../private/SkTDArray.h\"\n#include \"SkPath.h\"\n\nstruct SkConic;\n\nclass SK_API SkPathMeasure : SkNoncopyable {\npublic:\n    SkPathMeasure();\n    /** Initialize the pathmeasure with the specified path. The path must remain valid\n        for the lifetime of the measure object, or until setPath() is called with\n        a different path (or null), since the measure object keeps a pointer to the\n        path object (does not copy its data).\n\n        resScale controls the precision of the measure. values > 1 increase the\n        precision (and possible slow down the computation).\n    */\n    SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale = 1);\n    ~SkPathMeasure();\n\n    /** Reset the pathmeasure with the specified path. The path must remain valid\n        for the lifetime of the measure object, or until setPath() is called with\n        a different path (or null), since the measure object keeps a pointer to the\n        path object (does not copy its data).\n    */\n    void setPath(const SkPath*, bool forceClosed);\n\n    /** Return the total length of the current contour, or 0 if no path\n        is associated (e.g. resetPath(null))\n    */\n    SkScalar getLength();\n\n    /** Pins distance to 0 <= distance <= getLength(), and then computes\n        the corresponding position and tangent.\n        Returns false if there is no path, or a zero-length path was specified, in which case\n        position and tangent are unchanged.\n    */\n    bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,\n                                         SkVector* tangent);\n\n    enum MatrixFlags {\n        kGetPosition_MatrixFlag     = 0x01,\n        kGetTangent_MatrixFlag      = 0x02,\n        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag\n    };\n\n    /** Pins distance to 0 <= distance <= getLength(), and then computes\n        the corresponding matrix (by calling getPosTan).\n        Returns false if there is no path, or a zero-length path was specified, in which case\n        matrix is unchanged.\n    */\n    bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,\n                                  MatrixFlags flags = kGetPosAndTan_MatrixFlag);\n\n    /** Given a start and stop distance, return in dst the intervening segment(s).\n        If the segment is zero-length, return false, else return true.\n        startD and stopD are pinned to legal values (0..getLength()). If startD > stopD\n        then return false (and leave dst untouched).\n        Begin the segment with a moveTo if startWithMoveTo is true\n    */\n    bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);\n\n    /** Return true if the current contour is closed()\n    */\n    bool isClosed();\n\n    /** Move to the next contour in the path. Return true if one exists, or false if\n        we're done with the path.\n    */\n    bool nextContour();\n\n#ifdef SK_DEBUG\n    void    dump();\n#endif\n\nprivate:\n    SkPath::Iter    fIter;\n    SkPath          fPath;\n    SkScalar        fTolerance;\n    SkScalar        fLength;            // relative to the current contour\n    unsigned        fFirstPtIndex;      // relative to the current contour\n    bool            fIsClosed;          // relative to the current contour\n    bool            fForceClosed;\n\n    struct Segment {\n        SkScalar    fDistance;  // total distance up to this point\n        unsigned    fPtIndex; // index into the fPts array\n        unsigned    fTValue : 30;\n        unsigned    fType : 2;  // actually the enum SkSegType\n                                // See SkPathMeasurePriv.h\n\n        SkScalar getScalarT() const;\n    };\n    SkTDArray<Segment>  fSegments;\n    SkTDArray<SkPoint>  fPts; // Points used to define the segments\n\n    static const Segment* NextSegment(const Segment*);\n\n    void     buildSegments();\n    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,\n                                int mint, int maxt, unsigned ptIndex);\n    SkScalar compute_conic_segs(const SkConic&, SkScalar distance,\n                                int mint, const SkPoint& minPt,\n                                int maxt, const SkPoint& maxPt, unsigned ptIndex);\n    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,\n                                int mint, int maxt, unsigned ptIndex);\n    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);\n    bool quad_too_curvy(const SkPoint pts[3]);\n    bool conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTPt,const SkPoint& lastPt);\n    bool cheap_dist_exceeds_limit(const SkPoint& pt, SkScalar x, SkScalar y);\n    bool cubic_too_curvy(const SkPoint pts[4]);\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPicture.h",
    "content": "/*\n * Copyright 2007 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPicture_DEFINED\n#define SkPicture_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkRect.h\"\n#include \"SkTypes.h\"\n\nclass SkBigPicture;\nclass SkCanvas;\nclass SkData;\nstruct SkDeserialProcs;\nclass SkImage;\nclass SkPictureData;\nclass SkReadBuffer;\nclass SkRefCntSet;\nstruct SkSerialProcs;\nclass SkStream;\nclass SkTypefacePlayback;\nclass SkWStream;\nclass SkWriteBuffer;\nstruct SkPictInfo;\n\n/** \\class SkPicture\n\n    An SkPicture records drawing commands made to a canvas to be played back at a later time.\n    This base class handles serialization and a few other miscellany.\n*/\nclass SK_API SkPicture : public SkRefCnt {\npublic:\n    /**\n     *  Recreate a picture that was serialized into a stream or data.\n     */\n\n    static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs* = nullptr);\n    static sk_sp<SkPicture> MakeFromData(const SkData* data, const SkDeserialProcs* = nullptr);\n    static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,\n                                         const SkDeserialProcs* = nullptr);\n\n    /**\n     *  Recreate a picture that was serialized into a buffer. If the creation requires bitmap\n     *  decoding, the decoder must be set on the SkReadBuffer parameter by calling\n     *  SkReadBuffer::setBitmapDecoder() before calling SkPicture::MakeFromBuffer().\n     *  @param SkReadBuffer Serialized picture data.\n     *  @return A new SkPicture representing the serialized data, or NULL if the buffer is\n     *          invalid.\n     */\n    static sk_sp<SkPicture> MakeFromBuffer(SkReadBuffer&);\n\n    /**\n    *  Subclasses of this can be passed to playback(). During the playback\n    *  of the picture, this callback will periodically be invoked. If its\n    *  abort() returns true, then picture playback will be interrupted.\n    *\n    *  The resulting drawing is undefined, as there is no guarantee how often the\n    *  callback will be invoked. If the abort happens inside some level of nested\n    *  calls to save(), restore will automatically be called to return the state\n    *  to the same level it was before the playback call was made.\n    */\n    class SK_API AbortCallback {\n    public:\n        AbortCallback() {}\n        virtual ~AbortCallback() {}\n        virtual bool abort() = 0;\n    };\n\n    /** Replays the drawing commands on the specified canvas. Note that\n        this has the effect of unfurling this picture into the destination\n        canvas. Using the SkCanvas::drawPicture entry point gives the destination\n        canvas the option of just taking a ref.\n        @param canvas the canvas receiving the drawing commands.\n        @param callback a callback that allows interruption of playback\n    */\n    virtual void playback(SkCanvas*, AbortCallback* = nullptr) const = 0;\n\n    /** Return a cull rect for this picture.\n        Ops recorded into this picture that attempt to draw outside the cull might not be drawn.\n     */\n    virtual SkRect cullRect() const = 0;\n\n    /** Returns a non-zero value unique among all pictures. */\n    uint32_t uniqueID() const;\n\n    sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;\n    void serialize(SkWStream*, const SkSerialProcs* = nullptr) const;\n\n    /**\n     * Return a placeholder SkPicture.\n     * This placeholder does not draw anything itself.  It has a distinct uniqueID()\n     * (just like all SkPictures) and will always be visible to SkSerialProcs.\n     * @param cull the placeholder's dimensions\n     */\n    static sk_sp<SkPicture> MakePlaceholder(SkRect cull);\n\n    /**\n     *  Serialize to a buffer.\n     */\n    void flatten(SkWriteBuffer&) const;\n\n    /** Return the approximate number of operations in this picture.  This\n     *  number may be greater or less than the number of SkCanvas calls\n     *  recorded: some calls may be recorded as more than one operation, or some\n     *  calls may be optimized away.\n     */\n    virtual int approximateOpCount() const = 0;\n\n    /** Returns the approximate byte size of this picture, not including large ref'd objects. */\n    virtual size_t approximateBytesUsed() const = 0;\n\n    // Returns NULL if this is not an SkBigPicture.\n    virtual const SkBigPicture* asSkBigPicture() const { return nullptr; }\n\nprivate:\n    // Subclass whitelist.\n    SkPicture();\n    friend class SkBigPicture;\n    friend class SkEmptyPicture;\n    template <typename> friend class SkMiniPicture;\n\n    void serialize(SkWStream*, const SkSerialProcs*, SkRefCntSet* typefaces) const;\n    static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs*, SkTypefacePlayback*);\n    friend class SkPictureData;\n\n    /** Return true if the SkStream/Buffer represents a serialized picture, and\n     fills out SkPictInfo. After this function returns, the data source is not\n     rewound so it will have to be manually reset before passing to\n     MakeFromStream or MakeFromBuffer. Note, MakeFromStream and\n     MakeFromBuffer perform this check internally so these entry points are\n     intended for stand alone tools.\n     If false is returned, SkPictInfo is unmodified.\n     */\n    static bool StreamIsSKP(SkStream*, SkPictInfo*);\n    static bool BufferIsSKP(SkReadBuffer*, SkPictInfo*);\n    friend bool SkPicture_StreamIsSKP(SkStream*, SkPictInfo*);\n\n    friend struct SkPathCounter;\n\n    // V35: Store SkRect (rather then width & height) in header\n    // V36: Remove (obsolete) alphatype from SkColorTable\n    // V37: Added shadow only option to SkDropShadowImageFilter (last version to record CLEAR)\n    // V38: Added PictureResolution option to SkPictureImageFilter\n    // V39: Added FilterLevel option to SkPictureImageFilter\n    // V40: Remove UniqueID serialization from SkImageFilter.\n    // V41: Added serialization of SkBitmapSource's filterQuality parameter\n    // V42: Added a bool to SkPictureShader serialization to indicate did-we-serialize-a-picture?\n    // V43: Added DRAW_IMAGE and DRAW_IMAGE_RECT opt codes to serialized data\n    // V44: Move annotations from paint to drawAnnotation\n    // V45: Add invNormRotation to SkLightingShader.\n    // V46: Add drawTextRSXform\n    // V47: Add occluder rect to SkBlurMaskFilter\n    // V48: Read and write extended SkTextBlobs.\n    // V49: Gradients serialized as SkColor4f + SkColorSpace\n    // V50: SkXfermode -> SkBlendMode\n    // V51: more SkXfermode -> SkBlendMode\n    // V52: Remove SkTextBlob::fRunCount\n    // V53: SaveLayerRec clip mask\n    // V54: ComposeShader can use a Mode or a Lerp\n    // V55: Drop blendmode[] from MergeImageFilter\n    // V56: Add TileMode in SkBlurImageFilter.\n    // V57: Sweep tiling info.\n    // V58: No more 2pt conical flipping.\n    // V59: No more LocalSpace option on PictureImageFilter\n    // V60: Remove flags in picture header\n    // V61: Change SkDrawPictureRec to take two colors rather than two alphas\n    // V62: Don't negate size of custom encoded images (don't write origin x,y either)\n    // V63: Store image bounds (including origin) instead of just width/height to support subsets\n\n    // Only SKPs within the min/current picture version range (inclusive) can be read.\n    static const uint32_t     MIN_PICTURE_VERSION = 56;     // august 2017\n    static const uint32_t CURRENT_PICTURE_VERSION = 63;\n\n    static_assert(MIN_PICTURE_VERSION <= 62, \"Remove kFontAxes_bad from SkFontDescriptor.cpp\");\n\n    static bool IsValidPictInfo(const SkPictInfo& info);\n    static sk_sp<SkPicture> Forwardport(const SkPictInfo&,\n                                        const SkPictureData*,\n                                        SkReadBuffer* buffer);\n\n    SkPictInfo createHeader() const;\n    SkPictureData* backport() const;\n\n    mutable uint32_t fUniqueID;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPictureRecorder.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPictureRecorder_DEFINED\n#define SkPictureRecorder_DEFINED\n\n#include \"SkBBHFactory.h\"\n#include \"SkPicture.h\"\n#include \"SkRefCnt.h\"\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\nnamespace android {\n    class Picture;\n};\n#endif\n\nclass GrContext;\nclass SkCanvas;\nclass SkDrawable;\nclass SkMiniRecorder;\nclass SkPictureRecord;\nclass SkRecord;\nclass SkRecorder;\n\nclass SK_API SkPictureRecorder : SkNoncopyable {\npublic:\n    SkPictureRecorder();\n    ~SkPictureRecorder();\n\n    enum RecordFlags {\n        // If you call drawPicture() or drawDrawable() on the recording canvas, this flag forces\n        // that object to playback its contents immediately rather than reffing the object.\n        kPlaybackDrawPicture_RecordFlag     = 1 << 0,\n    };\n\n    enum FinishFlags {\n    };\n\n    /** Returns the canvas that records the drawing commands.\n        @param bounds the cull rect used when recording this picture. Any drawing the falls outside\n                      of this rect is undefined, and may be drawn or it may not.\n        @param bbhFactory factory to create desired acceleration structure\n        @param recordFlags optional flags that control recording.\n        @return the canvas.\n    */\n    SkCanvas* beginRecording(const SkRect& bounds,\n                             SkBBHFactory* bbhFactory = nullptr,\n                             uint32_t recordFlags = 0);\n\n    SkCanvas* beginRecording(SkScalar width, SkScalar height,\n                             SkBBHFactory* bbhFactory = nullptr,\n                             uint32_t recordFlags = 0) {\n        return this->beginRecording(SkRect::MakeWH(width, height), bbhFactory, recordFlags);\n    }\n\n    /** Returns the recording canvas if one is active, or NULL if recording is\n        not active. This does not alter the refcnt on the canvas (if present).\n    */\n    SkCanvas* getRecordingCanvas();\n\n    /**\n     *  Signal that the caller is done recording. This invalidates the canvas returned by\n     *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who\n     *  must call unref() when they are done using it.\n     *\n     *  The returned picture is immutable. If during recording drawables were added to the canvas,\n     *  these will have been \"drawn\" into a recording canvas, so that this resulting picture will\n     *  reflect their current state, but will not contain a live reference to the drawables\n     *  themselves.\n     */\n    sk_sp<SkPicture> finishRecordingAsPicture(uint32_t endFlags = 0);\n\n    /**\n     *  Signal that the caller is done recording, and update the cull rect to use for bounding\n     *  box hierarchy (BBH) generation. The behavior is the same as calling\n     *  finishRecordingAsPicture(), except that this method updates the cull rect initially passed\n     *  into beginRecording.\n     *  @param cullRect the new culling rectangle to use as the overall bound for BBH generation\n     *                  and subsequent culling operations.\n     *  @return the picture containing the recorded content.\n     */\n    sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect,\n                                                      uint32_t endFlags = 0);\n\n    /**\n     *  Signal that the caller is done recording. This invalidates the canvas returned by\n     *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who\n     *  must call unref() when they are done using it.\n     *\n     *  Unlike finishRecordingAsPicture(), which returns an immutable picture, the returned drawable\n     *  may contain live references to other drawables (if they were added to the recording canvas)\n     *  and therefore this drawable will reflect the current state of those nested drawables anytime\n     *  it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).\n     */\n    sk_sp<SkDrawable> finishRecordingAsDrawable(uint32_t endFlags = 0);\n\nprivate:\n    void reset();\n\n    /** Replay the current (partially recorded) operation stream into\n        canvas. This call doesn't close the current recording.\n    */\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    friend class android::Picture;\n#endif\n    friend class SkPictureRecorderReplayTester; // for unit testing\n    void partialReplay(SkCanvas* canvas) const;\n\n    bool                        fActivelyRecording;\n    uint32_t                    fFlags;\n    SkRect                      fCullRect;\n    sk_sp<SkBBoxHierarchy>      fBBH;\n    std::unique_ptr<SkRecorder> fRecorder;\n    sk_sp<SkRecord>             fRecord;\n    std::unique_ptr<SkMiniRecorder> fMiniRecorder;\n\n    typedef SkNoncopyable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPixelRef.h",
    "content": "/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPixelRef_DEFINED\n#define SkPixelRef_DEFINED\n\n#include \"../private/SkAtomics.h\"\n#include \"../private/SkMutex.h\"\n#include \"../private/SkTDArray.h\"\n#include \"SkBitmap.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkImageInfo.h\"\n#include \"SkPixmap.h\"\n#include \"SkRefCnt.h\"\n#include \"SkSize.h\"\n#include \"SkString.h\"\n\nstruct SkIRect;\n\nclass GrTexture;\nclass SkDiscardableMemory;\n\n/** \\class SkPixelRef\n\n    This class is the smart container for pixel memory, and is used with SkBitmap.\n    This class can be shared/accessed between multiple threads.\n*/\nclass SK_API SkPixelRef : public SkRefCnt {\npublic:\n    SkPixelRef(int width, int height, void* addr, size_t rowBytes);\n    ~SkPixelRef() override;\n\n    int width() const { return fWidth; }\n    int height() const { return fHeight; }\n    void* pixels() const { return fPixels; }\n    size_t rowBytes() const { return fRowBytes; }\n\n    /** Returns a non-zero, unique value corresponding to the pixels in this\n        pixelref. Each time the pixels are changed (and notifyPixelsChanged is\n        called), a different generation ID will be returned.\n    */\n    uint32_t getGenerationID() const;\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    /** Returns a non-zero, unique value corresponding to this SkPixelRef.\n        Unlike the generation ID, this ID remains the same even when the pixels\n        are changed. IDs are not reused (until uint32_t wraps), so it is safe\n        to consider this ID unique even after this SkPixelRef is deleted.\n\n        Can be used as a key which uniquely identifies this SkPixelRef\n        regardless of changes to its pixels or deletion of this object.\n     */\n    uint32_t getStableID() const { return fStableID; }\n#endif\n\n    /**\n     *  Call this if you have changed the contents of the pixels. This will in-\n     *  turn cause a different generation ID value to be returned from\n     *  getGenerationID().\n     */\n    void notifyPixelsChanged();\n\n    /** Returns true if this pixelref is marked as immutable, meaning that the\n        contents of its pixels will not change for the lifetime of the pixelref.\n    */\n    bool isImmutable() const { return fMutability != kMutable; }\n\n    /** Marks this pixelref is immutable, meaning that the contents of its\n        pixels will not change for the lifetime of the pixelref. This state can\n        be set on a pixelref, but it cannot be cleared once it is set.\n    */\n    void setImmutable();\n\n    // Register a listener that may be called the next time our generation ID changes.\n    //\n    // We'll only call the listener if we're confident that we are the only SkPixelRef with this\n    // generation ID.  If our generation ID changes and we decide not to call the listener, we'll\n    // never call it: you must add a new listener for each generation ID change.  We also won't call\n    // the listener when we're certain no one knows what our generation ID is.\n    //\n    // This can be used to invalidate caches keyed by SkPixelRef generation ID.\n    struct GenIDChangeListener {\n        virtual ~GenIDChangeListener() {}\n        virtual void onChange() = 0;\n    };\n\n    // Takes ownership of listener.\n    void addGenIDChangeListener(GenIDChangeListener* listener);\n\n    // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache\n    // to know automatically those entries can be purged when this pixelref is changed or deleted.\n    void notifyAddedToCache() {\n        fAddedToCache.store(true);\n    }\n\n    virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }\n\nprotected:\n    void android_only_reset(int width, int height, size_t rowBytes);\n\nprivate:\n    int                 fWidth;\n    int                 fHeight;\n    void*               fPixels;\n    size_t              fRowBytes;\n\n    // Bottom bit indicates the Gen ID is unique.\n    bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }\n    mutable SkAtomic<uint32_t> fTaggedGenID;\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    const uint32_t fStableID;\n#endif\n\n    SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned\n\n    // Set true by caches when they cache content that's derived from the current pixels.\n    SkAtomic<bool> fAddedToCache;\n\n    enum Mutability {\n        kMutable,               // PixelRefs begin mutable.\n        kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.\n        kImmutable,             // Once set to this state, it never leaves.\n    } fMutability : 8;          // easily fits inside a byte\n\n    void needsNewGenID();\n    void callGenIDChangeListeners();\n\n    void setTemporarilyImmutable();\n    void restoreMutability();\n    friend class SkSurface_Raster;   // For the two methods above.\n\n    friend class SkImage_Raster;\n    friend class SkSpecialImage_Raster;\n\n    void setImmutableWithID(uint32_t genID);\n    friend class SkImage_Gpu;\n    friend class SkImage_Lazy;\n    friend class SkSpecialImage_Gpu;\n    friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPixmap.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPixmap_DEFINED\n#define SkPixmap_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkImageInfo.h\"\n\nclass SkData;\nstruct SkMask;\n\n/** \\class SkPixmap\n    SkPixmap provides a utility to pair SkImageInfo with pixels and row bytes.\n    SkPixmap is a low level class which provides convenience functions to access\n    raster destinations. SkCanvas can not draw SkPixmap, nor does SkPixmap provide\n    a direct drawing destination.\n\n    Use SkBitmap to draw pixels referenced by SkPixmap; use SkSurface to draw into\n    pixels referenced by SkPixmap.\n\n    SkPixmap does not try to manage the lifetime of the pixel memory. Use SkPixelRef\n    to manage pixel memory; SkPixelRef is safe across threads.\n*/\nclass SK_API SkPixmap {\npublic:\n\n    /** Creates an empty SkPixmap without pixels, with kUnknown_SkColorType, with\n        kUnknown_SkAlphaType, and with a width and height of zero. Use\n        reset() to associate pixels, SkColorType, SkAlphaType, width, and height\n        after SkPixmap has been created.\n\n        @return  empty SkPixmap\n    */\n    SkPixmap()\n        : fPixels(nullptr), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))\n    {}\n\n    /** Creates SkPixmap from info width, height, SkAlphaType, and SkColorType.\n        addr points to pixels, or nullptr. rowBytes should be info.width() times\n        info.bytesPerPixel(), or larger.\n\n        No parameter checking is performed; it is up to the caller to ensure that\n        addr and rowBytes agree with info.\n\n        The memory lifetime of pixels is managed by the caller. When SkPixmap goes\n        out of scope, addr is unaffected.\n\n        SkPixmap may be later modified by reset() to change its size, pixel type, or\n        storage.\n\n        @param info      width, height, SkAlphaType, SkColorType of SkImageInfo\n        @param addr      pointer to pixels allocated by caller; may be nullptr\n        @param rowBytes  size of one row of addr; width times pixel size, or larger\n        @return          initialized SkPixmap\n    */\n    SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes)\n        : fPixels(addr), fRowBytes(rowBytes), fInfo(info)\n    {}\n\n    /** Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to\n        kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.\n\n        The prior pixels are unaffected; it is up to the caller to release pixels\n        memory if desired.\n    */\n    void reset();\n\n    /** Sets width, height, SkAlphaType, and SkColorType from info.\n        Sets pixel address from addr, which may be nullptr.\n        Sets row bytes from rowBytes, which should be info.width() times\n        info.bytesPerPixel(), or larger.\n\n        Does not check addr. Asserts if built with SK_DEBUG defined and if rowBytes is\n        too small to hold one row of pixels.\n\n        The memory lifetime pixels are managed by the caller. When SkPixmap goes\n        out of scope, addr is unaffected.\n\n        @param info      width, height, SkAlphaType, SkColorType of SkImageInfo\n        @param addr      pointer to pixels allocated by caller; may be nullptr\n        @param rowBytes  size of one row of addr; width times pixel size, or larger\n    */\n    void reset(const SkImageInfo& info, const void* addr, size_t rowBytes);\n\n    /** Changes SkColorSpace in SkImageInfo; preserves width, height, SkAlphaType, and\n        SkColorType in SkImage, and leaves pixel address and row bytes unchanged.\n        SkColorSpace reference count is incremented.\n\n        @param colorSpace  SkColorSpace moved to SkImageInfo\n    */\n    void setColorSpace(sk_sp<SkColorSpace> colorSpace);\n\n    /** To be deprecated soon.\n    */\n    bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask);\n\n    /** Sets subset width, height, pixel address to intersection of SkPixmap with area,\n        if intersection is not empty; and return true. Otherwise, leave subset unchanged\n        and return false.\n\n        Failing to read the return value generates a compile time warning.\n\n        @param subset  storage for width, height, pixel address of intersection\n        @param area    bounds to intersect with SkPixmap\n        @return        true if intersection of SkPixmap and area is not empty\n    */\n    bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;\n\n    /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.\n\n        @return  reference to ImageInfo\n    */\n    const SkImageInfo& info() const { return fInfo; }\n\n    /** Returns row bytes, the interval from one pixel row to the next. Row bytes\n        is at least as large as: width() * info().bytesPerPixel().\n\n        Returns zero if colorType() is kUnknown_SkColorType.\n        It is up to the SkBitmap creator to ensure that row bytes is a useful value.\n\n        @return  byte length of pixel row\n    */\n    size_t rowBytes() const { return fRowBytes; }\n\n    /** Returns pixel address, the base address corresponding to the pixel origin.\n\n        It is up to the SkPixmap creator to ensure that pixel address is a useful value.\n\n        @return  pixel address\n    */\n    const void* addr() const { return fPixels; }\n\n    /** Returns pixel count in each pixel row. Should be equal or less than:\n        rowBytes() / info().bytesPerPixel().\n\n        @return  pixel width in SkImageInfo\n    */\n    int width() const { return fInfo.width(); }\n\n    /** Returns pixel row count.\n\n        @return  pixel height in SkImageInfo\n    */\n    int height() const { return fInfo.height(); }\n\n    /** Returns SkColorType, one of:\n        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n        kGray_8_SkColorType, kRGBA_F16_SkColorType.\n\n        @return  SkColorType in SkImageInfo\n    */\n    SkColorType colorType() const { return fInfo.colorType(); }\n\n    /** Returns SkAlphaType, one of:\n        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,\n        kUnpremul_SkAlphaType.\n\n        @return  SkAlphaType in SkImageInfo\n    */\n    SkAlphaType alphaType() const { return fInfo.alphaType(); }\n\n    /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The\n        reference count of SkColorSpace is unchanged. The returned SkColorSpace is\n        immutable.\n\n        @return  SkColorSpace in SkImageInfo, or nullptr\n    */\n    SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }\n\n    /** Returns true if SkAlphaType is kOpaque_SkAlphaType.\n        Does not check if SkColorType allows alpha, or if any pixel value has\n        transparency.\n\n        @return  true if SkImageInfo has opaque SkAlphaType\n    */\n    bool isOpaque() const { return fInfo.isOpaque(); }\n\n    /** Returns SkIRect { 0, 0, width(), height() }.\n\n        @return  integral rectangle from origin to width() and height()\n    */\n    SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }\n\n    /** Returns number of pixels that fit on row. Should be greater than or equal to\n        width().\n\n        @return  maximum pixels per row\n    */\n    int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }\n\n    /** Returns bit shift converting row bytes to row pixels.\n        Returns zero for kUnknown_SkColorType.\n\n        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes\n    */\n    int shiftPerPixel() const { return fInfo.shiftPerPixel(); }\n\n    /** Returns minimum memory required for pixel storage.\n        Does not include unused memory on last row when rowBytesAsPixels() exceeds width().\n        Returns zero if result does not fit in size_t.\n        Returns zero if height() or width() is 0.\n        Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.\n\n        @return  size in bytes of image buffer\n    */\n    size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }\n\n    /** Returns true if all pixels are opaque. SkColorType determines how pixels\n        are encoded, and whether pixel describes alpha. Returns true for SkColorType\n        without alpha in each pixel; for other SkColorType, returns true if all\n        pixels have alpha values equivalent to 1.0 or greater.\n\n        For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always\n        returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,\n        kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.\n        For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.\n        For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or\n        greater.\n\n        Returns false for kUnknown_SkColorType.\n\n        @return  true if all pixels have opaque values or SkColorType is opaque\n    */\n    bool computeIsOpaque() const;\n\n    /** Returns pixel at (x, y) as unpremultiplied color.\n        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined; and returns undefined values or may crash if\n        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or\n        pixel address is nullptr.\n\n        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the\n        conversion to unpremultiplied color; original pixel data may have additional\n        precision.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   pixel converted to unpremultiplied color\n    */\n    SkColor getColor(int x, int y) const;\n\n    /** Returns readable pixel address at (x, y). Returns nullptr if SkPixelRef is nullptr.\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined. Returns nullptr if SkColorType is kUnknown_SkColorType.\n\n        Performs a lookup of pixel size; for better performance, call\n        one of: addr8, addr16, addr32, addr64, or addrF16().\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable generic pointer to pixel\n    */\n    const void* addr(int x, int y) const {\n        return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);\n    }\n\n    /** Returns readable base pixel address. Result is addressable as unsigned 8-bit bytes.\n        Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or\n        kGray_8_SkColorType, and is built with SK_DEBUG defined.\n\n        One byte corresponds to one pixel.\n\n        @return  readable unsigned 8-bit pointer to pixels\n    */\n    const uint8_t* addr8() const {\n        SkASSERT(1 == fInfo.bytesPerPixel());\n        return reinterpret_cast<const uint8_t*>(fPixels);\n    }\n\n    /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.\n        Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or\n        kARGB_4444_SkColorType, and is built with SK_DEBUG defined.\n\n        One word corresponds to one pixel.\n\n        @return  readable unsigned 16-bit pointer to pixels\n    */\n    const uint16_t* addr16() const {\n        SkASSERT(2 == fInfo.bytesPerPixel());\n        return reinterpret_cast<const uint16_t*>(fPixels);\n    }\n\n    /** Returns readable base pixel address. Result is addressable as unsigned 32-bit words.\n        Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or\n        kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.\n\n        One word corresponds to one pixel.\n\n        @return  readable unsigned 32-bit pointer to pixels\n    */\n    const uint32_t* addr32() const {\n        SkASSERT(4 == fInfo.bytesPerPixel());\n        return reinterpret_cast<const uint32_t*>(fPixels);\n    }\n\n    /** Returns readable base pixel address. Result is addressable as unsigned 64-bit words.\n        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built\n        with SK_DEBUG defined.\n\n        One word corresponds to one pixel.\n\n        @return  readable unsigned 64-bit pointer to pixels\n    */\n    const uint64_t* addr64() const {\n        SkASSERT(8 == fInfo.bytesPerPixel());\n        return reinterpret_cast<const uint64_t*>(fPixels);\n    }\n\n    /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.\n        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built\n        with SK_DEBUG defined.\n\n        Each word represents one color component encoded as a half float.\n        Four words correspond to one pixel.\n\n        @return  readable unsigned 16-bit pointer to first component of pixels\n    */\n    const uint16_t* addrF16() const {\n        SkASSERT(8 == fInfo.bytesPerPixel());\n        SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());\n        return reinterpret_cast<const uint16_t*>(fPixels);\n    }\n\n    /** Returns readable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined.\n\n        Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or\n        kGray_8_SkColorType, and is built with SK_DEBUG defined.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable unsigned 8-bit pointer to pixel at (x, y)\n    */\n    const uint8_t* addr8(int x, int y) const {\n        SkASSERT((unsigned)x < (unsigned)fInfo.width());\n        SkASSERT((unsigned)y < (unsigned)fInfo.height());\n        return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));\n    }\n\n    /** Returns readable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined.\n\n        Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or\n        kARGB_4444_SkColorType, and is built with SK_DEBUG defined.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable unsigned 16-bit pointer to pixel at (x, y)\n    */\n    const uint16_t* addr16(int x, int y) const {\n        SkASSERT((unsigned)x < (unsigned)fInfo.width());\n        SkASSERT((unsigned)y < (unsigned)fInfo.height());\n        return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));\n    }\n\n    /** Returns readable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined.\n\n        Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or\n        kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable unsigned 32-bit pointer to pixel at (x, y)\n    */\n    const uint32_t* addr32(int x, int y) const {\n        SkASSERT((unsigned)x < (unsigned)fInfo.width());\n        SkASSERT((unsigned)y < (unsigned)fInfo.height());\n        return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));\n    }\n\n    /** Returns readable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined.\n\n        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built\n        with SK_DEBUG defined.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable unsigned 64-bit pointer to pixel at (x, y)\n    */\n    const uint64_t* addr64(int x, int y) const {\n        SkASSERT((unsigned)x < (unsigned)fInfo.width());\n        SkASSERT((unsigned)y < (unsigned)fInfo.height());\n        return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3));\n    }\n\n    /** Returns readable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined.\n\n        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built\n        with SK_DEBUG defined.\n\n        Each unsigned 16-bit word represents one color component encoded as a half float.\n        Four words correspond to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   readable unsigned 16-bit pointer to pixel component at (x, y)\n    */\n    const uint16_t* addrF16(int x, int y) const {\n        SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());\n        return reinterpret_cast<const uint16_t*>(this->addr64(x, y));\n    }\n\n    /** Returns writable base pixel address.\n\n        @return  writable generic base pointer to pixels\n    */\n    void* writable_addr() const { return const_cast<void*>(fPixels); }\n\n    /** Returns writable pixel address at (x, y).\n\n        Input is not validated: out of bounds values of x or y trigger an assert() if\n        built with SK_DEBUG defined. Returns zero if SkColorType is kUnknown_SkColorType.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable generic pointer to pixel\n    */\n    void* writable_addr(int x, int y) const {\n        return const_cast<void*>(this->addr(x, y));\n    }\n\n    /** Returns writable pixel address at (x, y). Result is addressable as unsigned\n        8-bit bytes. Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType\n        or kGray_8_SkColorType, and is built with SK_DEBUG defined.\n\n        One byte corresponds to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable unsigned 8-bit pointer to pixels\n    */\n    uint8_t* writable_addr8(int x, int y) const {\n        return const_cast<uint8_t*>(this->addr8(x, y));\n    }\n\n    /** Returns writable_addr pixel address at (x, y). Result is addressable as unsigned\n        16-bit words. Will trigger an assert() if SkColorType is not kRGB_565_SkColorType\n        or kARGB_4444_SkColorType, and is built with SK_DEBUG defined.\n\n        One word corresponds to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable unsigned 16-bit pointer to pixel\n    */\n    uint16_t* writable_addr16(int x, int y) const {\n        return const_cast<uint16_t*>(this->addr16(x, y));\n    }\n\n    /** Returns writable pixel address at (x, y). Result is addressable as unsigned\n        32-bit words. Will trigger an assert() if SkColorType is not\n        kRGBA_8888_SkColorType or kBGRA_8888_SkColorType, and is built with SK_DEBUG\n        defined.\n\n        One word corresponds to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable unsigned 32-bit pointer to pixel\n    */\n    uint32_t* writable_addr32(int x, int y) const {\n        return const_cast<uint32_t*>(this->addr32(x, y));\n    }\n\n    /** Returns writable pixel address at (x, y). Result is addressable as unsigned\n        64-bit words. Will trigger an assert() if SkColorType is not\n        kRGBA_F16_SkColorType and is built with SK_DEBUG defined.\n\n        One word corresponds to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable unsigned 64-bit pointer to pixel\n    */\n    uint64_t* writable_addr64(int x, int y) const {\n        return const_cast<uint64_t*>(this->addr64(x, y));\n    }\n\n    /** Returns writable pixel address at (x, y). Result is addressable as unsigned\n        16-bit words. Will trigger an assert() if SkColorType is not\n        kRGBA_F16_SkColorType and is built with SK_DEBUG defined.\n\n        Each word represents one color component encoded as a half float.\n        Four words correspond to one pixel.\n\n        @param x  column index, zero or greater, and less than width()\n        @param y  row index, zero or greater, and less than height()\n        @return   writable unsigned 16-bit pointer to first component of pixel\n    */\n    uint16_t* writable_addrF16(int x, int y) const {\n        return reinterpret_cast<uint16_t*>(writable_addr64(x, y));\n    }\n\n    /** Copies a SkRect of pixels to dstPixels. Copy starts at (srcX, srcY), and does not\n        exceed SkPixmap (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and\n        SkColorSpace of destination. dstRowBytes specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if\n        dstInfo.addr() equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if width() or height() is zero or negative. Returns false if:\n        abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().\n\n        If behavior is SkTransferFunctionBehavior::kRespect: converts source\n        pixels to a linear space before converting to dstInfo.\n        If behavior is SkTransferFunctionBehavior::kIgnore: source\n        pixels are treated as if they are linear, regardless of how they are encoded.\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @param behavior     one of: SkTransferFunctionBehavior::kRespect,\n                            SkTransferFunctionBehavior::kIgnore\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY, SkTransferFunctionBehavior behavior) const;\n\n    /** Copies a SkRect of pixels to dstPixels. Copy starts at (0, 0), and does not\n        exceed SkPixmap (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and\n        SkColorSpace of destination. dstRowBytes specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if\n        dstInfo.addr() equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        Returns false if SkPixmap width() or height() is zero or negative.\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {\n        return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);\n    }\n\n    /** Copies a SkRect of pixels to dstPixels. Copy starts at (srcX, srcY), and does not\n        exceed SkPixmap (width(), height()).\n\n        dstInfo specifies width, height, SkColorType, SkAlphaType, and\n        SkColorSpace of destination. dstRowBytes specifics the gap from one destination\n        row to the next. Returns true if pixels are copied. Returns false if\n        dstInfo.addr() equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must\n        match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false if SkPixmap width() or height() is zero or negative. Returns false if:\n        abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().\n\n        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace\n        @param dstPixels    destination pixel storage\n        @param dstRowBytes  destination row length\n        @param srcX         column index whose absolute value is less than width()\n        @param srcY         row index whose absolute value is less than height()\n        @return             true if pixels are copied to dstPixels\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,\n                    int srcY) const {\n        return this->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY,\n                                SkTransferFunctionBehavior::kRespect);\n    }\n\n    /** Copies a SkRect of pixels to dst. Copy starts at (srcX, srcY), and does not\n        exceed SkPixmap (width(), height()). dst specifies width, height, SkColorType,\n        SkAlphaType, and SkColorSpace of destination.  Returns true if pixels are copied.\n        Returns false if dst.addr() equals nullptr, or dst.rowBytes() is less than\n        dst SkImageInfo::minRowBytes.\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.info().colorType must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dst.info().colorSpace must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst.info().alphaType must\n        match. If SkPixmap colorSpace() is nullptr, dst.info().colorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        srcX and srcY may be negative to copy only top or left of source. Returns\n        false SkPixmap width() or height() is zero or negative. Returns false if:\n        abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().\n\n        @param dst   SkImageInfo and pixel address to write to\n        @param srcX  column index whose absolute value is less than width()\n        @param srcY  row index whose absolute value is less than height()\n        @return      true if pixels are copied to dst\n    */\n    bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {\n        return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);\n    }\n\n    /** Copies pixels inside bounds() to dst. dst specifies width, height, SkColorType,\n        SkAlphaType, and SkColorSpace of destination.  Returns true if pixels are copied.\n        Returns false if dst.addr() equals nullptr, or dst.rowBytes() is less than\n        dst SkImageInfo::minRowBytes.\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must\n        match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        Returns false if SkPixmap width() or height() is zero or negative.\n\n        @param dst  SkImageInfo and pixel address to write to\n        @return     true if pixels are copied to dst\n    */\n    bool readPixels(const SkPixmap& dst) const {\n        return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);\n    }\n\n    /** Copies SkBitmap to dst, scaling pixels to fit dst.width() and dst.height(), and\n        converting pixels to match dst.colorType() and dst.alphaType(). Returns true if\n        pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is\n        less than dst SkImageInfo::minRowBytes.\n\n        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is\n        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.\n        If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.\n        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must\n        match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns\n        false if pixel conversion is not possible.\n\n        Returns false if SkBitmap width() or height() is zero or negative.\n\n        Scales the image, with filterQuality, to match dst.width() and dst.height().\n        filterQuality kNone_SkFilterQuality is fastest, typically implemented with\n        nearest neighbor filter. kLow_SkFilterQuality is typically implemented with\n        bilerp filter. kMedium_SkFilterQuality is typically implemented with\n        bilerp filter, and Filter_Quality_MipMap when size is reduced.\n        kHigh_SkFilterQuality is slowest, typically implemented with Filter_Quality_BiCubic.\n\n        @param dst            SkImageInfo and pixel address to write to\n        @param filterQuality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,\n                              kMedium_SkFilterQuality, kHigh_SkFilterQuality\n        @return               true if pixels are scaled to fit dst\n    */\n    bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality) const;\n\n    /** Writes color to pixels bounded by subset; returns true on success.\n        Returns false if colorType() is kUnknown_SkColorType, or if subset does\n        not intersect bounds().\n\n        @param color   unpremultiplied color to write\n        @param subset  bounding integer SkRect of written pixels\n        @return        true if pixels are changed\n    */\n    bool erase(SkColor color, const SkIRect& subset) const;\n\n    /** Writes color to pixels inside bounds(); returns true on success.\n        Returns false if colorType() is kUnknown_SkColorType, or if bounds()\n        is empty.\n\n        @param color  unpremultiplied color to write\n        @return       true if pixels are changed\n    */\n    bool erase(SkColor color) const { return this->erase(color, this->bounds()); }\n\n    /** Writes color to pixels bounded by subset; returns true on success.\n        if subset is nullptr, writes colors pixels inside bounds(). Returns false if\n        colorType() is kUnknown_SkColorType, if subset is not nullptr and does\n        not intersect bounds(), or if subset is nullptr and bounds() is empty.\n\n        @param color   unpremultiplied color to write\n        @param subset  bounding integer SkRect of pixels to write; may be nullptr\n        @return        true if pixels are changed\n    */\n    bool erase(const SkColor4f& color, const SkIRect* subset = nullptr) const;\n\nprivate:\n    const void*     fPixels;\n    size_t          fRowBytes;\n    SkImageInfo     fInfo;\n\n    friend class SkPixmapPriv;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPngChunkReader.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPngChunkReader_DEFINED\n#define SkPngChunkReader_DEFINED\n\n#include \"SkTypes.h\"\n#include \"SkRefCnt.h\"\n\n/**\n *  SkPngChunkReader\n *\n *  Base class for optional callbacks to retrieve meta/chunk data out of a PNG\n *  encoded image as it is being decoded.\n *  Used by SkCodec.\n */\nclass SkPngChunkReader : public SkRefCnt {\npublic:\n    /**\n     *  This will be called by the decoder when it sees an unknown chunk.\n     *\n     *  Use by SkCodec:\n     *  Depending on the location of the unknown chunks, this callback may be\n     *  called by\n     *      - the factory (NewFromStream/NewFromData)\n     *      - getPixels\n     *      - startScanlineDecode\n     *      - the first call to getScanlines/skipScanlines\n     *  The callback may be called from a different thread (e.g. if the SkCodec\n     *  is passed to another thread), and it may be called multiple times, if\n     *  the SkCodec is used multiple times.\n     *\n     *  @param tag Name for this type of chunk.\n     *  @param data Data to be interpreted by the subclass.\n     *  @param length Number of bytes of data in the chunk.\n     *  @return true to continue decoding, or false to indicate an error, which\n     *      will cause the decoder to not return the image.\n     */\n    virtual bool readChunk(const char tag[], const void* data, size_t length) = 0;\n};\n#endif // SkPngChunkReader_DEFINED\n"
  },
  {
    "path": "include/core/SkPoint.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPoint_DEFINED\n#define SkPoint_DEFINED\n\n#include \"SkMath.h\"\n#include \"SkScalar.h\"\n#include \"../private/SkSafe32.h\"\n\nstruct SkIPoint;\ntypedef SkIPoint SkIVector;\n\n/** \\struct SkIPoint\n    SkIPoint holds two 32-bit integer coordinates.\n*/\nstruct SkIPoint {\n    int32_t fX; //!< x-axis value\n    int32_t fY; //!< y-axis value\n\n    /** Sets fX to x, fY to y.\n\n        @param x  integer x-axis value of constructed SkIPoint\n        @param y  integer y-axis value of constructed SkIPoint\n        @return   SkIPoint (x, y)\n    */\n    static constexpr SkIPoint Make(int32_t x, int32_t y) {\n        return {x, y};\n    }\n\n    /** Returns x-axis value of SkIPoint.\n\n        @return  fX\n    */\n    int32_t x() const { return fX; }\n\n    /** Returns y-axis value of SkIPoint.\n\n        @return  fY\n    */\n    int32_t y() const { return fY; }\n\n    /** Returns true if fX and fY are both zero.\n\n        @return  true if fX is zero and fY is zero\n    */\n    bool isZero() const { return (fX | fY) == 0; }\n\n    /** Sets fX to x and fY to y.\n\n        @param x  new value for fX\n        @param y  new value for fY\n    */\n    void set(int32_t x, int32_t y) {\n        fX = x;\n        fY = y;\n    }\n\n    /** Returns SkIPoint changing the signs of fX and fY.\n\n        @return  SkIPoint as (-fX, -fY)\n    */\n    SkIPoint operator-() const {\n        return {-fX, -fY};\n    }\n\n    /** Offsets SkIPoint by ivector v. Sets SkIPoint to (fX + v.fX, fY + v.fY).\n\n        @param v  ivector to add\n    */\n    void operator+=(const SkIVector& v) {\n        fX = Sk32_sat_add(fX, v.fX);\n        fY = Sk32_sat_add(fY, v.fY);\n    }\n\n    /** Subtracts ivector v from SkIPoint. Sets SkIPoint to: (fX - v.fX, fY - v.fY).\n\n        @param v  ivector to subtract\n    */\n    void operator-=(const SkIVector& v) {\n        fX = Sk32_sat_sub(fX, v.fX);\n        fY = Sk32_sat_sub(fY, v.fY);\n    }\n\n    /** Returns true if SkIPoint is equivalent to SkIPoint constructed from (x, y).\n\n        @param x  value compared with fX\n        @param y  value compared with fY\n        @return   true if SkIPoint equals (x, y)\n    */\n    bool equals(int32_t x, int32_t y) const {\n        return fX == x && fY == y;\n    }\n\n    /** Returns true if a is equivalent to b.\n\n        @param a  SkIPoint to compare\n        @param b  SkIPoint to compare\n        @return   true if a.fX == b.fX and a.fY == b.fY\n    */\n    friend bool operator==(const SkIPoint& a, const SkIPoint& b) {\n        return a.fX == b.fX && a.fY == b.fY;\n    }\n\n    /** Returns true if a is not equivalent to b.\n\n        @param a  SkIPoint to compare\n        @param b  SkIPoint to compare\n        @return   true if a.fX != b.fX or a.fY != b.fY\n    */\n    friend bool operator!=(const SkIPoint& a, const SkIPoint& b) {\n        return a.fX != b.fX || a.fY != b.fY;\n    }\n\n    /** Returns ivector from b to a; computed as (a.fX - b.fX, a.fY - b.fY).\n\n        Can also be used to subtract ivector from ivector, returning ivector.\n\n        @param a  SkIPoint or ivector to subtract from\n        @param b  ivector to subtract\n        @return   ivector from b to a\n    */\n    friend SkIVector operator-(const SkIPoint& a, const SkIPoint& b) {\n        return { Sk32_sat_sub(a.fX, b.fX), Sk32_sat_sub(a.fY, b.fY) };\n    }\n\n    /** Returns SkIPoint resulting from SkIPoint a offset by ivector b, computed as: (a.fX + b.fX, a.fY + b.fY).\n\n        Can also be used to offset SkIPoint b by ivector a, returning SkIPoint.\n        Can also be used to add ivector to ivector, returning ivector.\n\n        @param a  SkIPoint or ivector to add to\n        @param b  SkIPoint or ivector to add\n        @return   SkIPoint equal to a offset by b\n    */\n    friend SkIPoint operator+(const SkIPoint& a, const SkIVector& b) {\n        return { Sk32_sat_add(a.fX, b.fX), Sk32_sat_add(a.fY, b.fY) };\n    }\n};\n\nstruct SkPoint;\ntypedef SkPoint SkVector;\n\n/** \\struct SkPoint\n    SkPoint holds two 32-bit floating point coordinates.\n*/\nstruct SK_API SkPoint {\n    SkScalar fX; //!< x-axis value\n    SkScalar fY; //!< y-axis value\n\n    /** Sets fX to x, fY to y. Used both to set SkPoint and vector.\n\n        @param x  SkScalar x-axis value of constructed SkPoint or vector\n        @param y  SkScalar y-axis value of constructed SkPoint or vector\n        @return   SkPoint (x, y)\n    */\n    static constexpr SkPoint Make(SkScalar x, SkScalar y) {\n        return {x, y};\n    }\n\n    /** Returns x-axis value of SkPoint or vector.\n\n        @return  fX\n    */\n    SkScalar x() const { return fX; }\n\n    /** Returns y-axis value of SkPoint or vector.\n\n        @return  fY\n    */\n    SkScalar y() const { return fY; }\n\n    /** Returns true if fX and fY are both zero.\n\n        @return  true if fX is zero and fY is zero\n    */\n    bool isZero() const { return (0 == fX) & (0 == fY); }\n\n    /** Sets fX to x and fY to y.\n\n        @param x  new value for fX\n        @param y  new value for fY\n    */\n    void set(SkScalar x, SkScalar y) {\n        fX = x;\n        fY = y;\n    }\n\n    /** Sets fX to x and fY to y, promoting integers to SkScalar values.\n\n        Assigning a large integer value directly to fX or fY may cause a compiler\n        error, triggered by narrowing conversion of int to SkScalar. This safely\n        casts x and y to avoid the error.\n\n        @param x  new value for fX\n        @param y  new value for fY\n    */\n    void iset(int32_t x, int32_t y) {\n        fX = SkIntToScalar(x);\n        fY = SkIntToScalar(y);\n    }\n\n    /** Sets fX to p.fX and fY to p.fY, promoting integers to SkScalar values.\n\n        Assigning an SkIPoint containing a large integer value directly to fX or fY may\n        cause a compiler error, triggered by narrowing conversion of int to SkScalar.\n        This safely casts p.fX and p.fY to avoid the error.\n\n        @param p  SkIPoint members promoted to SkScalar\n    */\n    void iset(const SkIPoint& p) {\n        fX = SkIntToScalar(p.fX);\n        fY = SkIntToScalar(p.fY);\n    }\n\n    /** Sets fX to absolute value of pt.fX; and fY to absolute value of pt.fY.\n\n        @param pt  members providing magnitude for fX and fY\n    */\n    void setAbs(const SkPoint& pt) {\n        fX = SkScalarAbs(pt.fX);\n        fY = SkScalarAbs(pt.fY);\n    }\n\n    /** Adds offset to each SkPoint in points array with count entries.\n\n        @param points  SkPoint array\n        @param count   entries in array\n        @param offset  vector added to points\n    */\n    static void Offset(SkPoint points[], int count, const SkVector& offset) {\n        Offset(points, count, offset.fX, offset.fY);\n    }\n\n    /** Adds offset (dx, dy) to each SkPoint in points array of length count.\n\n        @param points  SkPoint array\n        @param count   entries in array\n        @param dx      added to fX in points\n        @param dy      added to fY in points\n    */\n    static void Offset(SkPoint points[], int count, SkScalar dx, SkScalar dy) {\n        for (int i = 0; i < count; ++i) {\n            points[i].offset(dx, dy);\n        }\n    }\n\n    /** Adds offset (dx, dy) to SkPoint.\n\n        @param dx  added to fX\n        @param dy  added to fY\n    */\n    void offset(SkScalar dx, SkScalar dy) {\n        fX += dx;\n        fY += dy;\n    }\n\n    /** Returns the Euclidean_Distance from origin, computed as:\n\n            sqrt(fX * fX + fY * fY)\n\n        .\n\n        @return  straight-line distance to origin\n    */\n    SkScalar length() const { return SkPoint::Length(fX, fY); }\n\n    /** Returns the Euclidean_Distance from origin, computed as:\n\n            sqrt(fX * fX + fY * fY)\n\n        .\n\n        @return  straight-line distance to origin\n    */\n    SkScalar distanceToOrigin() const { return this->length(); }\n\n    /** Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,\n        if possible. If prior length is nearly zero, sets vector to (0, 0) and returns\n        false; otherwise returns true.\n\n        @return  true if former length is not zero or nearly zero\n    */\n    bool normalize();\n\n    /** Sets vector to (x, y) scaled so length() returns one, and so that\n        (fX, fY) is proportional to (x, y).  If (x, y) length is nearly zero,\n        sets vector to (0, 0) and returns false; otherwise returns true.\n\n        @param x  proportional value for fX\n        @param y  proportional value for fY\n        @return   true if (x, y) length is not zero or nearly zero\n    */\n    bool setNormalize(SkScalar x, SkScalar y);\n\n    /** Scales vector so that distanceToOrigin() returns length, if possible. If former\n        length is nearly zero, sets vector to (0, 0) and return false; otherwise returns\n        true.\n\n        @param length  straight-line distance to origin\n        @return        true if former length is not zero or nearly zero\n    */\n    bool setLength(SkScalar length);\n\n    /** Sets vector to (x, y) scaled to length, if possible. If former\n        length is nearly zero, sets vector to (0, 0) and return false; otherwise returns\n        true.\n\n        @param x       proportional value for fX\n        @param y       proportional value for fY\n        @param length  straight-line distance to origin\n        @return        true if (x, y) length is not zero or nearly zero\n    */\n    bool setLength(SkScalar x, SkScalar y, SkScalar length);\n\n    /** Sets dst to SkPoint times scale. dst may be SkPoint to modify SkPoint in place.\n\n        @param scale  factor to multiply SkPoint by\n        @param dst    storage for scaled SkPoint\n    */\n    void scale(SkScalar scale, SkPoint* dst) const;\n\n    /** Scales SkPoint in place by scale.\n\n        @param value  factor to multiply SkPoint by\n    */\n    void scale(SkScalar value) { this->scale(value, this); }\n\n    /** Changes the sign of fX and fY.\n    */\n    void negate() {\n        fX = -fX;\n        fY = -fY;\n    }\n\n    /** Returns SkPoint changing the signs of fX and fY.\n\n        @return  SkPoint as (-fX, -fY)\n    */\n    SkPoint operator-() const {\n        return {-fX, -fY};\n    }\n\n    /** Adds vector v to SkPoint. Sets SkPoint to: (fX + v.fX, fY + v.fY).\n\n        @param v  vector to add\n    */\n    void operator+=(const SkVector& v) {\n        fX += v.fX;\n        fY += v.fY;\n    }\n\n    /** Subtracts vector v from SkPoint. Sets SkPoint to: (fX - v.fX, fY - v.fY).\n\n        @param v  vector to subtract\n    */\n    void operator-=(const SkVector& v) {\n        fX -= v.fX;\n        fY -= v.fY;\n    }\n\n    /** Returns SkPoint multiplied by scale.\n\n        @param scale  scalar to multiply by\n        @return       SkPoint as (fX * scale, fY * scale)\n    */\n    SkPoint operator*(SkScalar scale) const {\n        return {fX * scale, fY * scale};\n    }\n\n    /** Multiplies SkPoint by scale. Sets SkPoint to: (fX * scale, fY * scale)\n\n        @param scale  scalar to multiply by\n        @return       reference to SkPoint\n    */\n    SkPoint& operator*=(SkScalar scale) {\n        fX *= scale;\n        fY *= scale;\n        return *this;\n    }\n\n    /** Returns true if both fX and fY are measurable values.\n\n        @return  true for values other than infinities and NaN\n    */\n    bool isFinite() const {\n        SkScalar accum = 0;\n        accum *= fX;\n        accum *= fY;\n\n        // accum is either NaN or it is finite (zero).\n        SkASSERT(0 == accum || SkScalarIsNaN(accum));\n\n        // value==value will be true iff value is not NaN\n        // TODO: is it faster to say !accum or accum==accum?\n        return !SkScalarIsNaN(accum);\n    }\n\n    /** Returns true if SkPoint is equivalent to SkPoint constructed from (x, y).\n\n        @param x  value compared with fX\n        @param y  value compared with fY\n        @return   true if SkPoint equals (x, y)\n    */\n    bool equals(SkScalar x, SkScalar y) const {\n        return fX == x && fY == y;\n    }\n\n    /** Returns true if a is equivalent to b.\n\n        @param a  SkPoint to compare\n        @param b  SkPoint to compare\n        @return   true if a.fX == b.fX and a.fY == b.fY\n    */\n    friend bool operator==(const SkPoint& a, const SkPoint& b) {\n        return a.fX == b.fX && a.fY == b.fY;\n    }\n\n    /** Returns true if a is not equivalent to b.\n\n        @param a  SkPoint to compare\n        @param b  SkPoint to compare\n        @return   true if a.fX != b.fX or a.fY != b.fY\n    */\n    friend bool operator!=(const SkPoint& a, const SkPoint& b) {\n        return a.fX != b.fX || a.fY != b.fY;\n    }\n\n    /** Returns vector from b to a, computed as (a.fX - b.fX, a.fY - b.fY).\n\n        Can also be used to subtract vector from SkPoint, returning SkPoint.\n        Can also be used to subtract vector from vector, returning vector.\n\n        @param a  SkPoint to subtract from\n        @param b  SkPoint to subtract\n        @return   vector from b to a\n    */\n    friend SkVector operator-(const SkPoint& a, const SkPoint& b) {\n        return {a.fX - b.fX, a.fY - b.fY};\n    }\n\n    /** Returns SkPoint resulting from SkPoint a offset by vector b, computed as: (a.fX + b.fX, a.fY + b.fY).\n\n        Can also be used to offset SkPoint b by vector a, returning SkPoint.\n        Can also be used to add vector to vector, returning vector.\n\n        @param a  SkPoint or vector to add to\n        @param b  SkPoint or vector to add\n        @return   SkPoint equal to a offset by b\n    */\n    friend SkPoint operator+(const SkPoint& a, const SkVector& b) {\n        return {a.fX + b.fX, a.fY + b.fY};\n    }\n\n    /** Returns the Euclidean_Distance from origin, computed as:\n\n            sqrt(x * x + y * y)\n\n        .\n\n        @param x  component of length\n        @param y  component of length\n        @return   straight-line distance to origin\n    */\n    static SkScalar Length(SkScalar x, SkScalar y);\n\n    /** Scales (vec->fX, vec->fY) so that length() returns one, while preserving ratio of vec->fX to vec->fY,\n        if possible. If original length is nearly zero, sets vec to (0, 0) and returns zero;\n        otherwise, returns length of vec before vec is scaled.\n\n        Returned prior length may be SK_ScalarInfinity if it can not be represented by SkScalar.\n\n        Note that normalize() is faster if prior length is not required.\n\n        @param vec  normalized to unit length\n        @return     original vec length\n    */\n    static SkScalar Normalize(SkVector* vec);\n\n    /** Returns the Euclidean_Distance between a and b.\n\n        @param a  line end point\n        @param b  line end point\n        @return   straight-line distance from a to b\n    */\n    static SkScalar Distance(const SkPoint& a, const SkPoint& b) {\n        return Length(a.fX - b.fX, a.fY - b.fY);\n    }\n\n    /** Returns the dot product of vector a and vector b.\n\n        @param a  left side of dot product\n        @param b  right side of dot product\n        @return   product of input magnitudes and cosine of the angle between them\n    */\n    static SkScalar DotProduct(const SkVector& a, const SkVector& b) {\n        return a.fX * b.fX + a.fY * b.fY;\n    }\n\n    /** Returns the cross product of vector a and vector b.\n\n        a and b form three-dimensional vectors with z-axis value equal to zero. The\n        cross product is a three-dimensional vector with x-axis and y-axis values equal\n        to zero. The cross product z-axis component is returned.\n\n        @param a  left side of cross product\n        @param b  right side of cross product\n        @return   area spanned by vectors signed by angle direction\n    */\n    static SkScalar CrossProduct(const SkVector& a, const SkVector& b) {\n        return a.fX * b.fY - a.fY * b.fX;\n    }\n\n    /** Returns the cross product of vector and vec.\n\n        Vector and vec form three-dimensional vectors with z-axis value equal to zero.\n        The cross product is a three-dimensional vector with x-axis and y-axis values\n        equal to zero. The cross product z-axis component is returned.\n\n        @param vec  right side of cross product\n        @return     area spanned by vectors signed by angle direction\n    */\n    SkScalar cross(const SkVector& vec) const {\n        return CrossProduct(*this, vec);\n    }\n\n    /** Returns the dot product of vector and vector vec.\n\n        @param vec  right side of dot product\n        @return     product of input magnitudes and cosine of the angle between them\n    */\n    SkScalar dot(const SkVector& vec) const {\n        return DotProduct(*this, vec);\n    }\n\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkPoint3.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPoint3_DEFINED\n#define SkPoint3_DEFINED\n\n#include \"SkPoint.h\"\n\nstruct SK_API SkPoint3 {\n    SkScalar fX, fY, fZ;\n\n    static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z) {\n        SkPoint3 pt;\n        pt.set(x, y, z);\n        return pt;\n    }\n\n    SkScalar x() const { return fX; }\n    SkScalar y() const { return fY; }\n    SkScalar z() const { return fZ; }\n\n    void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; }\n\n    friend bool operator==(const SkPoint3& a, const SkPoint3& b) {\n        return a.fX == b.fX && a.fY == b.fY && a.fZ == b.fZ;\n    }\n\n    friend bool operator!=(const SkPoint3& a, const SkPoint3& b) {\n        return !(a == b);\n    }\n\n    /** Returns the Euclidian distance from (0,0,0) to (x,y,z)\n    */\n    static SkScalar Length(SkScalar x, SkScalar y, SkScalar z);\n\n    /** Return the Euclidian distance from (0,0,0) to the point\n    */\n    SkScalar length() const { return SkPoint3::Length(fX, fY, fZ); }\n\n    /** Set the point (vector) to be unit-length in the same direction as it\n        already points.  If the point has a degenerate length (i.e., nearly 0)\n        then set it to (0,0,0) and return false; otherwise return true.\n    */\n    bool normalize();\n\n    /** Return a new point whose X, Y and Z coordinates are scaled.\n    */\n    SkPoint3 makeScale(SkScalar scale) const {\n        SkPoint3 p;\n        p.set(scale * fX, scale * fY, scale * fZ);\n        return p;\n    }\n\n    /** Scale the point's coordinates by scale.\n    */\n    void scale(SkScalar value) {\n        fX *= value;\n        fY *= value;\n        fZ *= value;\n    }\n\n    /** Return a new point whose X, Y and Z coordinates are the negative of the\n        original point's\n    */\n    SkPoint3 operator-() const {\n        SkPoint3 neg;\n        neg.fX = -fX;\n        neg.fY = -fY;\n        neg.fZ = -fZ;\n        return neg;\n    }\n\n    /** Returns a new point whose coordinates are the difference between\n        a and b (i.e., a - b)\n    */\n    friend SkPoint3 operator-(const SkPoint3& a, const SkPoint3& b) {\n        SkPoint3 v;\n        v.set(a.fX - b.fX, a.fY - b.fY, a.fZ - b.fZ);\n        return v;\n    }\n\n    /** Returns a new point whose coordinates are the sum of a and b (a + b)\n    */\n    friend SkPoint3 operator+(const SkPoint3& a, const SkPoint3& b) {\n        SkPoint3 v;\n        v.set(a.fX + b.fX, a.fY + b.fY, a.fZ + b.fZ);\n        return v;\n    }\n\n    /** Add v's coordinates to the point's\n    */\n    void operator+=(const SkPoint3& v) {\n        fX += v.fX;\n        fY += v.fY;\n        fZ += v.fZ;\n    }\n\n    /** Subtract v's coordinates from the point's\n    */\n    void operator-=(const SkPoint3& v) {\n        fX -= v.fX;\n        fY -= v.fY;\n        fZ -= v.fZ;\n    }\n\n    /** Returns true if fX, fY, and fZ are measurable values.\n\n     @return  true for values other than infinities and NaN\n     */\n    bool isFinite() const {\n        SkScalar accum = 0;\n        accum *= fX;\n        accum *= fY;\n        accum *= fZ;\n\n        // accum is either NaN or it is finite (zero).\n        SkASSERT(0 == accum || SkScalarIsNaN(accum));\n\n        // value==value will be true iff value is not NaN\n        // TODO: is it faster to say !accum or accum==accum?\n        return !SkScalarIsNaN(accum);\n    }\n\n    /** Returns the dot product of a and b, treating them as 3D vectors\n    */\n    static SkScalar DotProduct(const SkPoint3& a, const SkPoint3& b) {\n        return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;\n    }\n\n    SkScalar dot(const SkPoint3& vec) const {\n        return DotProduct(*this, vec);\n    }\n};\n\ntypedef SkPoint3 SkVector3;\ntypedef SkPoint3 SkColor3f;\n\n#endif\n"
  },
  {
    "path": "include/core/SkPostConfig.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// IWYU pragma: private, include \"SkTypes.h\"\n\n#ifndef SkPostConfig_DEFINED\n#define SkPostConfig_DEFINED\n\n#if !defined(SK_DEBUG) && !defined(SK_RELEASE)\n    #ifdef NDEBUG\n        #define SK_RELEASE\n    #else\n        #define SK_DEBUG\n    #endif\n#endif\n\n#if defined(SK_DEBUG) && defined(SK_RELEASE)\n#  error \"cannot define both SK_DEBUG and SK_RELEASE\"\n#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)\n#  error \"must define either SK_DEBUG or SK_RELEASE\"\n#endif\n\n#if defined(SK_SUPPORT_UNITTEST) && !defined(SK_DEBUG)\n#  error \"can't have unittests without debug\"\n#endif\n\n/**\n * Matrix calculations may be float or double.\n * The default is float, as that's what Chromium's using.\n */\n#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT)\n#  error \"cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT\"\n#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT)\n#  define SK_MSCALAR_IS_FLOAT\n#endif\n\n#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)\n#  error \"cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN\"\n#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)\n#  error \"must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN\"\n#endif\n\n/**\n * Ensure the port has defined all of SK_X32_SHIFT, or none of them.\n */\n#ifdef SK_A32_SHIFT\n#  if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)\n#    error \"all or none of the 32bit SHIFT amounts must be defined\"\n#  endif\n#else\n#  if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)\n#    error \"all or none of the 32bit SHIFT amounts must be defined\"\n#  endif\n#endif\n\n#if !defined(SK_HAS_COMPILER_FEATURE)\n#  if defined(__has_feature)\n#    define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)\n#  else\n#    define SK_HAS_COMPILER_FEATURE(x) 0\n#  endif\n#endif\n\n#if !defined(SK_ATTRIBUTE)\n#  if defined(__clang__) || defined(__GNUC__)\n#    define SK_ATTRIBUTE(attr) __attribute__((attr))\n#  else\n#    define SK_ATTRIBUTE(attr)\n#  endif\n#endif\n\n#if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2\n    #define SK_VECTORCALL __vectorcall\n#elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)\n    #define SK_VECTORCALL __attribute__((pcs(\"aapcs-vfp\")))\n#else\n    #define SK_VECTORCALL\n#endif\n\n#if !defined(SK_SUPPORT_GPU)\n#  define SK_SUPPORT_GPU 1\n#endif\n\n#if !defined(SK_SUPPORT_ATLAS_TEXT)\n#  define SK_SUPPORT_ATLAS_TEXT 0\n#elif SK_SUPPORT_ATLAS_TEXT && !SK_SUPPORT_GPU\n#  error \"SK_SUPPORT_ATLAS_TEXT requires SK_SUPPORT_GPU\"\n#endif\n\n/**\n * The clang static analyzer likes to know that when the program is not\n * expected to continue (crash, assertion failure, etc). It will notice that\n * some combination of parameters lead to a function call that does not return.\n * It can then make appropriate assumptions about the parameters in code\n * executed only if the non-returning function was *not* called.\n */\n#if !defined(SkNO_RETURN_HINT)\n#  if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)\n     static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));\n     static inline void SkNO_RETURN_HINT() {}\n#  else\n#    define SkNO_RETURN_HINT() do {} while (false)\n#  endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n// TODO(mdempsky): Move elsewhere as appropriate.\n#include <new>\n\n\n///////////////////////////////////////////////////////////////////////////////\n\n#ifdef SK_BUILD_FOR_WIN\n#  ifndef SK_A32_SHIFT\n#    define SK_A32_SHIFT 24\n#    define SK_R32_SHIFT 16\n#    define SK_G32_SHIFT 8\n#    define SK_B32_SHIFT 0\n#  endif\n#\n#endif\n\n#if defined(SK_BUILD_FOR_GOOGLE3)\n    void SkDebugfForDumpStackTrace(const char* data, void* unused);\n    void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);\n#  define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)\n#else\n#  define SK_DUMP_GOOGLE3_STACK()\n#endif\n\n#ifdef SK_BUILD_FOR_WIN\n// permits visual studio to follow error back to source\n#define SK_DUMP_LINE_FORMAT(message) \\\n    SkDebugf(\"%s(%d): fatal error: \\\"%s\\\"\\n\", __FILE__, __LINE__, message)\n#else\n#define SK_DUMP_LINE_FORMAT(message) \\\n    SkDebugf(\"%s:%d: fatal error: \\\"%s\\\"\\n\", __FILE__, __LINE__, message)\n#endif\n\n#ifndef SK_ABORT\n#  define SK_ABORT(message) \\\n    do { \\\n       SkNO_RETURN_HINT(); \\\n       SK_DUMP_LINE_FORMAT(message); \\\n       SK_DUMP_GOOGLE3_STACK(); \\\n       sk_abort_no_print(); \\\n    } while (false)\n#endif\n\n/**\n *  We check to see if the SHIFT value has already been defined.\n *  if not, we define it ourself to some default values. We default to OpenGL\n *  order (in memory: r,g,b,a)\n */\n#ifndef SK_A32_SHIFT\n#  ifdef SK_CPU_BENDIAN\n#    define SK_R32_SHIFT    24\n#    define SK_G32_SHIFT    16\n#    define SK_B32_SHIFT    8\n#    define SK_A32_SHIFT    0\n#  else\n#    define SK_R32_SHIFT    0\n#    define SK_G32_SHIFT    8\n#    define SK_B32_SHIFT    16\n#    define SK_A32_SHIFT    24\n#  endif\n#endif\n\n/**\n * SkColor has well defined shift values, but SkPMColor is configurable. This\n * macro is a convenience that returns true if the shift values are equal while\n * ignoring the machine's endianness.\n */\n#define SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER \\\n    (SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 0)\n\n/**\n * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The\n * relationship between the byte order and shift values depends on machine endianness. If the shift\n * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little\n * endian machine and the A channel on a big endian machine. Thus, given those shifts values,\n * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and\n * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.\n */\n#ifdef SK_CPU_BENDIAN\n#  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \\\n        (SK_ ## C3 ## 32_SHIFT == 0  &&             \\\n         SK_ ## C2 ## 32_SHIFT == 8  &&             \\\n         SK_ ## C1 ## 32_SHIFT == 16 &&             \\\n         SK_ ## C0 ## 32_SHIFT == 24)\n#else\n#  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \\\n        (SK_ ## C0 ## 32_SHIFT == 0  &&             \\\n         SK_ ## C1 ## 32_SHIFT == 8  &&             \\\n         SK_ ## C2 ## 32_SHIFT == 16 &&             \\\n         SK_ ## C3 ## 32_SHIFT == 24)\n#endif\n\n//////////////////////////////////////////////////////////////////////////////////////////////\n\n#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN\n#  ifdef free\n#    undef free\n#  endif\n#  include <crtdbg.h>\n#  undef free\n#\n#  ifdef SK_DEBUGx\n#    if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)\n       void * operator new(\n           size_t cb,\n           int nBlockUse,\n           const char * szFileName,\n           int nLine,\n           int foo\n           );\n       void * operator new[](\n           size_t cb,\n           int nBlockUse,\n           const char * szFileName,\n           int nLine,\n           int foo\n           );\n       void operator delete(\n           void *pUserData,\n           int, const char*, int, int\n           );\n       void operator delete(\n           void *pUserData\n           );\n       void operator delete[]( void * p );\n#      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)\n#    else\n#      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)\n#    endif\n#    define new DEBUG_CLIENTBLOCK\n#  else\n#    define DEBUG_CLIENTBLOCK\n#  endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if !defined(SK_UNUSED)\n#  if !defined(__clang__) && defined(_MSC_VER)\n#    define SK_UNUSED __pragma(warning(suppress:4189))\n#  else\n#    define SK_UNUSED SK_ATTRIBUTE(unused)\n#  endif\n#endif\n\n#if !defined(SK_ATTR_DEPRECATED)\n   // FIXME: we ignore msg for now...\n#  define SK_ATTR_DEPRECATED(msg) SK_ATTRIBUTE(deprecated)\n#endif\n\n/**\n * If your judgment is better than the compiler's (i.e. you've profiled it),\n * you can use SK_ALWAYS_INLINE to force inlining. E.g.\n *     inline void someMethod() { ... }             // may not be inlined\n *     SK_ALWAYS_INLINE void someMethod() { ... }   // should always be inlined\n */\n#if !defined(SK_ALWAYS_INLINE)\n#  if defined(SK_BUILD_FOR_WIN)\n#    define SK_ALWAYS_INLINE __forceinline\n#  else\n#    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline\n#  endif\n#endif\n\n/**\n * If your judgment is better than the compiler's (i.e. you've profiled it),\n * you can use SK_NEVER_INLINE to prevent inlining.\n */\n#if !defined(SK_NEVER_INLINE)\n#  if defined(SK_BUILD_FOR_WIN)\n#    define SK_NEVER_INLINE __declspec(noinline)\n#  else\n#    define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)\n#  endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1\n    #define SK_PREFETCH(ptr)       _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)\n    #define SK_WRITE_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)\n#elif defined(__GNUC__)\n    #define SK_PREFETCH(ptr)       __builtin_prefetch(ptr)\n    #define SK_WRITE_PREFETCH(ptr) __builtin_prefetch(ptr, 1)\n#else\n    #define SK_PREFETCH(ptr)\n    #define SK_WRITE_PREFETCH(ptr)\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifndef SK_PRINTF_LIKE\n#  if defined(__clang__) || defined(__GNUC__)\n#    define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))\n#  else\n#    define SK_PRINTF_LIKE(A, B)\n#  endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifndef SK_SIZE_T_SPECIFIER\n#  if defined(_MSC_VER) && !defined(__clang__)\n#    define SK_SIZE_T_SPECIFIER \"%Iu\"\n#  else\n#    define SK_SIZE_T_SPECIFIER \"%zu\"\n#  endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS\n#  define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifndef SK_EGL\n#  if defined(SK_BUILD_FOR_ANDROID)\n#    define SK_EGL 1\n#  else\n#    define SK_EGL 0\n#  endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if !defined(SK_GAMMA_EXPONENT)\n    #define SK_GAMMA_EXPONENT (0.0f)  // SRGB\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifndef GR_TEST_UTILS\n#  define GR_TEST_UTILS 0\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if defined(SK_HISTOGRAM_ENUMERATION) && defined(SK_HISTOGRAM_BOOLEAN)\n#  define SK_HISTOGRAMS_ENABLED 1\n#else\n#  define SK_HISTOGRAMS_ENABLED 0\n#endif\n\n#ifndef SK_HISTOGRAM_BOOLEAN\n#  define SK_HISTOGRAM_BOOLEAN(name, value)\n#endif\n\n#ifndef SK_HISTOGRAM_ENUMERATION\n#  define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)\n#endif\n\n#endif // SkPostConfig_DEFINED\n"
  },
  {
    "path": "include/core/SkPreConfig.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n// IWYU pragma: private, include \"SkTypes.h\"\n\n#ifndef SkPreConfig_DEFINED\n#define SkPreConfig_DEFINED\n\n// Allows embedders that want to disable macros that take arguments to just\n// define that symbol to be one of these\n#define SK_NOTHING_ARG1(arg1)\n#define SK_NOTHING_ARG2(arg1, arg2)\n#define SK_NOTHING_ARG3(arg1, arg2, arg3)\n\n//////////////////////////////////////////////////////////////////////\n\n#if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC)\n\n    #ifdef __APPLE__\n        #include \"TargetConditionals.h\"\n    #endif\n\n    #if defined(_WIN32) || defined(__SYMBIAN32__)\n        #define SK_BUILD_FOR_WIN\n    #elif defined(ANDROID) || defined(__ANDROID__)\n        #define SK_BUILD_FOR_ANDROID\n    #elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \\\n          defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \\\n          defined(__DragonFly__) || defined(__Fuchsia__) || \\\n          defined(__GLIBC__) || defined(__GNU__) || defined(__unix__)\n        #define SK_BUILD_FOR_UNIX\n    #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR\n        #define SK_BUILD_FOR_IOS\n    #else\n        #define SK_BUILD_FOR_MAC\n    #endif\n\n#endif\n\n/* Even if the user only defined the framework variant we still need to build\n * the default (NDK-compliant) Android code. Therefore, when attempting to\n * include/exclude something from the framework variant check first that we are\n * building for Android then check the status of the framework define.\n */\n#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && !defined(SK_BUILD_FOR_ANDROID)\n    #define SK_BUILD_FOR_ANDROID\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#ifdef SK_BUILD_FOR_WIN\n    #if !defined(SK_RESTRICT)\n        #define SK_RESTRICT __restrict\n    #endif\n    #if !defined(SK_WARN_UNUSED_RESULT)\n        #define SK_WARN_UNUSED_RESULT\n    #endif\n#endif\n\n#if !defined(SK_RESTRICT)\n    #define SK_RESTRICT __restrict__\n#endif\n\n#if !defined(SK_WARN_UNUSED_RESULT)\n    #define SK_WARN_UNUSED_RESULT __attribute__((warn_unused_result))\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)\n    #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n        #define SK_CPU_BENDIAN\n    #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n        #define SK_CPU_LENDIAN\n    #elif defined(__sparc) || defined(__sparc__) || \\\n      defined(_POWER) || defined(__powerpc__) || \\\n      defined(__ppc__) || defined(__hppa) || \\\n      defined(__PPC__) || defined(__PPC64__) || \\\n      defined(_MIPSEB) || defined(__ARMEB__) || \\\n      defined(__s390__) || \\\n      (defined(__sh__) && defined(__BIG_ENDIAN__)) || \\\n      (defined(__ia64) && defined(__BIG_ENDIAN__))\n         #define SK_CPU_BENDIAN\n    #else\n        #define SK_CPU_LENDIAN\n    #endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if defined(__i386) || defined(_M_IX86) ||  defined(__x86_64__) || defined(_M_X64)\n  #define SK_CPU_X86 1\n#endif\n\n/**\n *  SK_CPU_SSE_LEVEL\n *\n *  If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.\n *  On non-intel CPU this should be undefined.\n */\n\n#define SK_CPU_SSE_LEVEL_SSE1     10\n#define SK_CPU_SSE_LEVEL_SSE2     20\n#define SK_CPU_SSE_LEVEL_SSE3     30\n#define SK_CPU_SSE_LEVEL_SSSE3    31\n#define SK_CPU_SSE_LEVEL_SSE41    41\n#define SK_CPU_SSE_LEVEL_SSE42    42\n#define SK_CPU_SSE_LEVEL_AVX      51\n#define SK_CPU_SSE_LEVEL_AVX2     52\n\n// When targetting iOS and using gyp to generate the build files, it is not\n// possible to select files to build depending on the architecture (i.e. it\n// is not possible to use hand optimized assembly implementation). In that\n// configuration SK_BUILD_NO_OPTS is defined. Remove optimisation then.\n#ifdef SK_BUILD_NO_OPTS\n    #define SK_CPU_SSE_LEVEL 0\n#endif\n\n// Are we in GCC?\n#ifndef SK_CPU_SSE_LEVEL\n    // These checks must be done in descending order to ensure we set the highest\n    // available SSE level.\n    #if defined(__AVX2__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX2\n    #elif defined(__AVX__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX\n    #elif defined(__SSE4_2__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE42\n    #elif defined(__SSE4_1__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE41\n    #elif defined(__SSSE3__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSSE3\n    #elif defined(__SSE3__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE3\n    #elif defined(__SSE2__)\n        #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2\n    #endif\n#endif\n\n// Are we in VisualStudio?\n#ifndef SK_CPU_SSE_LEVEL\n    // These checks must be done in descending order to ensure we set the highest\n    // available SSE level. 64-bit intel guarantees at least SSE2 support.\n    #if defined(__AVX2__)\n        #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX2\n    #elif defined(__AVX__)\n        #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX\n    #elif defined(_M_X64) || defined(_M_AMD64)\n        #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_SSE2\n    #elif defined(_M_IX86_FP)\n        #if _M_IX86_FP >= 2\n            #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2\n        #elif _M_IX86_FP == 1\n            #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE1\n        #endif\n    #endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n// ARM defines\n\n#if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)\n    #define SK_CPU_ARM32\n\n    #if defined(__GNUC__)\n        #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \\\n                || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \\\n                || defined(__ARM_ARCH_7EM__) || defined(_ARM_ARCH_7)\n            #define SK_ARM_ARCH 7\n        #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \\\n                || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \\\n                || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \\\n                || defined(__ARM_ARCH_6M__) || defined(_ARM_ARCH_6)\n            #define SK_ARM_ARCH 6\n        #elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \\\n                || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \\\n                || defined(__ARM_ARCH_5TEJ__) || defined(_ARM_ARCH_5)\n            #define SK_ARM_ARCH 5\n        #elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || defined(_ARM_ARCH_4)\n            #define SK_ARM_ARCH 4\n        #else\n            #define SK_ARM_ARCH 3\n        #endif\n    #endif\n#endif\n\n#if defined(__aarch64__) && !defined(SK_BUILD_NO_OPTS)\n    #define SK_CPU_ARM64\n#endif\n\n// All 64-bit ARM chips have NEON.  Many 32-bit ARM chips do too.\n#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_NO_OPTS) && (defined(__ARM_NEON__) || defined(__ARM_NEON))\n    #define SK_ARM_HAS_NEON\n#endif\n\n// Really this __APPLE__ check shouldn't be necessary, but it seems that Apple's Clang defines\n// __ARM_FEATURE_CRC32 for -arch arm64, even though their chips don't support those instructions!\n#if defined(__ARM_FEATURE_CRC32) && !defined(__APPLE__)\n    #define SK_ARM_HAS_CRC32\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n#if !defined(SKIA_IMPLEMENTATION)\n    #define SKIA_IMPLEMENTATION 0\n#endif\n\n#if !defined(SK_API)\n    #if defined(SKIA_DLL)\n        #if defined(_MSC_VER)\n            #if SKIA_IMPLEMENTATION\n                #define SK_API __declspec(dllexport)\n            #else\n                #define SK_API __declspec(dllimport)\n            #endif\n        #else\n            #define SK_API __attribute__((visibility(\"default\")))\n        #endif\n    #else\n        #define SK_API\n    #endif\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n/**\n * Use SK_PURE_FUNC as an attribute to indicate that a function's\n * return value only depends on the value of its parameters. This\n * can help the compiler optimize out successive calls.\n *\n * Usage:\n *      void  function(int params)  SK_PURE_FUNC;\n */\n#if defined(__GNUC__)\n#  define  SK_PURE_FUNC  __attribute__((pure))\n#else\n#  define  SK_PURE_FUNC  /* nothing */\n#endif\n\n//////////////////////////////////////////////////////////////////////\n\n/**\n * SK_HAS_ATTRIBUTE(<name>) should return true iff the compiler\n * supports __attribute__((<name>)). Mostly important because\n * Clang doesn't support all of GCC attributes.\n */\n#if defined(__has_attribute)\n#   define SK_HAS_ATTRIBUTE(x) __has_attribute(x)\n#elif defined(__GNUC__)\n#   define SK_HAS_ATTRIBUTE(x) 1\n#else\n#   define SK_HAS_ATTRIBUTE(x) 0\n#endif\n\n/**\n * SK_ATTRIBUTE_OPTIMIZE_O1 can be used as a function attribute\n * to specify individual optimization level of -O1, if the compiler\n * supports it.\n *\n * NOTE: Clang/ARM (r161757) does not support the 'optimize' attribute.\n */\n#if SK_HAS_ATTRIBUTE(optimize)\n#   define SK_ATTRIBUTE_OPTIMIZE_O1 __attribute__((optimize(\"O1\")))\n#else\n#   define SK_ATTRIBUTE_OPTIMIZE_O1 /* nothing */\n#endif\n\n#endif\n"
  },
  {
    "path": "include/core/SkRRect.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRRect_DEFINED\n#define SkRRect_DEFINED\n\n#include \"SkRect.h\"\n#include \"SkPoint.h\"\n\nclass SkPath;\nclass SkMatrix;\nclass SkRBuffer;\nclass SkWBuffer;\n\n// Path forward:\n//   core work\n//      add contains(SkRect&)  - for clip stack\n//      add contains(SkRRect&) - for clip stack\n//      add heart rect computation (max rect inside RR)\n//      add 9patch rect computation\n//      add growToInclude(SkPath&)\n//   analysis\n//      use growToInclude to fit skp round rects & generate stats (RRs vs. real paths)\n//      check on # of rectorus's the RRs could handle\n//   rendering work\n//      update SkPath.addRRect() to only use quads\n//      add GM and bench\n//   further out\n//      detect and triangulate RRectorii rather than falling back to SW in Ganesh\n//\n\n/** \\class SkRRect\n\n    The SkRRect class represents a rounded rect with a potentially different\n    radii for each corner. It does not have a constructor so must be\n    initialized with one of the initialization functions (e.g., setEmpty,\n    setRectRadii, etc.)\n\n    This class is intended to roughly match CSS' border-*-*-radius capabilities.\n    This means:\n        If either of a corner's radii are 0 the corner will be square.\n        Negative radii are not allowed (they are clamped to zero).\n        If the corner curves overlap they will be proportionally reduced to fit.\n*/\nclass SK_API SkRRect {\npublic:\n    /** Default initialized to a rrect at the origin with zero width and height. */\n    SkRRect() = default;\n\n    SkRRect(const SkRRect&) = default;\n    SkRRect& operator=(const SkRRect&) = default;\n\n    /**\n     * Enum to capture the various possible subtypes of RR. Accessed\n     * by type(). The subtypes become progressively less restrictive.\n     */\n    enum Type {\n        // !< The RR has zero width and/or zero height. All radii are zero.\n        kEmpty_Type,\n\n        //!< The RR is actually a (non-empty) rect (i.e., at least one radius\n        //!< at each corner is zero)\n        kRect_Type,\n\n        //!< The RR is actually a (non-empty) oval (i.e., all x radii are equal\n        //!< and >= width/2 and all the y radii are equal and >= height/2\n        kOval_Type,\n\n        //!< The RR is non-empty and all the x radii are equal & all y radii\n        //!< are equal but it is not an oval (i.e., there are lines between\n        //!< the curves) nor a rect (i.e., both radii are non-zero)\n        kSimple_Type,\n\n        //!< The RR is non-empty and the two left x radii are equal, the two top\n        //!< y radii are equal, and the same for the right and bottom but it is\n        //!< neither an rect, oval, nor a simple RR. It is called \"nine patch\"\n        //!< because the centers of the corner ellipses form an axis aligned\n        //!< rect with edges that divide the RR into an 9 rectangular patches:\n        //!< an interior patch, four edge patches, and four corner patches.\n        kNinePatch_Type,\n\n        //!< A fully general (non-empty) RR. Some of the x and/or y radii are\n        //!< different from the others and there must be one corner where\n        //!< both radii are non-zero.\n        kComplex_Type,\n\n        kLastType = kComplex_Type,\n    };\n\n    /**\n     * Returns the RR's sub type.\n     */\n    Type getType() const {\n        SkASSERT(this->isValid());\n        return static_cast<Type>(fType);\n    }\n\n    Type type() const { return this->getType(); }\n\n    inline bool isEmpty() const { return kEmpty_Type == this->getType(); }\n    inline bool isRect() const { return kRect_Type == this->getType(); }\n    inline bool isOval() const { return kOval_Type == this->getType(); }\n    inline bool isSimple() const { return kSimple_Type == this->getType(); }\n    inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }\n    inline bool isComplex() const { return kComplex_Type == this->getType(); }\n\n    SkScalar width() const { return fRect.width(); }\n    SkScalar height() const { return fRect.height(); }\n\n    /**\n     *  kSimple means that all corners have the same x,y radii. This returns the top/left\n     *  corner's radii as representative of all corners. If the RRect is kComplex, then\n     *  this still returns that corner's radii, but it is not indicative of the other corners.\n     */\n    SkVector getSimpleRadii() const {\n        return fRadii[0];\n    }\n\n    /**\n     * Same as default initialized - zero width and height at the origin.\n     */\n    void setEmpty() { *this = SkRRect(); }\n\n    /**\n     * Set this RR to match the supplied rect. All radii will be 0.\n     */\n    void setRect(const SkRect& rect) {\n        if (!this->initializeRect(rect)) {\n            return;\n        }\n\n        memset(fRadii, 0, sizeof(fRadii));\n        fType = kRect_Type;\n\n        SkASSERT(this->isValid());\n    }\n\n    /** Makes an empty rrect at the origin with zero width and height. */\n    static SkRRect MakeEmpty() { return SkRRect(); }\n\n    static SkRRect MakeRect(const SkRect& r) {\n        SkRRect rr;\n        rr.setRect(r);\n        return rr;\n    }\n\n    static SkRRect MakeOval(const SkRect& oval) {\n        SkRRect rr;\n        rr.setOval(oval);\n        return rr;\n    }\n\n    static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {\n        SkRRect rr;\n        rr.setRectXY(rect, xRad, yRad);\n        return rr;\n    }\n\n    /**\n     * Set this RR to match the supplied oval. All x radii will equal half the\n     * width and all y radii will equal half the height.\n     */\n    void setOval(const SkRect& oval) {\n        if (!this->initializeRect(oval)) {\n            return;\n        }\n\n        SkScalar xRad = SkScalarHalf(fRect.width());\n        SkScalar yRad = SkScalarHalf(fRect.height());\n\n        for (int i = 0; i < 4; ++i) {\n            fRadii[i].set(xRad, yRad);\n        }\n        fType = kOval_Type;\n\n        SkASSERT(this->isValid());\n    }\n\n    /**\n     * Initialize the RR with the same radii for all four corners.\n     */\n    void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);\n\n    /**\n     * Initialize the rr with one radius per-side.\n     */\n    void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,\n                      SkScalar rightRad, SkScalar bottomRad);\n\n    /**\n     * Initialize the RR with potentially different radii for all four corners.\n     */\n    void setRectRadii(const SkRect& rect, const SkVector radii[4]);\n\n    // The radii are stored in UL, UR, LR, LL order.\n    enum Corner {\n        kUpperLeft_Corner,\n        kUpperRight_Corner,\n        kLowerRight_Corner,\n        kLowerLeft_Corner\n    };\n\n    const SkRect& rect() const { return fRect; }\n    SkVector radii(Corner corner) const { return fRadii[corner]; }\n    const SkRect& getBounds() const { return fRect; }\n\n    friend bool operator==(const SkRRect& a, const SkRRect& b) {\n        return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);\n    }\n\n    friend bool operator!=(const SkRRect& a, const SkRRect& b) {\n        return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);\n    }\n\n    /**\n     *  Call inset on the bounds, and adjust the radii to reflect what happens\n     *  in stroking: If the corner is sharp (no curvature), leave it alone,\n     *  otherwise we grow/shrink the radii by the amount of the inset. If a\n     *  given radius becomes negative, it is pinned to 0.\n     *\n     *  If the inset amount is larger than the width/height then the rrect collapses to\n     *  a degenerate line or point.\n     *\n     *  If the inset is sufficiently negative to cause the bounds to become infinite then\n     *  the result is a default initialized rrect.\n     *\n     *  It is valid for dst == this.\n     */\n    void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;\n\n    void inset(SkScalar dx, SkScalar dy) {\n        this->inset(dx, dy, this);\n    }\n\n    /**\n     *  Call outset on the bounds, and adjust the radii to reflect what happens\n     *  in stroking: If the corner is sharp (no curvature), leave it alone,\n     *  otherwise we grow/shrink the radii by the amount of the inset. If a\n     *  given radius becomes negative, it is pinned to 0.\n     *\n     *  It is valid for dst == this.\n     */\n    void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {\n        this->inset(-dx, -dy, dst);\n    }\n    void outset(SkScalar dx, SkScalar dy) {\n        this->inset(-dx, -dy, this);\n    }\n\n    /**\n     * Translate the rrect by (dx, dy).\n     */\n    void offset(SkScalar dx, SkScalar dy) {\n        fRect.offset(dx, dy);\n    }\n\n    SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const {\n        return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);\n    }\n\n    /**\n     *  Returns true if 'rect' is wholy inside the RR, and both\n     *  are not empty.\n     */\n    bool contains(const SkRect& rect) const;\n\n    bool isValid() const;\n\n    static constexpr size_t kSizeInMemory = 12 * sizeof(SkScalar);\n\n    /**\n     *  Write the rrect into the specified buffer. This is guaranteed to always\n     *  write kSizeInMemory bytes, and that value is guaranteed to always be\n     *  a multiple of 4. Return kSizeInMemory.\n     */\n    size_t writeToMemory(void* buffer) const;\n    void writeToBuffer(SkWBuffer*) const;\n\n    /**\n     * Reads the rrect from the specified buffer\n     *\n     * If the specified buffer is large enough, this will read kSizeInMemory bytes,\n     * and that value is guaranteed to always be a multiple of 4.\n     *\n     * @param buffer Memory to read from\n     * @param length Amount of memory available in the buffer\n     * @return number of bytes read (must be a multiple of 4) or\n     *         0 if there was not enough memory available\n     */\n    size_t readFromMemory(const void* buffer, size_t length);\n    bool readFromBuffer(SkRBuffer*);\n\n    /**\n     *  Transform by the specified matrix, and put the result in dst.\n     *\n     *  @param matrix SkMatrix specifying the transform. Must only contain\n     *      scale and/or translate, or this call will fail.\n     *  @param dst SkRRect to store the result. It is an error to use this,\n     *      which would make this function no longer const.\n     *  @return true on success, false on failure.\n     */\n    bool transform(const SkMatrix& matrix, SkRRect* dst) const;\n\n    void dump(bool asHex) const;\n    void dump() const { this->dump(false); }\n    void dumpHex() const { this->dump(true); }\n\nprivate:\n    static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]);\n\n    SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)\n        : fRect(rect)\n        , fRadii{radii[0], radii[1], radii[2], radii[3]}\n        , fType(type) {}\n\n    /**\n     * Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully\n     * initialized and false is returned. Otherwise, just fRect is initialized and true is returned.\n     */\n    bool initializeRect(const SkRect&);\n\n    void computeType();\n    bool checkCornerContainment(SkScalar x, SkScalar y) const;\n    void scaleRadii(const SkRect& rect);\n\n    SkRect fRect = SkRect::MakeEmpty();\n    // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]\n    SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}};\n    // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)\n    int32_t fType = kEmpty_Type;\n    // TODO: add padding so we can use memcpy for flattening and not copy uninitialized data\n\n    // to access fRadii directly\n    friend class SkPath;\n    friend class SkRRectPriv;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkRSXform.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRSXform_DEFINED\n#define SkRSXform_DEFINED\n\n#include \"SkPoint.h\"\n#include \"SkSize.h\"\n\n/**\n *  A compressed form of a rotation+scale matrix.\n *\n *  [ fSCos     -fSSin    fTx ]\n *  [ fSSin      fSCos    fTy ]\n *  [     0          0      1 ]\n */\nstruct SkRSXform {\n    static SkRSXform Make(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {\n        SkRSXform xform = { scos, ssin, tx, ty };\n        return xform;\n    }\n\n    /*\n     *  Initialize a new xform based on the scale, rotation (in radians), final tx,ty location\n     *  and anchor-point ax,ay within the src quad.\n     *\n     *  Note: the anchor point is not normalized (e.g. 0...1) but is in pixels of the src image.\n     */\n    static SkRSXform MakeFromRadians(SkScalar scale, SkScalar radians, SkScalar tx, SkScalar ty,\n                                     SkScalar ax, SkScalar ay) {\n        const SkScalar s = SkScalarSin(radians) * scale;\n        const SkScalar c = SkScalarCos(radians) * scale;\n        return Make(c, s, tx + -c * ax + s * ay, ty + -s * ax - c * ay);\n    }\n\n    SkScalar fSCos;\n    SkScalar fSSin;\n    SkScalar fTx;\n    SkScalar fTy;\n\n    bool rectStaysRect() const {\n        return 0 == fSCos || 0 == fSSin;\n    }\n\n    void setIdentity() {\n        fSCos = 1;\n        fSSin = fTx = fTy = 0;\n    }\n\n    void set(SkScalar scos, SkScalar ssin, SkScalar tx, SkScalar ty) {\n        fSCos = scos;\n        fSSin = ssin;\n        fTx = tx;\n        fTy = ty;\n    }\n\n    void toQuad(SkScalar width, SkScalar height, SkPoint quad[4]) const;\n    void toQuad(const SkSize& size, SkPoint quad[4]) const {\n        this->toQuad(size.width(), size.height(), quad);\n    }\n    void toTriStrip(SkScalar width, SkScalar height, SkPoint strip[4]) const;\n};\n\n#endif\n\n"
  },
  {
    "path": "include/core/SkRWBuffer.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRWBuffer_DEFINED\n#define SkRWBuffer_DEFINED\n\n#include \"SkRefCnt.h\"\n\nstruct SkBufferBlock;\nstruct SkBufferHead;\nclass SkRWBuffer;\nclass SkStreamAsset;\n\n/**\n *  Contains a read-only, thread-sharable block of memory. To access the memory, the caller must\n *  instantiate a local iterator, as the memory is stored in 1 or more contiguous blocks.\n */\nclass SK_API SkROBuffer : public SkRefCnt {\npublic:\n    /**\n     *  Return the logical length of the data owned/shared by this buffer. It may be stored in\n     *  multiple contiguous blocks, accessible via the iterator.\n     */\n    size_t size() const { return fAvailable; }\n\n    class SK_API Iter {\n    public:\n        Iter(const SkROBuffer*);\n        Iter(const sk_sp<SkROBuffer>&);\n\n        void reset(const SkROBuffer*);\n\n        /**\n         *  Return the current continuous block of memory, or nullptr if the iterator is exhausted\n         */\n        const void* data() const;\n\n        /**\n         *  Returns the number of bytes in the current continguous block of memory, or 0 if the\n         *  iterator is exhausted.\n         */\n        size_t size() const;\n\n        /**\n         *  Advance to the next contiguous block of memory, returning true if there is another\n         *  block, or false if the iterator is exhausted.\n         */\n        bool next();\n\n    private:\n        const SkBufferBlock* fBlock;\n        size_t               fRemaining;\n        const SkROBuffer*    fBuffer;\n    };\n\nprivate:\n    SkROBuffer(const SkBufferHead* head, size_t available, const SkBufferBlock* fTail);\n    virtual ~SkROBuffer();\n\n    const SkBufferHead*     fHead;\n    const size_t            fAvailable;\n    const SkBufferBlock*    fTail;\n\n    friend class SkRWBuffer;\n};\n\n/**\n *  Accumulates bytes of memory that are \"appended\" to it, growing internal storage as needed.\n *  The growth is done such that at any time in the writer's thread, an RBuffer or StreamAsset\n *  can be snapped off (and safely passed to another thread). The RBuffer/StreamAsset snapshot\n *  can see the previously stored bytes, but will be unaware of any future writes.\n */\nclass SK_API SkRWBuffer {\npublic:\n    SkRWBuffer(size_t initialCapacity = 0);\n    ~SkRWBuffer();\n\n    size_t size() const { return fTotalUsed; }\n\n    /**\n     *  Append |length| bytes from |buffer|.\n     *\n     *  If the caller knows in advance how much more data they are going to append, they can\n     *  pass a |reserve| hint (representing the number of upcoming bytes *in addition* to the\n     *  current append), to minimize the number of internal allocations.\n     */\n    void append(const void* buffer, size_t length, size_t reserve = 0);\n\n    sk_sp<SkROBuffer> makeROBufferSnapshot() const {\n        return sk_sp<SkROBuffer>(new SkROBuffer(fHead, fTotalUsed, fTail));\n    }\n\n    std::unique_ptr<SkStreamAsset> makeStreamSnapshot() const;\n\n#ifdef SK_DEBUG\n    void validate() const;\n#else\n    void validate() const {}\n#endif\n\nprivate:\n    SkBufferHead*   fHead;\n    SkBufferBlock*  fTail;\n    size_t          fTotalUsed;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkRasterHandleAllocator.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRasterHandleAllocator_DEFINED\n#define SkRasterHandleAllocator_DEFINED\n\n#include \"SkImageInfo.h\"\n\nclass SkBitmap;\nclass SkCanvas;\nclass SkMatrix;\n\n/**\n *  If a client wants to control the allocation of raster layers in a canvas, it should subclass\n *  SkRasterHandleAllocator. This allocator performs two tasks:\n *      1. controls how the memory for the pixels is allocated\n *      2. associates a \"handle\" to a private object that can track the matrix/clip of the SkCanvas\n *\n *  This example allocates a canvas, and defers to the allocator to create the base layer.\n *\n *      std::unique_ptr<SkCanvas> canvas = SkRasterHandleAllocator::MakeCanvas(\n *              SkImageInfo::Make(...),\n *              skstd::make_unique<MySubclassRasterHandleAllocator>(...),\n *              nullptr);\n *\n *  If you have already allocated the base layer (and its handle, release-proc etc.) then you\n *  can pass those in using the last parameter to MakeCanvas().\n *\n *  Regardless of how the base layer is allocated, each time canvas->saveLayer() is called,\n *  your allocator's allocHandle() will be called.\n */\nclass SK_API SkRasterHandleAllocator {\npublic:\n    virtual ~SkRasterHandleAllocator() {}\n\n    // The value that is returned to clients of the canvas that has this allocator installed.\n    typedef void* Handle;\n\n    struct Rec {\n        // When the allocation goes out of scope, this proc is called to free everything associated\n        // with it: the pixels, the \"handle\", etc. This is passed the pixel address and fReleaseCtx.\n        void    (*fReleaseProc)(void* pixels, void* ctx);\n        void*   fReleaseCtx;    // context passed to fReleaseProc\n        void*   fPixels;        // pixels for this allocation\n        size_t  fRowBytes;      // rowbytes for these pixels\n        Handle  fHandle;        // public handle returned by SkCanvas::accessTopRasterHandle()\n    };\n\n    /**\n     *  Given a requested info, allocate the corresponding pixels/rowbytes, and whatever handle\n     *  is desired to give clients access to those pixels. The rec also contains a proc and context\n     *  which will be called when this allocation goes out of scope.\n     *\n     *  e.g.\n     *      when canvas->saveLayer() is called, the allocator will be called to allocate the pixels\n     *      for the layer. When canvas->restore() is called, the fReleaseProc will be called.\n     */\n    virtual bool allocHandle(const SkImageInfo&, Rec*) = 0;\n\n    /**\n     *  Clients access the handle for a given layer by calling SkCanvas::accessTopRasterHandle().\n     *  To allow the handle to reflect the current matrix/clip in the canvs, updateHandle() is\n     *  is called. The subclass is responsible to update the handle as it sees fit.\n     */\n    virtual void updateHandle(Handle, const SkMatrix&, const SkIRect&) = 0;\n\n    /**\n     *  This creates a canvas which will use the allocator to manage pixel allocations, including\n     *  all calls to saveLayer().\n     *\n     *  If rec is non-null, then it will be used as the base-layer of pixels/handle.\n     *  If rec is null, then the allocator will be called for the base-layer as well.\n     */\n    static std::unique_ptr<SkCanvas> MakeCanvas(std::unique_ptr<SkRasterHandleAllocator>,\n                                                const SkImageInfo&, const Rec* rec = nullptr);\n\nprivate:\n    friend class SkBitmapDevice;\n\n    Handle allocBitmap(const SkImageInfo&, SkBitmap*);\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkRect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRect_DEFINED\n#define SkRect_DEFINED\n\n#include \"SkPoint.h\"\n#include \"SkSize.h\"\n#include \"../private/SkSafe32.h\"\n#include \"../private/SkTFitsIn.h\"\n\nstruct SkRect;\n\n/** \\struct SkIRect\n    SkIRect holds four 32-bit integer coordinates describing the upper and\n    lower bounds of a rectangle. SkIRect may be created from outer bounds or\n    from position, width, and height. SkIRect describes an area; if its right\n    is less than or equal to its left, or if its bottom is less than or equal to\n    its top, it is considered empty.\n*/\nstruct SK_API SkIRect {\n    int32_t fLeft;   //!< smaller x-axis bounds\n    int32_t fTop;    //!< smaller y-axis bounds\n    int32_t fRight;  //!< larger x-axis bounds\n    int32_t fBottom; //!< larger y-axis bounds\n\n    /** Returns constructed SkIRect set to (0, 0, 0, 0).\n        Many other rectangles are empty; if left is equal to or greater than right,\n        or if top is equal to or greater than bottom. Setting all members to zero\n        is a convenience, but does not designate a special empty rectangle.\n\n        @return  bounds (0, 0, 0, 0)\n    */\n    static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeEmpty() {\n        return SkIRect{0, 0, 0, 0};\n    }\n\n#ifdef SK_SUPPORT_LEGACY_RECTMAKELARGEST\n    /** Deprecated.\n    */\n    static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {\n        return { SK_MinS32, SK_MinS32, SK_MaxS32, SK_MaxS32 };\n    }\n#endif\n\n    /** Returns constructed SkIRect set to (0, 0, w, h). Does not validate input; w or h\n        may be negative.\n\n        @param w  width of constructed SkIRect\n        @param h  height of constructed SkIRect\n        @return   bounds (0, 0, w, h)\n    */\n    static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {\n        return SkIRect{0, 0, w, h};\n    }\n\n    /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).\n        Does not validate input; size.width() or size.height() may be negative.\n\n        @param size  values for SkIRect width and height\n        @return      bounds (0, 0, size.width(), size.height())\n    */\n    static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeSize(const SkISize& size) {\n        return SkIRect{0, 0, size.fWidth, size.fHeight};\n    }\n\n    /** Returns constructed SkIRect set to (l, t, r, b). Does not sort input; SkIRect may\n        result in fLeft greater than fRight, or fTop greater than fBottom.\n\n        @param l  integer stored in fLeft\n        @param t  integer stored in fTop\n        @param r  integer stored in fRight\n        @param b  integer stored in fBottom\n        @return   bounds (l, t, r, b)\n    */\n    static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeLTRB(int32_t l, int32_t t,\n                                                            int32_t r, int32_t b) {\n        return SkIRect{l, t, r, b};\n    }\n\n    /** Returns constructed SkIRect set to: (x, y, x + w, y + h). Does not validate input;\n        w or h may be negative.\n\n        @param x  stored in fLeft\n        @param y  stored in fTop\n        @param w  added to x and stored in fRight\n        @param h  added to y and stored in fBottom\n        @return   bounds at (x, y) with width w and height h\n    */\n    static constexpr SkIRect SK_WARN_UNUSED_RESULT MakeXYWH(int32_t x, int32_t y,\n                                                            int32_t w, int32_t h) {\n        return { x, y, Sk32_sat_add(x, w), Sk32_sat_add(y, h) };\n    }\n\n    /** Returns left edge of SkIRect, if sorted.\n        Call sort() to reverse fLeft and fRight if needed.\n\n        @return  fLeft\n    */\n    int32_t left() const { return fLeft; }\n\n    /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fTop\n    */\n    int32_t top() const { return fTop; }\n\n    /** Returns right edge of SkIRect, if sorted.\n        Call sort() to reverse fLeft and fRight if needed.\n\n        @return  fRight\n    */\n    int32_t right() const { return fRight; }\n\n    /** Returns bottom edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fBottom\n    */\n    int32_t bottom() const { return fBottom; }\n\n    /** Returns left edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,\n        and sort() to reverse fLeft and fRight if needed.\n\n        @return  fLeft\n    */\n    int32_t x() const { return fLeft; }\n\n    /** Returns top edge of SkIRect, if sorted. Call isEmpty() to see if SkIRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fTop\n    */\n    int32_t y() const { return fTop; }\n\n    /** Returns span on the x-axis. This does not check if SkIRect is sorted, or if\n        result fits in 32-bit signed integer; result may be negative.\n\n        @return  fRight minus fLeft\n    */\n    int32_t width() const { return Sk32_can_overflow_sub(fRight, fLeft); }\n\n    /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if\n        result fits in 32-bit signed integer; result may be negative.\n\n        @return  fBottom minus fTop\n    */\n    int32_t height() const { return Sk32_can_overflow_sub(fBottom, fTop); }\n\n    /** Returns spans on the x-axis and y-axis. This does not check if SkIRect is sorted,\n        or if result fits in 32-bit signed integer; result may be negative.\n\n        @return  SkISize (width, height)\n    */\n    SkISize size() const { return SkISize::Make(this->width(), this->height()); }\n\n    /** Returns span on the x-axis. This does not check if SkIRect is sorted, so the\n        result may be negative. This is safer than calling width() since width() might\n        overflow in its calculation.\n\n        @return  fRight minus fLeft cast to int64_t\n    */\n    int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; }\n\n    /** Returns span on the y-axis. This does not check if SkIRect is sorted, so the\n        result may be negative. This is safer than calling height() since height() might\n        overflow in its calculation.\n\n        @return  fBottom minus fTop cast to int64_t\n    */\n    int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; }\n\n    /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal\n        to or greater than fBottom. Call sort() to reverse rectangles with negative\n        width64() or height64().\n\n        @return  true if width64() or height64() are zero or negative\n    */\n    bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; }\n\n    /** Returns true if width() or height() .\n\n        @return  true if width() or height() are zero or negative\n    */\n    bool isEmpty() const {\n        int64_t w = this->width64();\n        int64_t h = this->height64();\n        if (w <= 0 || h <= 0) {\n            return true;\n        }\n        // Return true if either exceeds int32_t\n        return !SkTFitsIn<int32_t>(w | h);\n    }\n\n    /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are\n        identical to corresponding members in b.\n\n        @param a  SkIRect to compare\n        @param b  SkIRect to compare\n        @return   true if members are equal\n    */\n    friend bool operator==(const SkIRect& a, const SkIRect& b) {\n        return !memcmp(&a, &b, sizeof(a));\n    }\n\n    /** Returns true if any member in a: fLeft, fTop, fRight, and fBottom; is not\n        identical to the corresponding member in b.\n\n        @param a  SkIRect to compare\n        @param b  SkIRect to compare\n        @return   true if members are not equal\n    */\n    friend bool operator!=(const SkIRect& a, const SkIRect& b) {\n        return !(a == b);\n    }\n\n    /** Sets SkIRect to (0, 0, 0, 0).\n\n        Many other rectangles are empty; if left is equal to or greater than right,\n        or if top is equal to or greater than bottom. Setting all members to zero\n        is a convenience, but does not designate a special empty rectangle.\n    */\n    void setEmpty() { memset(this, 0, sizeof(*this)); }\n\n    /** Sets SkIRect to (left, top, right, bottom).\n        left and right are not sorted; left is not necessarily less than right.\n        top and bottom are not sorted; top is not necessarily less than bottom.\n\n        @param left    assigned to fLeft\n        @param top     assigned to fTop\n        @param right   assigned to fRight\n        @param bottom  assigned to fBottom\n    */\n    void set(int32_t left, int32_t top, int32_t right, int32_t bottom) {\n        fLeft   = left;\n        fTop    = top;\n        fRight  = right;\n        fBottom = bottom;\n    }\n\n    /** Sets SkIRect to (left, top, right, bottom).\n        left and right are not sorted; left is not necessarily less than right.\n        top and bottom are not sorted; top is not necessarily less than bottom.\n\n        @param left    stored in fLeft\n        @param top     stored in fTop\n        @param right   stored in fRight\n        @param bottom  stored in fBottom\n    */\n    void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom) {\n        this->set(left, top, right, bottom);\n    }\n\n    /** Sets SkIRect to: (x, y, x + width, y + height). Does not validate input;\n        width or height may be negative.\n\n        @param x       stored in fLeft\n        @param y       stored in fTop\n        @param width   added to x and stored in fRight\n        @param height  added to y and stored in fBottom\n    */\n    void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height) {\n        fLeft   = x;\n        fTop    = y;\n        fRight  = Sk32_sat_add(x, width);\n        fBottom = Sk32_sat_add(y, height);\n    }\n\n    /** Returns SkIRect offset by (dx, dy).\n\n        If dx is negative, SkIRect returned is moved to the left.\n        If dx is positive, SkIRect returned is moved to the right.\n        If dy is negative, SkIRect returned is moved upward.\n        If dy is positive, SkIRect returned is moved downward.\n\n        @param dx  offset added to fLeft and fRight\n        @param dy  offset added to fTop and fBottom\n        @return    SkIRect offset in x or y, with original width and height\n    */\n    SkIRect makeOffset(int32_t dx, int32_t dy) const {\n        return {\n            Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),\n            Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),\n        };\n    }\n\n    /** Returns SkIRect, inset by (dx, dy).\n\n        If dx is negative, SkIRect returned is wider.\n        If dx is positive, SkIRect returned is narrower.\n        If dy is negative, SkIRect returned is taller.\n        If dy is positive, SkIRect returned is shorter.\n\n        @param dx  offset added to fLeft and subtracted from fRight\n        @param dy  offset added to fTop and subtracted from fBottom\n        @return    SkIRect inset symmetrically left and right, top and bottom\n    */\n    SkIRect makeInset(int32_t dx, int32_t dy) const {\n        return {\n            Sk32_sat_add(fLeft,  dx), Sk32_sat_add(fTop,    dy),\n            Sk32_sat_sub(fRight, dx), Sk32_sat_sub(fBottom, dy),\n        };\n    }\n\n    /** Returns SkIRect, outset by (dx, dy).\n\n        If dx is negative, SkIRect returned is narrower.\n        If dx is positive, SkIRect returned is wider.\n        If dy is negative, SkIRect returned is shorter.\n        If dy is positive, SkIRect returned is taller.\n\n        @param dx  offset subtracted to fLeft and added from fRight\n        @param dy  offset subtracted to fTop and added from fBottom\n        @return    SkIRect outset symmetrically left and right, top and bottom\n    */\n    SkIRect makeOutset(int32_t dx, int32_t dy) const {\n        return {\n            Sk32_sat_sub(fLeft,  dx), Sk32_sat_sub(fTop,    dy),\n            Sk32_sat_add(fRight, dx), Sk32_sat_add(fBottom, dy),\n        };\n    }\n\n    /** Offsets SkIRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.\n\n        If dx is negative, moves SkIRect returned to the left.\n        If dx is positive, moves SkIRect returned to the right.\n        If dy is negative, moves SkIRect returned upward.\n        If dy is positive, moves SkIRect returned downward.\n\n        @param dx  offset added to fLeft and fRight\n        @param dy  offset added to fTop and fBottom\n    */\n    void offset(int32_t dx, int32_t dy) {\n        fLeft   = Sk32_sat_add(fLeft,   dx);\n        fTop    = Sk32_sat_add(fTop,    dy);\n        fRight  = Sk32_sat_add(fRight,  dx);\n        fBottom = Sk32_sat_add(fBottom, dy);\n    }\n\n    /** Offsets SkIRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to\n        fTop, fBottom.\n\n        If delta.fX is negative, moves SkIRect returned to the left.\n        If delta.fX is positive, moves SkIRect returned to the right.\n        If delta.fY is negative, moves SkIRect returned upward.\n        If delta.fY is positive, moves SkIRect returned downward.\n\n        @param delta  offset added to SkIRect\n    */\n    void offset(const SkIPoint& delta) {\n        this->offset(delta.fX, delta.fY);\n    }\n\n    /** Offsets SkIRect so that fLeft equals newX, and fTop equals newY. width and height\n        are unchanged.\n\n        @param newX  stored in fLeft, preserving width()\n        @param newY  stored in fTop, preserving height()\n    */\n    void offsetTo(int32_t newX, int32_t newY) {\n        fRight  = Sk64_pin_to_s32((int64_t)fRight + newX - fLeft);\n        fBottom = Sk64_pin_to_s32((int64_t)fBottom + newY - fTop);\n        fLeft   = newX;\n        fTop    = newY;\n    }\n\n    /** Insets SkIRect by (dx,dy).\n\n        If dx is positive, makes SkIRect narrower.\n        If dx is negative, makes SkIRect wider.\n        If dy is positive, makes SkIRect shorter.\n        If dy is negative, makes SkIRect taller.\n\n        @param dx  offset added to fLeft and subtracted from fRight\n        @param dy  offset added to fTop and subtracted from fBottom\n    */\n    void inset(int32_t dx, int32_t dy) {\n        fLeft   = Sk32_sat_add(fLeft,   dx);\n        fTop    = Sk32_sat_add(fTop,    dy);\n        fRight  = Sk32_sat_sub(fRight,  dx);\n        fBottom = Sk32_sat_sub(fBottom, dy);\n    }\n\n    /** Outsets SkIRect by (dx, dy).\n\n        If dx is positive, makes SkIRect wider.\n        If dx is negative, makes SkIRect narrower.\n        If dy is positive, makes SkIRect taller.\n        If dy is negative, makes SkIRect shorter.\n\n        @param dx  subtracted to fLeft and added from fRight\n        @param dy  subtracted to fTop and added from fBottom\n    */\n    void outset(int32_t dx, int32_t dy)  { this->inset(-dx, -dy); }\n\n    /** Adjusts SkIRect by adding dL to fLeft, dT to fTop, dR to fRight, and dB to fBottom.\n\n        If dL is positive, narrows SkIRect on the left. If negative, widens it on the left.\n        If dT is positive, shrinks SkIRect on the top. If negative, lengthens it on the top.\n        If dR is positive, narrows SkIRect on the right. If negative, widens it on the right.\n        If dB is positive, shrinks SkIRect on the bottom. If negative, lengthens it on the bottom.\n\n        The resulting SkIRect is not checked for validity. Thus, if the resulting SkIRect left is\n        greater than right, the SkIRect will be considered empty. Call sort() after this call\n        if that is not the desired behavior.\n\n        @param dL  offset added to fLeft\n        @param dT  offset added to fTop\n        @param dR  offset added to fRight\n        @param dB  offset added to fBottom\n    */\n    void adjust(int32_t dL, int32_t dT, int32_t dR, int32_t dB) {\n        fLeft   = Sk32_sat_add(fLeft,   dL);\n        fTop    = Sk32_sat_add(fTop,    dT);\n        fRight  = Sk32_sat_add(fRight,  dR);\n        fBottom = Sk32_sat_add(fBottom, dB);\n    }\n\n    /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.\n        Returns false if SkIRect is empty.\n\n        Considers input to describe constructed SkIRect: (x, y, x + 1, y + 1) and\n        returns true if constructed area is completely enclosed by SkIRect area.\n\n        @param x  test SkIPoint x-coordinate\n        @param y  test SkIPoint y-coordinate\n        @return   true if (x, y) is inside SkIRect\n    */\n    bool contains(int32_t x, int32_t y) const {\n        return x >= fLeft && x < fRight && y >= fTop && y < fBottom;\n    }\n\n    /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Returns true if SkIRect contains construction.\n        Returns false if SkIRect is empty or construction is empty.\n\n        @param left    x minimum of constructed SkIRect\n        @param top     y minimum of constructed SkIRect\n        @param right   x maximum of constructed SkIRect\n        @param bottom  y maximum of constructed SkIRect\n        @return        true if all sides of SkIRect are outside construction\n    */\n    bool contains(int32_t left, int32_t top, int32_t right, int32_t bottom) const {\n        return  left < right && top < bottom && !this->isEmpty() && // check for empties\n                fLeft <= left && fTop <= top &&\n                fRight >= right && fBottom >= bottom;\n    }\n\n    /** Returns true if SkIRect contains r.\n        Returns false if SkIRect is empty or r is empty.\n\n        SkIRect contains r when SkIRect area completely includes r area.\n\n        @param r  SkIRect contained\n        @return   true if all sides of SkIRect are outside r\n    */\n    bool contains(const SkIRect& r) const {\n        return  !r.isEmpty() && !this->isEmpty() &&     // check for empties\n                fLeft <= r.fLeft && fTop <= r.fTop &&\n                fRight >= r.fRight && fBottom >= r.fBottom;\n    }\n\n    /** Returns true if SkIRect contains r.\n        Returns false if SkIRect is empty or r is empty.\n\n        SkIRect contains r when SkIRect area completely includes r area.\n\n        @param r  SkRect contained\n        @return   true if all sides of SkIRect are outside r\n    */\n    bool contains(const SkRect& r) const;\n\n    /** Constructs SkIRect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Returns true if SkIRect contains construction.\n        Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.\n\n        Return is undefined if SkIRect is empty or construction is empty.\n\n        @param left    x minimum of constructed SkIRect\n        @param top     y minimum of constructed SkIRect\n        @param right   x maximum of constructed SkIRect\n        @param bottom  y maximum of constructed SkIRect\n        @return        true if all sides of SkIRect are outside construction\n    */\n    bool containsNoEmptyCheck(int32_t left, int32_t top,\n                              int32_t right, int32_t bottom) const {\n        SkASSERT(fLeft < fRight && fTop < fBottom);\n        SkASSERT(left < right && top < bottom);\n\n        return fLeft <= left && fTop <= top &&\n               fRight >= right && fBottom >= bottom;\n    }\n\n    /** Returns true if SkIRect contains construction.\n        Asserts if SkIRect is empty or construction is empty, and if SK_DEBUG is defined.\n\n        Return is undefined if SkIRect is empty or construction is empty.\n\n        @param r  SkIRect contained\n        @return   true if all sides of SkIRect are outside r\n    */\n    bool containsNoEmptyCheck(const SkIRect& r) const {\n        return containsNoEmptyCheck(r.fLeft, r.fTop, r.fRight, r.fBottom);\n    }\n\n    /** Returns true if SkIRect intersects r, and sets SkIRect to intersection.\n        Returns false if SkIRect does not intersect r, and leaves SkIRect unchanged.\n\n        Returns false if either r or SkIRect is empty, leaving SkIRect unchanged.\n\n        @param r  limit of result\n        @return   true if r and SkIRect have area in common\n    */\n    bool intersect(const SkIRect& r) {\n        return this->intersect(*this, r);\n    }\n\n    /** Returns true if a intersects b, and sets SkIRect to intersection.\n        Returns false if a does not intersect b, and leaves SkIRect unchanged.\n\n        Asserts if either a or b is empty, and if SK_DEBUG is defined.\n\n        @param a  SkIRect to intersect\n        @param b  SkIRect to intersect\n        @return   true if a and b have area in common\n    */\n    bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) {\n        SkASSERT(!a.isEmpty64() && !b.isEmpty64());\n        SkIRect r = {\n            SkMax32(a.fLeft,   b.fLeft),\n            SkMax32(a.fTop,    b.fTop),\n            SkMin32(a.fRight,  b.fRight),\n            SkMin32(a.fBottom, b.fBottom)\n        };\n        if (r.isEmpty()) {\n            return false;\n        }\n        *this = r;\n        return true;\n    }\n\n    /** Returns true if a intersects b, and sets SkIRect to intersection.\n        Returns false if a does not intersect b, and leaves SkIRect unchanged.\n\n        Returns false if either a or b is empty, leaving SkIRect unchanged.\n\n        @param a  SkIRect to intersect\n        @param b  SkIRect to intersect\n        @return   true if a and b have area in common\n    */\n    bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) {\n        if (a.isEmpty64() || b.isEmpty64()) {\n            return false;\n        }\n        return this->intersectNoEmptyCheck(a, b);\n    }\n\n    /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Returns true if SkIRect intersects construction, and sets SkIRect to intersection.\n        Returns false if SkIRect does not intersect construction, and leaves SkIRect unchanged.\n\n        Returns false if either construction or SkIRect is empty, leaving SkIRect unchanged.\n\n        @param left    x minimum of constructed SkIRect\n        @param top     y minimum of constructed SkIRect\n        @param right   x maximum of constructed SkIRect\n        @param bottom  y maximum of constructed SkIRect\n        @return        true if construction and SkIRect have area in common\n    */\n    bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) {\n        return this->intersect(*this, {left, top, right, bottom});\n    }\n\n    /** Returns true if a intersects b.\n        Returns false if either a or b is empty, or do not intersect.\n\n        @param a  SkIRect to intersect\n        @param b  SkIRect to intersect\n        @return   true if a and b have area in common\n    */\n    static bool Intersects(const SkIRect& a, const SkIRect& b) {\n        SkIRect dummy;\n        return dummy.intersect(a, b);\n    }\n\n    /** Returns true if a intersects b.\n        Asserts if either a or b is empty, and if SK_DEBUG is defined.\n\n        @param a  SkIRect to intersect\n        @param b  SkIRect to intersect\n        @return   true if a and b have area in common\n    */\n    static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) {\n        SkIRect dummy;\n        return dummy.intersectNoEmptyCheck(a, b);\n    }\n\n    /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Sets SkIRect to the union of itself and the construction.\n\n        Has no effect if construction is empty. Otherwise, if SkIRect is empty, sets\n        SkIRect to construction.\n\n        @param left    x minimum of constructed SkIRect\n        @param top     y minimum of constructed SkIRect\n        @param right   x maximum of constructed SkIRect\n        @param bottom  y maximum of constructed SkIRect\n    */\n    void join(int32_t left, int32_t top, int32_t right, int32_t bottom);\n\n    /** Sets SkIRect to the union of itself and r.\n\n        Has no effect if r is empty. Otherwise, if SkIRect is empty, sets SkIRect to r.\n\n        @param r  expansion SkIRect\n    */\n    void join(const SkIRect& r) {\n        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);\n    }\n\n    /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps\n        fTop and fBottom if fTop is greater than fBottom. Result may be empty,\n        and width() and height() will be zero or positive.\n    */\n    void sort() {\n        if (fLeft > fRight) {\n            SkTSwap<int32_t>(fLeft, fRight);\n        }\n        if (fTop > fBottom) {\n            SkTSwap<int32_t>(fTop, fBottom);\n        }\n    }\n\n    /** Returns SkIRect with fLeft and fRight swapped if fLeft is greater than fRight; and\n        with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;\n        and width() and height() will be zero or positive.\n\n        @return  sorted SkIRect\n    */\n    SkIRect makeSorted() const {\n        return MakeLTRB(SkMin32(fLeft, fRight), SkMin32(fTop, fBottom),\n                        SkMax32(fLeft, fRight), SkMax32(fTop, fBottom));\n    }\n\n    /** Returns a reference to immutable empty SkIRect, set to (0, 0, 0, 0).\n\n        @return  global SkIRect set to all zeroes\n    */\n    static const SkIRect& SK_WARN_UNUSED_RESULT EmptyIRect() {\n        static const SkIRect gEmpty = { 0, 0, 0, 0 };\n        return gEmpty;\n    }\n};\n\n/** \\struct SkRect\n    SkRect holds four SkScalar coordinates describing the upper and\n    lower bounds of a rectangle. SkRect may be created from outer bounds or\n    from position, width, and height. SkRect describes an area; if its right\n    is less than or equal to its left, or if its bottom is less than or equal to\n    its top, it is considered empty.\n*/\nstruct SK_API SkRect {\n    SkScalar fLeft;   //!< smaller x-axis bounds\n    SkScalar fTop;    //!< smaller y-axis bounds\n    SkScalar fRight;  //!< larger x-axis bounds\n    SkScalar fBottom; //!< larger y-axis bounds\n\n    /** Returns constructed SkRect set to (0, 0, 0, 0).\n        Many other rectangles are empty; if left is equal to or greater than right,\n        or if top is equal to or greater than bottom. Setting all members to zero\n        is a convenience, but does not designate a special empty rectangle.\n\n        @return  bounds (0, 0, 0, 0)\n    */\n    static constexpr SkRect SK_WARN_UNUSED_RESULT MakeEmpty() {\n        return SkRect{0, 0, 0, 0};\n    }\n\n#ifdef SK_SUPPORT_LEGACY_RECTMAKELARGEST\n    /** Deprecated.\n    */\n    static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {\n        return { SK_ScalarMin, SK_ScalarMin, SK_ScalarMax, SK_ScalarMax };\n    }\n#endif\n\n    /** Returns constructed SkRect set to SkScalar values (0, 0, w, h). Does not\n        validate input; w or h may be negative.\n\n        Passing integer values may generate a compiler warning since SkRect cannot\n        represent 32-bit integers exactly. Use SkIRect for an exact integer rectangle.\n\n        @param w  SkScalar width of constructed SkRect\n        @param h  SkScalar height of constructed SkRect\n        @return   bounds (0, 0, w, h)\n    */\n    static constexpr SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {\n        return SkRect{0, 0, w, h};\n    }\n\n    /** Returns constructed SkRect set to integer values (0, 0, w, h). Does not validate\n        input; w or h may be negative.\n\n        Use to avoid a compiler warning that input may lose precision when stored.\n        Use SkIRect for an exact integer rectangle.\n\n        @param w  integer width of constructed SkRect\n        @param h  integer height of constructed SkRect\n        @return   bounds (0, 0, w, h)\n    */\n    static SkRect SK_WARN_UNUSED_RESULT MakeIWH(int w, int h) {\n        SkRect r;\n        r.set(0, 0, SkIntToScalar(w), SkIntToScalar(h));\n        return r;\n    }\n\n    /** Returns constructed SkRect set to (0, 0, size.width(), size.height()). Does not\n        validate input; size.width() or size.height() may be negative.\n\n        @param size  SkScalar values for SkRect width and height\n        @return      bounds (0, 0, size.width(), size.height())\n    */\n    static constexpr SkRect SK_WARN_UNUSED_RESULT MakeSize(const SkSize& size) {\n        return SkRect{0, 0, size.fWidth, size.fHeight};\n    }\n\n    /** Returns constructed SkRect set to (l, t, r, b). Does not sort input; SkRect may\n        result in fLeft greater than fRight, or fTop greater than fBottom.\n\n        @param l  SkScalar stored in fLeft\n        @param t  SkScalar stored in fTop\n        @param r  SkScalar stored in fRight\n        @param b  SkScalar stored in fBottom\n        @return   bounds (l, t, r, b)\n    */\n    static constexpr SkRect SK_WARN_UNUSED_RESULT MakeLTRB(SkScalar l, SkScalar t, SkScalar r,\n                                                           SkScalar b) {\n        return SkRect {l, t, r, b};\n    }\n\n    /** Returns constructed SkRect set to (x, y, x + w, y + h). Does not validate input;\n        w or h may be negative.\n\n        @param x  stored in fLeft\n        @param y  stored in fTop\n        @param w  added to x and stored in fRight\n        @param h  added to y and stored in fBottom\n        @return   bounds at (x, y) with width w and height h\n    */\n    static constexpr SkRect SK_WARN_UNUSED_RESULT MakeXYWH(SkScalar x, SkScalar y, SkScalar w, SkScalar h) {\n        return SkRect {x, y, x + w, y + h};\n    }\n\n    /** Deprecated.\n    */\n    SK_ATTR_DEPRECATED(\"use Make()\")\n    static SkRect SK_WARN_UNUSED_RESULT MakeFromIRect(const SkIRect& irect) {\n        SkRect r;\n        r.set(SkIntToScalar(irect.fLeft),\n              SkIntToScalar(irect.fTop),\n              SkIntToScalar(irect.fRight),\n              SkIntToScalar(irect.fBottom));\n        return r;\n    }\n\n    /** Returns constructed SkIRect set to (0, 0, size.width(), size.height()).\n        Does not validate input; size.width() or size.height() may be negative.\n\n        @param size  integer values for SkRect width and height\n        @return      bounds (0, 0, size.width(), size.height())\n    */\n    static SkRect Make(const SkISize& size) {\n        return MakeIWH(size.width(), size.height());\n    }\n\n    /** Returns constructed SkIRect set to irect, promoting integers to scalar.\n        Does not validate input; fLeft may be greater than fRight, fTop may be greater\n        than fBottom.\n\n        @param irect  integer unsorted bounds\n        @return       irect members converted to SkScalar\n    */\n    static SkRect SK_WARN_UNUSED_RESULT Make(const SkIRect& irect) {\n        SkRect r;\n        r.set(SkIntToScalar(irect.fLeft),\n              SkIntToScalar(irect.fTop),\n              SkIntToScalar(irect.fRight),\n              SkIntToScalar(irect.fBottom));\n        return r;\n    }\n\n    /** Returns true if fLeft is equal to or greater than fRight, or if fTop is equal\n        to or greater than fBottom. Call sort() to reverse rectangles with negative\n        width() or height().\n\n        @return  true if width() or height() are zero or negative\n    */\n    bool isEmpty() const {\n        // We write it as the NOT of a non-empty rect, so we will return true if any values\n        // are NaN.\n        return !(fLeft < fRight && fTop < fBottom);\n    }\n\n    /** Returns true if fLeft is equal to or less than fRight, or if fTop is equal\n        to or less than fBottom. Call sort() to reverse rectangles with negative\n        width() or height().\n\n        @return  true if width() or height() are zero or positive\n    */\n    bool isSorted() const { return fLeft <= fRight && fTop <= fBottom; }\n\n    /** Returns true if all values in the rectangle are finite: SK_ScalarMin or larger,\n        and SK_ScalarMax or smaller.\n\n        @return  true if no member is infinite or NaN\n    */\n    bool isFinite() const {\n        float accum = 0;\n        accum *= fLeft;\n        accum *= fTop;\n        accum *= fRight;\n        accum *= fBottom;\n\n        // accum is either NaN or it is finite (zero).\n        SkASSERT(0 == accum || SkScalarIsNaN(accum));\n\n        // value==value will be true iff value is not NaN\n        // TODO: is it faster to say !accum or accum==accum?\n        return !SkScalarIsNaN(accum);\n    }\n\n    /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.\n        Call sort() to reverse fLeft and fRight if needed.\n\n        @return  fLeft\n    */\n    SkScalar    x() const { return fLeft; }\n\n    /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fTop\n    */\n    SkScalar    y() const { return fTop; }\n\n    /** Returns left edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.\n        Call sort() to reverse fLeft and fRight if needed.\n\n        @return  fLeft\n    */\n    SkScalar    left() const { return fLeft; }\n\n    /** Returns top edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fTop\n    */\n    SkScalar    top() const { return fTop; }\n\n    /** Returns right edge of SkRect, if sorted. Call isSorted() to see if SkRect is valid.\n        Call sort() to reverse fLeft and fRight if needed.\n\n        @return  fRight\n    */\n    SkScalar    right() const { return fRight; }\n\n    /** Returns bottom edge of SkRect, if sorted. Call isEmpty() to see if SkRect may be invalid,\n        and sort() to reverse fTop and fBottom if needed.\n\n        @return  fBottom\n    */\n    SkScalar    bottom() const { return fBottom; }\n\n    /** Returns span on the x-axis. This does not check if SkRect is sorted, or if\n        result fits in 32-bit float; result may be negative or infinity.\n\n        @return  fRight minus fLeft\n    */\n    SkScalar    width() const { return fRight - fLeft; }\n\n    /** Returns span on the y-axis. This does not check if SkIRect is sorted, or if\n        result fits in 32-bit float; result may be negative or infinity.\n\n        @return  fBottom minus fTop\n    */\n    SkScalar    height() const { return fBottom - fTop; }\n\n    /** Returns average of left edge and right edge. Result does not change if SkRect\n        is sorted. Result may overflow to infinity if SkRect is far from the origin.\n\n        @return  midpoint in x\n    */\n    SkScalar centerX() const {\n        // don't use SkScalarHalf(fLeft + fBottom) as that might overflow before the 0.5\n        return SkScalarHalf(fLeft) + SkScalarHalf(fRight);\n    }\n\n    /** Returns average of top edge and bottom edge. Result does not change if SkRect\n        is sorted. Result may overflow to infinity if SkRect is far from the origin.\n\n        @return  midpoint in y\n    */\n    SkScalar centerY() const {\n        // don't use SkScalarHalf(fTop + fBottom) as that might overflow before the 0.5\n        return SkScalarHalf(fTop) + SkScalarHalf(fBottom);\n    }\n\n    /** Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are\n        equal to the corresponding members in b.\n\n        a and b are not equal if either contain NaN. a and b are equal if members\n        contain zeroes width different signs.\n\n        @param a  SkRect to compare\n        @param b  SkRect to compare\n        @return   true if members are equal\n    */\n    friend bool operator==(const SkRect& a, const SkRect& b) {\n        return SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);\n    }\n\n    /** Returns true if any in a: fLeft, fTop, fRight, and fBottom; does not\n        equal the corresponding members in b.\n\n        a and b are not equal if either contain NaN. a and b are equal if members\n        contain zeroes width different signs.\n\n        @param a  SkRect to compare\n        @param b  SkRect to compare\n        @return   true if members are not equal\n    */\n    friend bool operator!=(const SkRect& a, const SkRect& b) {\n        return !SkScalarsEqual((const SkScalar*)&a, (const SkScalar*)&b, 4);\n    }\n\n    /** Returns four points in quad that enclose SkRect ordered as: top-left, top-right,\n        bottom-right, bottom-left.\n        Consider adding param to control whether quad is clockwise or counterclockwise.\n\n        @param quad  storage for corners of SkRect\n    */\n    void toQuad(SkPoint quad[4]) const;\n\n    /** Sets SkRect to (0, 0, 0, 0).\n\n        Many other rectangles are empty; if left is equal to or greater than right,\n        or if top is equal to or greater than bottom. Setting all members to zero\n        is a convenience, but does not designate a special empty rectangle.\n    */\n    void setEmpty() { *this = MakeEmpty(); }\n\n    /** Sets SkRect to src, promoting src members from integer to scalar.\n        Very large values in src may lose precision.\n\n        @param src  integer SkRect\n    */\n    void set(const SkIRect& src) {\n        fLeft   = SkIntToScalar(src.fLeft);\n        fTop    = SkIntToScalar(src.fTop);\n        fRight  = SkIntToScalar(src.fRight);\n        fBottom = SkIntToScalar(src.fBottom);\n    }\n\n    /** Sets SkRect to (left, top, right, bottom).\n        left and right are not sorted; left is not necessarily less than right.\n        top and bottom are not sorted; top is not necessarily less than bottom.\n\n        @param left    stored in fLeft\n        @param top     stored in fTop\n        @param right   stored in fRight\n        @param bottom  stored in fBottom\n    */\n    void set(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {\n        fLeft   = left;\n        fTop    = top;\n        fRight  = right;\n        fBottom = bottom;\n    }\n\n    /** Sets SkRect to (left, top, right, bottom).\n        left and right are not sorted; left is not necessarily less than right.\n        top and bottom are not sorted; top is not necessarily less than bottom.\n\n        @param left    stored in fLeft\n        @param top     stored in fTop\n        @param right   stored in fRight\n        @param bottom  stored in fBottom\n    */\n    void setLTRB(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) {\n        this->set(left, top, right, bottom);\n    }\n\n    /** Sets SkRect to (left, top, right, bottom).\n        All parameters are promoted from integer to scalar.\n        left and right are not sorted; left is not necessarily less than right.\n        top and bottom are not sorted; top is not necessarily less than bottom.\n\n        @param left    promoted to SkScalar and stored in fLeft\n        @param top     promoted to SkScalar and stored in fTop\n        @param right   promoted to SkScalar and stored in fRight\n        @param bottom  promoted to SkScalar and stored in fBottom\n    */\n    void iset(int left, int top, int right, int bottom) {\n        fLeft   = SkIntToScalar(left);\n        fTop    = SkIntToScalar(top);\n        fRight  = SkIntToScalar(right);\n        fBottom = SkIntToScalar(bottom);\n    }\n\n    /** Sets SkRect to (0, 0, width, height).\n        width and height may be zero or negative. width and height are promoted from\n        integer to SkScalar, large values may lose precision.\n\n        @param width   promoted to SkScalar and stored in fRight\n        @param height  promoted to SkScalar and stored in fBottom\n    */\n    void isetWH(int width, int height) {\n        fLeft = fTop = 0;\n        fRight = SkIntToScalar(width);\n        fBottom = SkIntToScalar(height);\n    }\n\n    /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,\n        or if SkPoint array contains an infinity or NaN, sets SkRect to (0, 0, 0, 0).\n\n        Result is either empty or sorted: fLeft is less than or equal to fRight, and\n        fTop is less than or equal to fBottom.\n\n        @param pts    SkPoint array\n        @param count  entries in array\n    */\n    void set(const SkPoint pts[], int count) {\n        // set() had been checking for non-finite values, so keep that behavior\n        // for now. Now that we have setBoundsCheck(), we may decide to make\n        // set() be simpler/faster, and not check for those.\n        (void)this->setBoundsCheck(pts, count);\n    }\n\n    /** Sets to bounds of SkPoint array with count entries. If count is zero or smaller,\n        or if SkPoint array contains an infinity or NaN, sets to (0, 0, 0, 0).\n\n        Result is either empty or sorted: fLeft is less than or equal to fRight, and\n        fTop is less than or equal to fBottom.\n\n        @param pts    SkPoint array\n        @param count  entries in array\n    */\n    void setBounds(const SkPoint pts[], int count) {\n        (void)this->setBoundsCheck(pts, count);\n    }\n\n    /** Sets to bounds of SkPoint array with count entries. Returns false if count is\n        zero or smaller, or if SkPoint array contains an infinity or NaN; in these cases\n        sets SkRect to (0, 0, 0, 0).\n\n        Result is either empty or sorted: fLeft is less than or equal to fRight, and\n        fTop is less than or equal to fBottom.\n\n        @param pts    SkPoint array\n        @param count  entries in array\n        @return       true if all SkPoint values are finite\n    */\n    bool setBoundsCheck(const SkPoint pts[], int count);\n\n    /** Sets to bounds of SkPoint pts array with count entries. If any SkPoint in pts\n        contains infinity or NaN, all SkRect dimensions are set to NaN.\n\n        @param pts    SkPoint array\n        @param count  entries in array\n    */\n    void setBoundsNoCheck(const SkPoint pts[], int count);\n\n    /** Sets bounds to the smallest SkRect enclosing SkPoint p0 and p1. The result is\n        sorted and may be empty. Does not check to see if values are finite.\n\n        @param p0  corner to include\n        @param p1  corner to include\n    */\n    void set(const SkPoint& p0, const SkPoint& p1) {\n        fLeft =   SkMinScalar(p0.fX, p1.fX);\n        fRight =  SkMaxScalar(p0.fX, p1.fX);\n        fTop =    SkMinScalar(p0.fY, p1.fY);\n        fBottom = SkMaxScalar(p0.fY, p1.fY);\n    }\n\n    /** Sets SkRect to (x, y, x + width, y + height). Does not validate input;\n        width or height may be negative.\n\n        @param x       stored in fLeft\n        @param y       stored in fTop\n        @param width   added to x and stored in fRight\n        @param height  added to y and stored in fBottom\n    */\n    void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) {\n        fLeft = x;\n        fTop = y;\n        fRight = x + width;\n        fBottom = y + height;\n    }\n\n    /** Sets SkRect to (0, 0, width, height). Does not validate input;\n        width or height may be negative.\n\n        @param width   stored in fRight\n        @param height  stored in fBottom\n    */\n    void setWH(SkScalar width, SkScalar height) {\n        fLeft = 0;\n        fTop = 0;\n        fRight = width;\n        fBottom = height;\n    }\n\n    /** Returns SkRect offset by (dx, dy).\n\n        If dx is negative, SkRect returned is moved to the left.\n        If dx is positive, SkRect returned is moved to the right.\n        If dy is negative, SkRect returned is moved upward.\n        If dy is positive, SkRect returned is moved downward.\n\n        @param dx  added to fLeft and fRight\n        @param dy  added to fTop and fBottom\n        @return    SkRect offset in x or y, with original width and height\n    */\n    SkRect makeOffset(SkScalar dx, SkScalar dy) const {\n        return MakeLTRB(fLeft + dx, fTop + dy, fRight + dx, fBottom + dy);\n    }\n\n    /** Returns SkRect, inset by (dx, dy).\n\n        If dx is negative, SkRect returned is wider.\n        If dx is positive, SkRect returned is narrower.\n        If dy is negative, SkRect returned is taller.\n        If dy is positive, SkRect returned is shorter.\n\n        @param dx  added to fLeft and subtracted from fRight\n        @param dy  added to fTop and subtracted from fBottom\n        @return    SkRect inset symmetrically left and right, top and bottom\n    */\n    SkRect makeInset(SkScalar dx, SkScalar dy) const {\n        return MakeLTRB(fLeft + dx, fTop + dy, fRight - dx, fBottom - dy);\n    }\n\n    /** Returns SkRect, outset by (dx, dy).\n\n        If dx is negative, SkRect returned is narrower.\n        If dx is positive, SkRect returned is wider.\n        If dy is negative, SkRect returned is shorter.\n        If dy is positive, SkRect returned is taller.\n\n        @param dx  subtracted to fLeft and added from fRight\n        @param dy  subtracted to fTop and added from fBottom\n        @return    SkRect outset symmetrically left and right, top and bottom\n    */\n    SkRect makeOutset(SkScalar dx, SkScalar dy) const {\n        return MakeLTRB(fLeft - dx, fTop - dy, fRight + dx, fBottom + dy);\n    }\n\n    /** Offsets SkRect by adding dx to fLeft, fRight; and by adding dy to fTop, fBottom.\n\n        If dx is negative, moves SkRect to the left.\n        If dx is positive, moves SkRect to the right.\n        If dy is negative, moves SkRect upward.\n        If dy is positive, moves SkRect downward.\n\n        @param dx  offset added to fLeft and fRight\n        @param dy  offset added to fTop and fBottom\n    */\n    void offset(SkScalar dx, SkScalar dy) {\n        fLeft   += dx;\n        fTop    += dy;\n        fRight  += dx;\n        fBottom += dy;\n    }\n\n    /** Offsets SkRect by adding delta.fX to fLeft, fRight; and by adding delta.fY to\n        fTop, fBottom.\n\n        If delta.fX is negative, moves SkRect to the left.\n        If delta.fX is positive, moves SkRect to the right.\n        If delta.fY is negative, moves SkRect upward.\n        If delta.fY is positive, moves SkRect downward.\n\n        @param delta  added to SkRect\n    */\n    void offset(const SkPoint& delta) {\n        this->offset(delta.fX, delta.fY);\n    }\n\n    /** Offsets SkRect so that fLeft equals newX, and fTop equals newY. width and height\n        are unchanged.\n\n        @param newX  stored in fLeft, preserving width()\n        @param newY  stored in fTop, preserving height()\n    */\n    void offsetTo(SkScalar newX, SkScalar newY) {\n        fRight += newX - fLeft;\n        fBottom += newY - fTop;\n        fLeft = newX;\n        fTop = newY;\n    }\n\n    /** Insets SkRect by (dx, dy).\n\n        If dx is positive, makes SkRect narrower.\n        If dx is negative, makes SkRect wider.\n        If dy is positive, makes SkRect shorter.\n        If dy is negative, makes SkRect taller.\n\n        @param dx  added to fLeft and subtracted from fRight\n        @param dy  added to fTop and subtracted from fBottom\n    */\n    void inset(SkScalar dx, SkScalar dy)  {\n        fLeft   += dx;\n        fTop    += dy;\n        fRight  -= dx;\n        fBottom -= dy;\n    }\n\n    /** Outsets SkRect by (dx, dy).\n\n        If dx is positive, makes SkRect wider.\n        If dx is negative, makes SkRect narrower.\n        If dy is positive, makes SkRect taller.\n        If dy is negative, makes SkRect shorter.\n\n        @param dx  subtracted to fLeft and added from fRight\n        @param dy  subtracted to fTop and added from fBottom\n    */\n    void outset(SkScalar dx, SkScalar dy)  { this->inset(-dx, -dy); }\n\n    /** Returns true if SkRect intersects r, and sets SkRect to intersection.\n        Returns false if SkRect does not intersect r, and leaves SkRect unchanged.\n\n        Returns false if either r or SkRect is empty, leaving SkRect unchanged.\n\n        @param r  limit of result\n        @return   true if r and SkRect have area in common\n    */\n    bool intersect(const SkRect& r);\n\n    /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Returns true if SkRect intersects construction, and sets SkRect to intersection.\n        Returns false if SkRect does not intersect construction, and leaves SkRect unchanged.\n\n        Returns false if either construction or SkRect is empty, leaving SkRect unchanged.\n\n        @param left    x minimum of constructed SkRect\n        @param top     y minimum of constructed SkRect\n        @param right   x maximum of constructed SkRect\n        @param bottom  y maximum of constructed SkRect\n        @return        true if construction and SkRect have area in common\n    */\n    bool intersect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);\n\n    /** Returns true if a intersects b, and sets SkRect to intersection.\n        Returns false if a does not intersect b, and leaves SkRect unchanged.\n\n        Returns false if either a or b is empty, leaving SkRect unchanged.\n\n        @param a  SkRect to intersect\n        @param b  SkRect to intersect\n        @return   true if a and b have area in common\n    */\n    bool SK_WARN_UNUSED_RESULT intersect(const SkRect& a, const SkRect& b);\n\n\nprivate:\n    static bool Intersects(SkScalar al, SkScalar at, SkScalar ar, SkScalar ab,\n                           SkScalar bl, SkScalar bt, SkScalar br, SkScalar bb) {\n        SkScalar L = SkMaxScalar(al, bl);\n        SkScalar R = SkMinScalar(ar, br);\n        SkScalar T = SkMaxScalar(at, bt);\n        SkScalar B = SkMinScalar(ab, bb);\n        return L < R && T < B;\n    }\n\npublic:\n\n    /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Returns true if SkRect intersects construction.\n        Returns false if either construction or SkRect is empty, or do not intersect.\n\n        @param left    x minimum of constructed SkRect\n        @param top     y minimum of constructed SkRect\n        @param right   x maximum of constructed SkRect\n        @param bottom  y maximum of constructed SkRect\n        @return        true if construction and SkRect have area in common\n    */\n    bool intersects(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom) const {\n        return Intersects(fLeft, fTop, fRight, fBottom, left, top, right, bottom);\n    }\n\n    /** Returns true if SkRect intersects r.\n        Returns false if either r or SkRect is empty, or do not intersect.\n\n        @param r  SkRect to intersect\n        @return   true if r and SkRect have area in common\n    */\n    bool intersects(const SkRect& r) const {\n        return Intersects(fLeft, fTop, fRight, fBottom,\n                          r.fLeft, r.fTop, r.fRight, r.fBottom);\n    }\n\n    /** Returns true if a intersects b.\n        Returns false if either a or b is empty, or do not intersect.\n\n        @param a  SkRect to intersect\n        @param b  SkRect to intersect\n        @return   true if a and b have area in common\n    */\n    static bool Intersects(const SkRect& a, const SkRect& b) {\n        return Intersects(a.fLeft, a.fTop, a.fRight, a.fBottom,\n                          b.fLeft, b.fTop, b.fRight, b.fBottom);\n    }\n\n    /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort\n        construction.\n\n        Sets SkRect to the union of itself and the construction.\n\n        Has no effect if construction is empty. Otherwise, if SkRect is empty, sets\n        SkRect to construction.\n\n        @param left    x minimum of constructed SkRect\n        @param top     y minimum of constructed SkRect\n        @param right   x maximum of constructed SkRect\n        @param bottom  y maximum of constructed SkRect\n    */\n    void join(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom);\n\n    /** Sets SkRect to the union of itself and r.\n\n        Has no effect if r is empty. Otherwise, if SkRect is empty, sets\n        SkRect to r.\n\n        @param r  expansion SkRect\n    */\n    void join(const SkRect& r) {\n        this->join(r.fLeft, r.fTop, r.fRight, r.fBottom);\n    }\n\n    /** Sets SkRect to the union of itself and r.\n\n        Asserts if r is empty and SK_DEBUG is defined.\n        If SkRect is empty, sets SkRect to r.\n\n        May produce incorrect results if r is empty.\n\n        @param r  expansion SkRect\n    */\n    void joinNonEmptyArg(const SkRect& r) {\n        SkASSERT(!r.isEmpty());\n        // if we are empty, just assign\n        if (fLeft >= fRight || fTop >= fBottom) {\n            *this = r;\n        } else {\n            this->joinPossiblyEmptyRect(r);\n        }\n    }\n\n    /** Sets SkRect to the union of itself and the construction.\n\n        May produce incorrect results if SkRect or r is empty.\n\n        @param r  expansion SkRect\n    */\n    void joinPossiblyEmptyRect(const SkRect& r) {\n        fLeft   = SkMinScalar(fLeft, r.left());\n        fTop    = SkMinScalar(fTop, r.top());\n        fRight  = SkMaxScalar(fRight, r.right());\n        fBottom = SkMaxScalar(fBottom, r.bottom());\n    }\n\n    /** Returns true if: fLeft <= x < fRight && fTop <= y < fBottom.\n        Returns false if SkRect is empty.\n\n        @param x  test SkPoint x-coordinate\n        @param y  test SkPoint y-coordinate\n        @return   true if (x, y) is inside SkRect\n    */\n    bool contains(SkScalar x, SkScalar y) const {\n        return x >= fLeft && x < fRight && y >= fTop && y < fBottom;\n    }\n\n    /** Returns true if SkRect contains r.\n        Returns false if SkRect is empty or r is empty.\n\n        SkRect contains r when SkRect area completely includes r area.\n\n        @param r  SkRect contained\n        @return   true if all sides of SkRect are outside r\n    */\n    bool contains(const SkRect& r) const {\n        // todo: can we eliminate the this->isEmpty check?\n        return  !r.isEmpty() && !this->isEmpty() &&\n                fLeft <= r.fLeft && fTop <= r.fTop &&\n                fRight >= r.fRight && fBottom >= r.fBottom;\n    }\n\n    /** Returns true if SkRect contains r.\n        Returns false if SkRect is empty or r is empty.\n\n        SkRect contains r when SkRect area completely includes r area.\n\n        @param r  SkIRect contained\n        @return   true if all sides of SkRect are outside r\n    */\n    bool contains(const SkIRect& r) const {\n        // todo: can we eliminate the this->isEmpty check?\n        return  !r.isEmpty() && !this->isEmpty() &&\n                fLeft <= SkIntToScalar(r.fLeft) && fTop <= SkIntToScalar(r.fTop) &&\n                fRight >= SkIntToScalar(r.fRight) && fBottom >= SkIntToScalar(r.fBottom);\n    }\n\n    /** Sets SkIRect by adding 0.5 and discarding the fractional portion of SkRect\n        members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),\n                        SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).\n\n        @param dst  storage for SkIRect\n    */\n    void round(SkIRect* dst) const {\n        SkASSERT(dst);\n        dst->set(SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),\n                 SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom));\n    }\n\n    /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and\n        rounding up fRight and fBottom, using (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),\n                                               SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).\n\n        @param dst  storage for SkIRect\n    */\n    void roundOut(SkIRect* dst) const {\n        SkASSERT(dst);\n        dst->set(SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),\n                 SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom));\n    }\n\n    /** Sets SkRect by discarding the fractional portion of fLeft and fTop; and\n        rounding up fRight and fBottom, using (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),\n                                               SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).\n\n        @param dst  storage for SkRect\n    */\n    void roundOut(SkRect* dst) const {\n        dst->set(SkScalarFloorToScalar(fLeft),\n                 SkScalarFloorToScalar(fTop),\n                 SkScalarCeilToScalar(fRight),\n                 SkScalarCeilToScalar(fBottom));\n    }\n\n    /** Sets SkRect by rounding up fLeft and fTop; and\n        discarding the fractional portion of fRight and fBottom, using\n        (SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),\n         SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom)).\n\n        @param dst  storage for SkIRect\n    */\n    void roundIn(SkIRect* dst) const {\n        SkASSERT(dst);\n        dst->set(SkScalarCeilToInt(fLeft), SkScalarCeilToInt(fTop),\n                 SkScalarFloorToInt(fRight), SkScalarFloorToInt(fBottom));\n    }\n\n    /** Returns SkIRect by adding 0.5 and discarding the fractional portion of SkRect\n        members, using (SkScalarRoundToInt(fLeft), SkScalarRoundToInt(fTop),\n                        SkScalarRoundToInt(fRight), SkScalarRoundToInt(fBottom)).\n\n        @return  rounded SkIRect\n    */\n    SkIRect round() const {\n        SkIRect ir;\n        this->round(&ir);\n        return ir;\n    }\n\n    /** Sets SkIRect by discarding the fractional portion of fLeft and fTop; and\n        rounding up fRight and fBottom, using (SkScalarFloorToInt(fLeft), SkScalarFloorToInt(fTop),\n                                               SkScalarCeilToInt(fRight), SkScalarCeilToInt(fBottom)).\n\n        @return  rounded SkIRect\n    */\n    SkIRect roundOut() const {\n        SkIRect ir;\n        this->roundOut(&ir);\n        return ir;\n    }\n\n    /** Swaps fLeft and fRight if fLeft is greater than fRight; and swaps\n        fTop and fBottom if fTop is greater than fBottom. Result may be empty;\n        and width() and height() will be zero or positive.\n    */\n    void sort() {\n        if (fLeft > fRight) {\n            SkTSwap<SkScalar>(fLeft, fRight);\n        }\n\n        if (fTop > fBottom) {\n            SkTSwap<SkScalar>(fTop, fBottom);\n        }\n    }\n\n    /** Returns SkRect with fLeft and fRight swapped if fLeft is greater than fRight; and\n        with fTop and fBottom swapped if fTop is greater than fBottom. Result may be empty;\n        and width() and height() will be zero or positive.\n\n        @return  sorted SkRect\n    */\n    SkRect makeSorted() const {\n        return MakeLTRB(SkMinScalar(fLeft, fRight), SkMinScalar(fTop, fBottom),\n                        SkMaxScalar(fLeft, fRight), SkMaxScalar(fTop, fBottom));\n    }\n\n    /** Returns pointer to first scalar in SkRect, to treat it as an array with four\n        entries.\n\n        @return  pointer to fLeft\n    */\n    const SkScalar* asScalars() const { return &fLeft; }\n\n    /** Writes text representation of SkRect to standard output. Set asHex to true to\n        generate exact binary representations of floating point numbers.\n\n        @param asHex  true if SkScalar values are written as hexadecimal\n    */\n    void dump(bool asHex) const;\n\n    /** Writes text representation of SkRect to standard output. The representation may be\n        directly compiled as C++ code. Floating point values are written\n        with limited precision; it may not be possible to reconstruct original SkRect\n        from output.\n    */\n    void dump() const { this->dump(false); }\n\n    /** Writes text representation of SkRect to standard output. The representation may be\n        directly compiled as C++ code. Floating point values are written\n        in hexadecimal to preserve their exact bit pattern. The output reconstructs the\n        original SkRect.\n\n        Use instead of dump() when submitting\n    */\n    void dumpHex() const { this->dump(true); }\n};\n\ninline bool SkIRect::contains(const SkRect& r) const {\n    return  !r.isEmpty() && !this->isEmpty() &&     // check for empties\n            (SkScalar)fLeft <= r.fLeft && (SkScalar)fTop <= r.fTop &&\n            (SkScalar)fRight >= r.fRight && (SkScalar)fBottom >= r.fBottom;\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkRefCnt.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRefCnt_DEFINED\n#define SkRefCnt_DEFINED\n\n#include \"../private/SkTLogic.h\"\n#include \"SkTypes.h\"\n#include <atomic>\n#include <functional>\n#include <memory>\n#include <ostream>\n#include <type_traits>\n#include <utility>\n\n/** \\class SkRefCntBase\n\n    SkRefCntBase is the base class for objects that may be shared by multiple\n    objects. When an existing owner wants to share a reference, it calls ref().\n    When an owner wants to release its reference, it calls unref(). When the\n    shared object's reference count goes to zero as the result of an unref()\n    call, its (virtual) destructor is called. It is an error for the\n    destructor to be called explicitly (or via the object going out of scope on\n    the stack or calling delete) if getRefCnt() > 1.\n*/\nclass SK_API SkRefCntBase : SkNoncopyable {\npublic:\n    /** Default construct, initializing the reference count to 1.\n    */\n    SkRefCntBase() : fRefCnt(1) {}\n\n    /** Destruct, asserting that the reference count is 1.\n    */\n    virtual ~SkRefCntBase() {\n#ifdef SK_DEBUG\n        SkASSERTF(getRefCnt() == 1, \"fRefCnt was %d\", getRefCnt());\n        // illegal value, to catch us if we reuse after delete\n        fRefCnt.store(0, std::memory_order_relaxed);\n#endif\n    }\n\n#ifdef SK_DEBUG\n    /** Return the reference count. Use only for debugging. */\n    int32_t getRefCnt() const {\n        return fRefCnt.load(std::memory_order_relaxed);\n    }\n\n    void validate() const {\n        SkASSERT(getRefCnt() > 0);\n    }\n#endif\n\n    /** May return true if the caller is the only owner.\n     *  Ensures that all previous owner's actions are complete.\n     */\n    bool unique() const {\n        if (1 == fRefCnt.load(std::memory_order_acquire)) {\n            // The acquire barrier is only really needed if we return true.  It\n            // prevents code conditioned on the result of unique() from running\n            // until previous owners are all totally done calling unref().\n            return true;\n        }\n        return false;\n    }\n\n    /** Increment the reference count. Must be balanced by a call to unref().\n    */\n    void ref() const {\n        SkASSERT(getRefCnt() > 0);\n        // No barrier required.\n        (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed);\n    }\n\n    /** Decrement the reference count. If the reference count is 1 before the\n        decrement, then delete the object. Note that if this is the case, then\n        the object needs to have been allocated via new, and not on the stack.\n    */\n    void unref() const {\n        SkASSERT(getRefCnt() > 0);\n        // A release here acts in place of all releases we \"should\" have been doing in ref().\n        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {\n            // Like unique(), the acquire is only needed on success, to make sure\n            // code in internal_dispose() doesn't happen before the decrement.\n            this->internal_dispose();\n        }\n    }\n\nprotected:\n    /**\n     *  Allow subclasses to call this if they've overridden internal_dispose\n     *  so they can reset fRefCnt before the destructor is called or if they\n     *  choose not to call the destructor (e.g. using a free list).\n     */\n    void internal_dispose_restore_refcnt_to_1() const {\n        SkASSERT(0 == getRefCnt());\n        fRefCnt.store(1, std::memory_order_relaxed);\n    }\n\nprivate:\n    /**\n     *  Called when the ref count goes to 0.\n     */\n    virtual void internal_dispose() const {\n        this->internal_dispose_restore_refcnt_to_1();\n        delete this;\n    }\n\n    // The following friends are those which override internal_dispose()\n    // and conditionally call SkRefCnt::internal_dispose().\n    friend class SkWeakRefCnt;\n\n    mutable std::atomic<int32_t> fRefCnt;\n\n    typedef SkNoncopyable INHERITED;\n};\n\n#ifdef SK_REF_CNT_MIXIN_INCLUDE\n// It is the responsibility of the following include to define the type SkRefCnt.\n// This SkRefCnt should normally derive from SkRefCntBase.\n#include SK_REF_CNT_MIXIN_INCLUDE\n#else\nclass SK_API SkRefCnt : public SkRefCntBase {\n    // \"#include SK_REF_CNT_MIXIN_INCLUDE\" doesn't work with this build system.\n    #if defined(SK_BUILD_FOR_GOOGLE3)\n    public:\n        void deref() const { this->unref(); }\n    #endif\n};\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n/** Helper macro to safely assign one SkRefCnt[TS]* to another, checking for\n    null in on each side of the assignment, and ensuring that ref() is called\n    before unref(), in case the two pointers point to the same object.\n */\n\n#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)\n// This version heuristically detects data races, since those otherwise result\n// in redundant reference count decrements, which are exceedingly\n// difficult to debug.\n\n#define SkRefCnt_SafeAssign(dst, src)   \\\n    do {                                \\\n        typedef typename std::remove_reference<decltype(dst)>::type \\\n                SkRefCntPtrT;  \\\n        SkRefCntPtrT old_dst = *const_cast<SkRefCntPtrT volatile *>(&dst); \\\n        if (src) src->ref();            \\\n        if (old_dst) old_dst->unref();          \\\n        if (old_dst != *const_cast<SkRefCntPtrT volatile *>(&dst)) { \\\n            SkDebugf(\"Detected racing Skia calls at %s:%d\\n\", \\\n                    __FILE__, __LINE__); \\\n        } \\\n        dst = src;                      \\\n    } while (0)\n\n#else /* !SK_BUILD_FOR_ANDROID_FRAMEWORK */\n\n#define SkRefCnt_SafeAssign(dst, src)   \\\n    do {                                \\\n        if (src) src->ref();            \\\n        if (dst) dst->unref();          \\\n        dst = src;                      \\\n    } while (0)\n\n#endif\n\n\n/** Call obj->ref() and return obj. The obj must not be nullptr.\n */\ntemplate <typename T> static inline T* SkRef(T* obj) {\n    SkASSERT(obj);\n    obj->ref();\n    return obj;\n}\n\n/** Check if the argument is non-null, and if so, call obj->ref() and return obj.\n */\ntemplate <typename T> static inline T* SkSafeRef(T* obj) {\n    if (obj) {\n        obj->ref();\n    }\n    return obj;\n}\n\n/** Check if the argument is non-null, and if so, call obj->unref()\n */\ntemplate <typename T> static inline void SkSafeUnref(T* obj) {\n    if (obj) {\n        obj->unref();\n    }\n}\n\ntemplate<typename T> static inline void SkSafeSetNull(T*& obj) {\n    if (obj) {\n        obj->unref();\n        obj = nullptr;\n    }\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n// This is a variant of SkRefCnt that's Not Virtual, so weighs 4 bytes instead of 8 or 16.\n// There's only benefit to using this if the deriving class does not otherwise need a vtable.\ntemplate <typename Derived>\nclass SkNVRefCnt : SkNoncopyable {\npublic:\n    SkNVRefCnt() : fRefCnt(1) {}\n    ~SkNVRefCnt() { SkASSERTF(1 == getRefCnt(), \"NVRefCnt was %d\", getRefCnt()); }\n\n    // Implementation is pretty much the same as SkRefCntBase. All required barriers are the same:\n    //   - unique() needs acquire when it returns true, and no barrier if it returns false;\n    //   - ref() doesn't need any barrier;\n    //   - unref() needs a release barrier, and an acquire if it's going to call delete.\n\n    bool unique() const { return 1 == fRefCnt.load(std::memory_order_acquire); }\n    void ref() const { (void)fRefCnt.fetch_add(+1, std::memory_order_relaxed); }\n    void  unref() const {\n        if (1 == fRefCnt.fetch_add(-1, std::memory_order_acq_rel)) {\n            // restore the 1 for our destructor's assert\n            SkDEBUGCODE(fRefCnt.store(1, std::memory_order_relaxed));\n            delete (const Derived*)this;\n        }\n    }\n    void  deref() const { this->unref(); }\n\nprivate:\n    mutable std::atomic<int32_t> fRefCnt;\n    int32_t getRefCnt() const {\n        return fRefCnt.load(std::memory_order_relaxed);\n    }\n};\n\n///////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n *  Shared pointer class to wrap classes that support a ref()/unref() interface.\n *\n *  This can be used for classes inheriting from SkRefCnt, but it also works for other\n *  classes that match the interface, but have different internal choices: e.g. the hosted class\n *  may have its ref/unref be thread-safe, but that is not assumed/imposed by sk_sp.\n */\ntemplate <typename T> class sk_sp {\npublic:\n    using element_type = T;\n\n    constexpr sk_sp() : fPtr(nullptr) {}\n    constexpr sk_sp(std::nullptr_t) : fPtr(nullptr) {}\n\n    /**\n     *  Shares the underlying object by calling ref(), so that both the argument and the newly\n     *  created sk_sp both have a reference to it.\n     */\n    sk_sp(const sk_sp<T>& that) : fPtr(SkSafeRef(that.get())) {}\n    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>\n    sk_sp(const sk_sp<U>& that) : fPtr(SkSafeRef(that.get())) {}\n\n    /**\n     *  Move the underlying object from the argument to the newly created sk_sp. Afterwards only\n     *  the new sk_sp will have a reference to the object, and the argument will point to null.\n     *  No call to ref() or unref() will be made.\n     */\n    sk_sp(sk_sp<T>&& that) : fPtr(that.release()) {}\n    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>\n    sk_sp(sk_sp<U>&& that) : fPtr(that.release()) {}\n\n    /**\n     *  Adopt the bare pointer into the newly created sk_sp.\n     *  No call to ref() or unref() will be made.\n     */\n    explicit sk_sp(T* obj) : fPtr(obj) {}\n\n    /**\n     *  Calls unref() on the underlying object pointer.\n     */\n    ~sk_sp() {\n        SkSafeUnref(fPtr);\n        SkDEBUGCODE(fPtr = nullptr);\n    }\n\n    sk_sp<T>& operator=(std::nullptr_t) { this->reset(); return *this; }\n\n    /**\n     *  Shares the underlying object referenced by the argument by calling ref() on it. If this\n     *  sk_sp previously had a reference to an object (i.e. not null) it will call unref() on that\n     *  object.\n     */\n    sk_sp<T>& operator=(const sk_sp<T>& that) {\n        if (this != &that) {\n            this->reset(SkSafeRef(that.get()));\n        }\n        return *this;\n    }\n    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>\n    sk_sp<T>& operator=(const sk_sp<U>& that) {\n        this->reset(SkSafeRef(that.get()));\n        return *this;\n    }\n\n    /**\n     *  Move the underlying object from the argument to the sk_sp. If the sk_sp previously held\n     *  a reference to another object, unref() will be called on that object. No call to ref()\n     *  will be made.\n     */\n    sk_sp<T>& operator=(sk_sp<T>&& that) {\n        this->reset(that.release());\n        return *this;\n    }\n    template <typename U, typename = skstd::enable_if_t<std::is_convertible<U*, T*>::value>>\n    sk_sp<T>& operator=(sk_sp<U>&& that) {\n        this->reset(that.release());\n        return *this;\n    }\n\n    T& operator*() const {\n        SkASSERT(this->get() != nullptr);\n        return *this->get();\n    }\n\n    explicit operator bool() const { return this->get() != nullptr; }\n\n    T* get() const { return fPtr; }\n    T* operator->() const { return fPtr; }\n\n    /**\n     *  Adopt the new bare pointer, and call unref() on any previously held object (if not null).\n     *  No call to ref() will be made.\n     */\n    void reset(T* ptr = nullptr) {\n        // Calling fPtr->unref() may call this->~() or this->reset(T*).\n        // http://wg21.cmeerw.net/lwg/issue998\n        // http://wg21.cmeerw.net/lwg/issue2262\n        T* oldPtr = fPtr;\n        fPtr = ptr;\n        SkSafeUnref(oldPtr);\n    }\n\n    /**\n     *  Return the bare pointer, and set the internal object pointer to nullptr.\n     *  The caller must assume ownership of the object, and manage its reference count directly.\n     *  No call to unref() will be made.\n     */\n    T* SK_WARN_UNUSED_RESULT release() {\n        T* ptr = fPtr;\n        fPtr = nullptr;\n        return ptr;\n    }\n\n    void swap(sk_sp<T>& that) /*noexcept*/ {\n        using std::swap;\n        swap(fPtr, that.fPtr);\n    }\n\nprivate:\n    T*  fPtr;\n};\n\ntemplate <typename T> inline void swap(sk_sp<T>& a, sk_sp<T>& b) /*noexcept*/ {\n    a.swap(b);\n}\n\ntemplate <typename T, typename U> inline bool operator==(const sk_sp<T>& a, const sk_sp<U>& b) {\n    return a.get() == b.get();\n}\ntemplate <typename T> inline bool operator==(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {\n    return !a;\n}\ntemplate <typename T> inline bool operator==(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {\n    return !b;\n}\n\ntemplate <typename T, typename U> inline bool operator!=(const sk_sp<T>& a, const sk_sp<U>& b) {\n    return a.get() != b.get();\n}\ntemplate <typename T> inline bool operator!=(const sk_sp<T>& a, std::nullptr_t) /*noexcept*/ {\n    return static_cast<bool>(a);\n}\ntemplate <typename T> inline bool operator!=(std::nullptr_t, const sk_sp<T>& b) /*noexcept*/ {\n    return static_cast<bool>(b);\n}\n\ntemplate <typename T, typename U> inline bool operator<(const sk_sp<T>& a, const sk_sp<U>& b) {\n    // Provide defined total order on sk_sp.\n    // http://wg21.cmeerw.net/lwg/issue1297\n    // http://wg21.cmeerw.net/lwg/issue1401 .\n    return std::less<skstd::common_type_t<T*, U*>>()(a.get(), b.get());\n}\ntemplate <typename T> inline bool operator<(const sk_sp<T>& a, std::nullptr_t) {\n    return std::less<T*>()(a.get(), nullptr);\n}\ntemplate <typename T> inline bool operator<(std::nullptr_t, const sk_sp<T>& b) {\n    return std::less<T*>()(nullptr, b.get());\n}\n\ntemplate <typename T, typename U> inline bool operator<=(const sk_sp<T>& a, const sk_sp<U>& b) {\n    return !(b < a);\n}\ntemplate <typename T> inline bool operator<=(const sk_sp<T>& a, std::nullptr_t) {\n    return !(nullptr < a);\n}\ntemplate <typename T> inline bool operator<=(std::nullptr_t, const sk_sp<T>& b) {\n    return !(b < nullptr);\n}\n\ntemplate <typename T, typename U> inline bool operator>(const sk_sp<T>& a, const sk_sp<U>& b) {\n    return b < a;\n}\ntemplate <typename T> inline bool operator>(const sk_sp<T>& a, std::nullptr_t) {\n    return nullptr < a;\n}\ntemplate <typename T> inline bool operator>(std::nullptr_t, const sk_sp<T>& b) {\n    return b < nullptr;\n}\n\ntemplate <typename T, typename U> inline bool operator>=(const sk_sp<T>& a, const sk_sp<U>& b) {\n    return !(a < b);\n}\ntemplate <typename T> inline bool operator>=(const sk_sp<T>& a, std::nullptr_t) {\n    return !(a < nullptr);\n}\ntemplate <typename T> inline bool operator>=(std::nullptr_t, const sk_sp<T>& b) {\n    return !(nullptr < b);\n}\n\ntemplate <typename C, typename CT, typename T>\nauto operator<<(std::basic_ostream<C, CT>& os, const sk_sp<T>& sp) -> decltype(os << sp.get()) {\n    return os << sp.get();\n}\n\ntemplate <typename T, typename... Args>\nsk_sp<T> sk_make_sp(Args&&... args) {\n    return sk_sp<T>(new T(std::forward<Args>(args)...));\n}\n\n/*\n *  Returns a sk_sp wrapping the provided ptr AND calls ref on it (if not null).\n *\n *  This is different than the semantics of the constructor for sk_sp, which just wraps the ptr,\n *  effectively \"adopting\" it.\n */\ntemplate <typename T> sk_sp<T> sk_ref_sp(T* obj) {\n    return sk_sp<T>(SkSafeRef(obj));\n}\n\ntemplate <typename T> sk_sp<T> sk_ref_sp(const T* obj) {\n    return sk_sp<T>(const_cast<T*>(SkSafeRef(obj)));\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkRegion.h",
    "content": "\n/*\n * Copyright 2005 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkRegion_DEFINED\n#define SkRegion_DEFINED\n\n#include \"SkRect.h\"\n\nclass SkPath;\nclass SkRgnBuilder;\n\nnamespace android {\n    class Region;\n}\n\n#define SkRegion_gEmptyRunHeadPtr   ((SkRegion::RunHead*)-1)\n#define SkRegion_gRectRunHeadPtr    nullptr\n\n/** \\class SkRegion\n\n    The SkRegion class encapsulates the geometric region used to specify\n    clipping areas for drawing.\n*/\nclass SK_API SkRegion {\npublic:\n    typedef int32_t RunType;\n    static constexpr int kRunTypeSentinel = 0x7FFFFFFF;\n\n    SkRegion();\n    SkRegion(const SkRegion&);\n    explicit SkRegion(const SkIRect&);\n    ~SkRegion();\n\n    SkRegion& operator=(const SkRegion&);\n\n    /**\n     *  Return true if the two regions are equal. i.e. The enclose exactly\n     *  the same area.\n     */\n    bool operator==(const SkRegion& other) const;\n\n    /**\n     *  Return true if the two regions are not equal.\n     */\n    bool operator!=(const SkRegion& other) const {\n        return !(*this == other);\n    }\n\n    /**\n     *  Replace this region with the specified region, and return true if the\n     *  resulting region is non-empty.\n     */\n    bool set(const SkRegion& src) {\n        *this = src;\n        return !this->isEmpty();\n    }\n\n    /**\n     *  Swap the contents of this and the specified region. This operation\n     *  is gauarenteed to never fail.\n     */\n    void swap(SkRegion&);\n\n    /** Return true if this region is empty */\n    bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }\n\n    /** Return true if this region is a single, non-empty rectangle */\n    bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }\n\n    /** Return true if this region consists of more than 1 rectangular area */\n    bool isComplex() const { return !this->isEmpty() && !this->isRect(); }\n\n    /**\n     *  Return the bounds of this region. If the region is empty, returns an\n     *  empty rectangle.\n     */\n    const SkIRect& getBounds() const { return fBounds; }\n\n    /**\n     *  Returns a value that grows approximately linearly with the number of\n     *  intervals comprised in the region. Empty region will return 0, Rect\n     *  will return 1, Complex will return a value > 1.\n     *\n     *  Use this to compare two regions, where the larger count likely\n     *  indicates a more complex region.\n     */\n    int computeRegionComplexity() const;\n\n    /**\n     *  Returns true if the region is non-empty, and if so, appends the\n     *  boundary(s) of the region to the specified path.\n     *  If the region is empty, returns false, and path is left unmodified.\n     */\n    bool getBoundaryPath(SkPath* path) const;\n\n    /**\n     *  Set the region to be empty, and return false, since the resulting\n     *  region is empty\n     */\n    bool setEmpty();\n\n    /**\n     *  If rect is non-empty, set this region to that rectangle and return true,\n     *  otherwise set this region to empty and return false.\n     */\n    bool setRect(const SkIRect&);\n\n    /**\n     *  If left < right and top < bottom, set this region to that rectangle and\n     *  return true, otherwise set this region to empty and return false.\n     */\n    bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) {\n        return this->setRect({ left, top, right, bottom });\n    }\n\n    /**\n     *  Set this region to the union of an array of rects. This is generally\n     *  faster than calling region.op(rect, kUnion_Op) in a loop. If count is\n     *  0, then this region is set to the empty region.\n     *  @return true if the resulting region is non-empty\n     */\n    bool setRects(const SkIRect rects[], int count);\n\n    /**\n     *  Set this region to the specified region, and return true if it is\n     *  non-empty.\n     */\n    bool setRegion(const SkRegion&);\n\n    /**\n     *  Set this region to the area described by the path, clipped.\n     *  Return true if the resulting region is non-empty.\n     *  This produces a region that is identical to the pixels that would be\n     *  drawn by the path (with no antialiasing) with the specified clip.\n     */\n    bool setPath(const SkPath&, const SkRegion& clip);\n\n    /**\n     *  Returns true if the specified rectangle has a non-empty intersection\n     *  with this region.\n     */\n    bool intersects(const SkIRect&) const;\n\n    /**\n     *  Returns true if the specified region has a non-empty intersection\n     *  with this region.\n     */\n    bool intersects(const SkRegion&) const;\n\n    /**\n     *  Return true if the specified x,y coordinate is inside the region.\n     */\n    bool contains(int32_t x, int32_t y) const;\n\n    /**\n     *  Return true if the specified rectangle is completely inside the region.\n     *  This works for simple (rectangular) and complex regions, and always\n     *  returns the correct result. Note: if either this region or the rectangle\n     *  is empty, contains() returns false.\n     */\n    bool contains(const SkIRect&) const;\n\n    /**\n     *  Return true if the specified region is completely inside the region.\n     *  This works for simple (rectangular) and complex regions, and always\n     *  returns the correct result. Note: if either region is empty, contains()\n     *  returns false.\n     */\n    bool contains(const SkRegion&) const;\n\n    /**\n     *  Return true if this region is a single rectangle (not complex) and the\n     *  specified rectangle is contained by this region. Returning false is not\n     *  a guarantee that the rectangle is not contained by this region, but\n     *  return true is a guarantee that the rectangle is contained by this region.\n     */\n    bool quickContains(const SkIRect& r) const {\n        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);\n    }\n\n    /**\n     *  Return true if this region is a single rectangle (not complex) and the\n     *  specified rectangle is contained by this region. Returning false is not\n     *  a guarantee that the rectangle is not contained by this region, but\n     *  return true is a guarantee that the rectangle is contained by this\n     *  region.\n     */\n    bool quickContains(int32_t left, int32_t top, int32_t right,\n                       int32_t bottom) const {\n        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region\n\n        return left < right && top < bottom &&\n               fRunHead == SkRegion_gRectRunHeadPtr &&  // this->isRect()\n               /* fBounds.contains(left, top, right, bottom); */\n               fBounds.fLeft <= left && fBounds.fTop <= top &&\n               fBounds.fRight >= right && fBounds.fBottom >= bottom;\n    }\n\n    /**\n     *  Return true if this region is empty, or if the specified rectangle does\n     *  not intersect the region. Returning false is not a guarantee that they\n     *  intersect, but returning true is a guarantee that they do not.\n     */\n    bool quickReject(const SkIRect& rect) const {\n        return this->isEmpty() || rect.isEmpty() ||\n                !SkIRect::Intersects(fBounds, rect);\n    }\n\n    /**\n     *  Return true if this region, or rgn, is empty, or if their bounds do not\n     *  intersect. Returning false is not a guarantee that they intersect, but\n     *  returning true is a guarantee that they do not.\n     */\n    bool quickReject(const SkRegion& rgn) const {\n        return this->isEmpty() || rgn.isEmpty() ||\n               !SkIRect::Intersects(fBounds, rgn.fBounds);\n    }\n\n    /** Translate the region by the specified (dx, dy) amount. */\n    void translate(int dx, int dy) { this->translate(dx, dy, this); }\n\n    /**\n     *  Translate the region by the specified (dx, dy) amount, writing the\n     *  resulting region into dst. Note: it is legal to pass this region as the\n     *  dst parameter, effectively translating the region in place. If dst is\n     *  null, nothing happens.\n     */\n    void translate(int dx, int dy, SkRegion* dst) const;\n\n    /**\n     *  The logical operations that can be performed when combining two regions.\n     */\n    enum Op {\n        kDifference_Op, //!< subtract the op region from the first region\n        kIntersect_Op,  //!< intersect the two regions\n        kUnion_Op,      //!< union (inclusive-or) the two regions\n        kXOR_Op,        //!< exclusive-or the two regions\n        /** subtract the first region from the op region */\n        kReverseDifference_Op,\n        kReplace_Op,    //!< replace the dst region with the op region\n\n        kLastOp = kReplace_Op\n    };\n\n    static const int kOpCnt = kLastOp + 1;\n\n    /**\n     *  Set this region to the result of applying the Op to this region and the\n     *  specified rectangle: this = (this op rect).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(const SkIRect& rect, Op op) {\n        if (this->isRect() && kIntersect_Op == op) {\n            if (!fBounds.intersect(rect)) {\n                return this->setEmpty();\n            }\n            return true;\n        }\n        return this->op(*this, rect, op);\n    }\n\n    /**\n     *  Set this region to the result of applying the Op to this region and the\n     *  specified rectangle: this = (this op rect).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(int left, int top, int right, int bottom, Op op) {\n        SkIRect rect;\n        rect.set(left, top, right, bottom);\n        return this->op(*this, rect, op);\n    }\n\n    /**\n     *  Set this region to the result of applying the Op to this region and the\n     *  specified region: this = (this op rgn).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }\n\n    /**\n     *  Set this region to the result of applying the Op to the specified\n     *  rectangle and region: this = (rect op rgn).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(const SkIRect& rect, const SkRegion& rgn, Op);\n\n    /**\n     *  Set this region to the result of applying the Op to the specified\n     *  region and rectangle: this = (rgn op rect).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(const SkRegion& rgn, const SkIRect& rect, Op);\n\n    /**\n     *  Set this region to the result of applying the Op to the specified\n     *  regions: this = (rgna op rgnb).\n     *  Return true if the resulting region is non-empty.\n     */\n    bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);\n\n#ifdef SK_BUILD_FOR_ANDROID\n    /** Returns a new char* containing the list of rectangles in this region\n     */\n    char* toString();\n#endif\n\n    /**\n     *  Returns the sequence of rectangles, sorted in Y and X, that make up\n     *  this region.\n     */\n    class SK_API Iterator {\n    public:\n        Iterator() : fRgn(nullptr), fDone(true) {}\n        Iterator(const SkRegion&);\n        // if we have a region, reset to it and return true, else return false\n        bool rewind();\n        // reset the iterator, using the new region\n        void reset(const SkRegion&);\n        bool done() const { return fDone; }\n        void next();\n        const SkIRect& rect() const { return fRect; }\n        // may return null\n        const SkRegion* rgn() const { return fRgn; }\n\n    private:\n        const SkRegion* fRgn;\n        const RunType*  fRuns;\n        SkIRect         fRect;\n        bool            fDone;\n    };\n\n    /**\n     *  Returns the sequence of rectangles, sorted in Y and X, that make up\n     *  this region intersected with the specified clip rectangle.\n     */\n    class SK_API Cliperator {\n    public:\n        Cliperator(const SkRegion&, const SkIRect& clip);\n        bool done() { return fDone; }\n        void  next();\n        const SkIRect& rect() const { return fRect; }\n\n    private:\n        Iterator    fIter;\n        SkIRect     fClip;\n        SkIRect     fRect;\n        bool        fDone;\n    };\n\n    /**\n     *  Returns the sequence of runs that make up this region for the specified\n     *  Y scanline, clipped to the specified left and right X values.\n     */\n    class Spanerator {\n    public:\n        Spanerator(const SkRegion&, int y, int left, int right);\n        bool next(int* left, int* right);\n\n    private:\n        const SkRegion::RunType* fRuns;\n        int     fLeft, fRight;\n        bool    fDone;\n    };\n\n    /**\n     *  Write the region to the buffer, and return the number of bytes written.\n     *  If buffer is NULL, it still returns the number of bytes.\n     */\n    size_t writeToMemory(void* buffer) const;\n    /**\n     * Initializes the region from the buffer\n     *\n     * @param buffer Memory to read from\n     * @param length Amount of memory available in the buffer\n     * @return number of bytes read (must be a multiple of 4) or\n     *         0 if there was not enough memory available\n     */\n    size_t readFromMemory(const void* buffer, size_t length);\n\n    /**\n     *  Returns a reference to a global empty region. Just a convenience for\n     *  callers that need a const empty region.\n     */\n    static const SkRegion& GetEmptyRegion();\n\n    SkDEBUGCODE(void dump() const;)\n    SkDEBUGCODE(void validate() const;)\n    SkDEBUGCODE(static void UnitTest();)\n\n    // expose this to allow for regression test on complex regions\n    SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)\n\nprivate:\n    static constexpr int kOpCount = kReplace_Op + 1;\n\n    // T\n    // [B N L R S]\n    // S\n    static constexpr int kRectRegionRuns = 7;\n\n    friend class android::Region;    // needed for marshalling efficiently\n\n    struct RunHead;\n\n    // allocate space for count runs\n    void allocateRuns(int count);\n    void allocateRuns(int count, int ySpanCount, int intervalCount);\n    void allocateRuns(const RunHead& src);\n\n    SkIRect     fBounds;\n    RunHead*    fRunHead;\n\n    void freeRuns();\n\n    /**\n     *  Return the runs from this region, consing up fake runs if the region\n     *  is empty or a rect. In those 2 cases, we use tmpStorage to hold the\n     *  run data.\n     */\n    const RunType*  getRuns(RunType tmpStorage[], int* intervals) const;\n\n    // This is called with runs[] that do not yet have their interval-count\n    // field set on each scanline. That is computed as part of this call\n    // (inside ComputeRunBounds).\n    bool setRuns(RunType runs[], int count);\n\n    int count_runtype_values(int* itop, int* ibot) const;\n\n    bool isValid() const;\n\n    static void BuildRectRuns(const SkIRect& bounds,\n                              RunType runs[kRectRegionRuns]);\n\n    // If the runs define a simple rect, return true and set bounds to that\n    // rect. If not, return false and ignore bounds.\n    static bool RunsAreARect(const SkRegion::RunType runs[], int count,\n                             SkIRect* bounds);\n\n    /**\n     *  If the last arg is null, just return if the result is non-empty,\n     *  else store the result in the last arg.\n     */\n    static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);\n\n    friend struct RunHead;\n    friend class Iterator;\n    friend class Spanerator;\n    friend class SkRegionPriv;\n    friend class SkRgnBuilder;\n    friend class SkFlatRegion;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkScalar.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkScalar_DEFINED\n#define SkScalar_DEFINED\n\n#include \"../private/SkFloatingPoint.h\"\n\n#undef SK_SCALAR_IS_FLOAT\n#define SK_SCALAR_IS_FLOAT  1\n\ntypedef float SkScalar;\n\n#define SK_Scalar1                  1.0f\n#define SK_ScalarHalf               0.5f\n#define SK_ScalarSqrt2              1.41421356f\n#define SK_ScalarPI                 3.14159265f\n#define SK_ScalarTanPIOver8         0.414213562f\n#define SK_ScalarRoot2Over2         0.707106781f\n#define SK_ScalarMax                3.402823466e+38f\n#define SK_ScalarInfinity           SK_FloatInfinity\n#define SK_ScalarNegativeInfinity   SK_FloatNegativeInfinity\n#define SK_ScalarNaN                SK_FloatNaN\n\n#define SkScalarFloorToScalar(x)    sk_float_floor(x)\n#define SkScalarCeilToScalar(x)     sk_float_ceil(x)\n#define SkScalarRoundToScalar(x)    sk_float_floor((x) + 0.5f)\n#define SkScalarTruncToScalar(x)    sk_float_trunc(x)\n\n#define SkScalarFloorToInt(x)       sk_float_floor2int(x)\n#define SkScalarCeilToInt(x)        sk_float_ceil2int(x)\n#define SkScalarRoundToInt(x)       sk_float_round2int(x)\n\n#define SkScalarAbs(x)              sk_float_abs(x)\n#define SkScalarCopySign(x, y)      sk_float_copysign(x, y)\n#define SkScalarMod(x, y)           sk_float_mod(x,y)\n#define SkScalarSqrt(x)             sk_float_sqrt(x)\n#define SkScalarPow(b, e)           sk_float_pow(b, e)\n\n#define SkScalarSin(radians)        (float)sk_float_sin(radians)\n#define SkScalarCos(radians)        (float)sk_float_cos(radians)\n#define SkScalarTan(radians)        (float)sk_float_tan(radians)\n#define SkScalarASin(val)           (float)sk_float_asin(val)\n#define SkScalarACos(val)           (float)sk_float_acos(val)\n#define SkScalarATan2(y, x)         (float)sk_float_atan2(y,x)\n#define SkScalarExp(x)              (float)sk_float_exp(x)\n#define SkScalarLog(x)              (float)sk_float_log(x)\n#define SkScalarLog2(x)             (float)sk_float_log2(x)\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n\n#define SkIntToScalar(x)        static_cast<SkScalar>(x)\n#define SkIntToFloat(x)         static_cast<float>(x)\n#define SkScalarTruncToInt(x)   sk_float_saturate2int(x)\n\n#define SkScalarToFloat(x)      static_cast<float>(x)\n#define SkFloatToScalar(x)      static_cast<SkScalar>(x)\n#define SkScalarToDouble(x)     static_cast<double>(x)\n#define SkDoubleToScalar(x)     sk_double_to_float(x)\n\n#define SK_ScalarMin            (-SK_ScalarMax)\n\nstatic inline bool SkScalarIsNaN(SkScalar x) { return x != x; }\n\n/** Returns true if x is not NaN and not infinite\n */\nstatic inline bool SkScalarIsFinite(SkScalar x) { return sk_float_isfinite(x); }\n\nstatic inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) {\n    return sk_float_isfinite(a) && sk_float_isfinite(b);\n}\n\nstatic inline bool SkScalarsAreFinite(const SkScalar array[], int count) {\n    SkScalar prod = 0;\n    for (int i = 0; i < count; ++i) {\n        prod *= array[i];\n    }\n    // At this point, prod will either be NaN or 0\n    return prod == 0;   // if prod is NaN, this check will return false\n}\n\n/**\n *  Variant of SkScalarRoundToInt, that performs the rounding step (adding 0.5) explicitly using\n *  double, to avoid possibly losing the low bit(s) of the answer before calling floor().\n *\n *  This routine will likely be slower than SkScalarRoundToInt(), and should only be used when the\n *  extra precision is known to be valuable.\n *\n *  In particular, this catches the following case:\n *      SkScalar x = 0.49999997;\n *      int ix = SkScalarRoundToInt(x);\n *      SkASSERT(0 == ix);    // <--- fails\n *      ix = SkDScalarRoundToInt(x);\n *      SkASSERT(0 == ix);    // <--- succeeds\n */\nstatic inline int SkDScalarRoundToInt(SkScalar x) {\n    double xx = x;\n    xx += 0.5;\n    return (int)floor(xx);\n}\n\n/** Returns the fractional part of the scalar. */\nstatic inline SkScalar SkScalarFraction(SkScalar x) {\n    return x - SkScalarTruncToScalar(x);\n}\n\nstatic inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {\n    x = SkTMin(x, max);\n    x = SkTMax<SkScalar>(x, 0);\n    return x;\n}\n\nstatic inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {\n    return SkTPin(x, min, max);\n}\n\nSkScalar SkScalarSinCos(SkScalar radians, SkScalar* cosValue);\n\nstatic inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }\n\n#define SkScalarDiv(numer, denom)   sk_ieee_float_divide(numer, denom)\n#define SkScalarInvert(x)           sk_ieee_float_divide(SK_Scalar1, (x))\n#define SkScalarFastInvert(x)       sk_ieee_float_divide(SK_Scalar1, (x))\n#define SkScalarAve(a, b)           (((a) + (b)) * SK_ScalarHalf)\n#define SkScalarHalf(a)             ((a) * SK_ScalarHalf)\n\n#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))\n#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))\n\nstatic inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }\nstatic inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }\n\nstatic inline bool SkScalarIsInt(SkScalar x) {\n    return x == SkScalarFloorToScalar(x);\n}\n\n/**\n *  Returns -1 || 0 || 1 depending on the sign of value:\n *  -1 if x < 0\n *   0 if x == 0\n *   1 if x > 0\n */\nstatic inline int SkScalarSignAsInt(SkScalar x) {\n    return x < 0 ? -1 : (x > 0);\n}\n\n// Scalar result version of above\nstatic inline SkScalar SkScalarSignAsScalar(SkScalar x) {\n    return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);\n}\n\n#define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))\n\nstatic inline bool SkScalarNearlyZero(SkScalar x,\n                                      SkScalar tolerance = SK_ScalarNearlyZero) {\n    SkASSERT(tolerance >= 0);\n    return SkScalarAbs(x) <= tolerance;\n}\n\nstatic inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,\n                                       SkScalar tolerance = SK_ScalarNearlyZero) {\n    SkASSERT(tolerance >= 0);\n    return SkScalarAbs(x-y) <= tolerance;\n}\n\n/** Linearly interpolate between A and B, based on t.\n    If t is 0, return A\n    If t is 1, return B\n    else interpolate.\n    t must be [0..SK_Scalar1]\n*/\nstatic inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {\n    SkASSERT(t >= 0 && t <= SK_Scalar1);\n    return A + (B - A) * t;\n}\n\n/** Interpolate along the function described by (keys[length], values[length])\n    for the passed searchKey.  SearchKeys outside the range keys[0]-keys[Length]\n    clamp to the min or max value.  This function was inspired by a desire\n    to change the multiplier for thickness in fakeBold; therefore it assumes\n    the number of pairs (length) will be small, and a linear search is used.\n    Repeated keys are allowed for discontinuous functions (so long as keys is\n    monotonically increasing), and if key is the value of a repeated scalar in\n    keys, the first one will be used.  However, that may change if a binary\n    search is used.\n*/\nSkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],\n                            const SkScalar values[], int length);\n\n/*\n *  Helper to compare an array of scalars.\n */\nstatic inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {\n    SkASSERT(n >= 0);\n    for (int i = 0; i < n; ++i) {\n        if (a[i] != b[i]) {\n            return false;\n        }\n    }\n    return true;\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkSerialProcs.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSerialProcs_DEFINED\n#define SkSerialProcs_DEFINED\n\n#include \"SkImage.h\"\n#include \"SkPicture.h\"\n#include \"SkTypeface.h\"\n\n/**\n *  A serial-proc is asked to serialize the specified object (e.g. picture or image).\n *  If a data object is returned, it will be used (even if it is zero-length).\n *  If null is returned, then Skia will take its default action.\n *\n *  The default action for pictures is to use Skia's internal format.\n *  The default action for images is to encode either in its native format or PNG.\n *  The default action for typefaces is to use Skia's internal format.\n */\n\ntypedef sk_sp<SkData> (*SkSerialPictureProc)(SkPicture*, void* ctx);\ntypedef sk_sp<SkData> (*SkSerialImageProc)(SkImage*, void* ctx);\ntypedef sk_sp<SkData> (*SkSerialTypefaceProc)(SkTypeface*, void* ctx);\n\n/**\n *  Called with the encoded form of a picture (previously written with a custom\n *  SkSerialPictureProc proc). Return a picture object, or nullptr indicating failure.\n */\ntypedef sk_sp<SkPicture> (*SkDeserialPictureProc)(const void* data, size_t length, void* ctx);\n\n/**\n *  Called with the encoded from of an image. The proc can return an image object, or if it\n *  returns nullptr, then Skia will take its default action to try to create an image from the data.\n *\n *  Note that unlike SkDeserialPictureProc and SkDeserialTypefaceProc, return nullptr from this\n *  does not indicate failure, but is a signal for Skia to take its default action.\n */\ntypedef sk_sp<SkImage> (*SkDeserialImageProc)(const void* data, size_t length, void* ctx);\n\n/**\n *  Called with the encoded form of a typeface (previously written with a custom\n *  SkSerialTypefaceProc proc). Return a typeface object, or nullptr indicating failure.\n */\ntypedef sk_sp<SkTypeface> (*SkDeserialTypefaceProc)(const void* data, size_t length, void* ctx);\n\nstruct SK_API SkSerialProcs {\n    SkSerialPictureProc fPictureProc = nullptr;\n    void*               fPictureCtx = nullptr;\n\n    SkSerialImageProc   fImageProc = nullptr;\n    void*               fImageCtx = nullptr;\n\n    SkSerialTypefaceProc fTypefaceProc = nullptr;\n    void*                fTypefaceCtx = nullptr;\n};\n\nstruct SK_API SkDeserialProcs {\n    SkDeserialPictureProc   fPictureProc = nullptr;\n    void*                   fPictureCtx = nullptr;\n\n    SkDeserialImageProc     fImageProc = nullptr;\n    void*                   fImageCtx = nullptr;\n\n    SkDeserialTypefaceProc  fTypefaceProc = nullptr;\n    void*                   fTypefaceCtx = nullptr;\n};\n\n#endif\n\n"
  },
  {
    "path": "include/core/SkShader.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkShader_DEFINED\n#define SkShader_DEFINED\n\n#include \"SkBlendMode.h\"\n#include \"SkColor.h\"\n#include \"SkFilterQuality.h\"\n#include \"SkFlattenable.h\"\n#include \"SkImageInfo.h\"\n#include \"SkMatrix.h\"\n\nclass SkArenaAlloc;\nclass SkBitmap;\nclass SkColorFilter;\nclass SkColorSpace;\nclass SkColorSpaceXformer;\nclass SkImage;\nclass SkPath;\nclass SkPicture;\nclass SkRasterPipeline;\nclass GrContext;\nclass GrFragmentProcessor;\n\n/** \\class SkShader\n *\n *  Shaders specify the source color(s) for what is being drawn. If a paint\n *  has no shader, then the paint's color is used. If the paint has a\n *  shader, then the shader's color(s) are use instead, but they are\n *  modulated by the paint's alpha. This makes it easy to create a shader\n *  once (e.g. bitmap tiling or gradient) and then change its transparency\n *  w/o having to modify the original shader... only the paint's alpha needs\n *  to be modified.\n */\nclass SK_API SkShader : public SkFlattenable {\npublic:\n    enum TileMode {\n        /** replicate the edge color if the shader draws outside of its\n         *  original bounds\n         */\n        kClamp_TileMode,\n\n        /** repeat the shader's image horizontally and vertically */\n        kRepeat_TileMode,\n\n        /** repeat the shader's image horizontally and vertically, alternating\n         *  mirror images so that adjacent images always seam\n         */\n        kMirror_TileMode,\n\n        /**\n         *  Only draw within the original domain, return transparent-black everywhere else.\n         *  EXPERIMENTAL -- DO NOT USE YET\n         */\n        kDecal_TileMode,\n\n        kLast_TileMode = kDecal_TileMode\n    };\n\n    static constexpr int kTileModeCount = kLast_TileMode + 1;\n\n    /**\n     *  Returns the local matrix.\n     *\n     *  FIXME: This can be incorrect for a Shader with its own local matrix\n     *  that is also wrapped via CreateLocalMatrixShader.\n     */\n    const SkMatrix& getLocalMatrix() const;\n\n    /**\n     *  Returns true if the shader is guaranteed to produce only opaque\n     *  colors, subject to the SkPaint using the shader to apply an opaque\n     *  alpha value. Subclasses should override this to allow some\n     *  optimizations.\n     */\n    virtual bool isOpaque() const { return false; }\n\n#ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP\n    /**\n     *  Returns true if this shader is just a bitmap, and if not null, returns the bitmap,\n     *  localMatrix, and tilemodes. If this is not a bitmap, returns false and ignores the\n     *  out-parameters.\n     */\n    bool isABitmap(SkBitmap* outTexture, SkMatrix* outMatrix, TileMode xy[2]) const;\n\n    bool isABitmap() const {\n        return this->isABitmap(nullptr, nullptr, nullptr);\n    }\n#endif\n\n    /**\n     *  Iff this shader is backed by a single SkImage, return its ptr (the caller must ref this\n     *  if they want to keep it longer than the lifetime of the shader). If not, return nullptr.\n     */\n    SkImage* isAImage(SkMatrix* localMatrix, TileMode xy[2]) const;\n\n    bool isAImage() const {\n        return this->isAImage(nullptr, nullptr) != nullptr;\n    }\n\n    /**\n     *  If the shader subclass can be represented as a gradient, asAGradient\n     *  returns the matching GradientType enum (or kNone_GradientType if it\n     *  cannot). Also, if info is not null, asAGradient populates info with\n     *  the relevant (see below) parameters for the gradient.  fColorCount\n     *  is both an input and output parameter.  On input, it indicates how\n     *  many entries in fColors and fColorOffsets can be used, if they are\n     *  non-NULL.  After asAGradient has run, fColorCount indicates how\n     *  many color-offset pairs there are in the gradient.  If there is\n     *  insufficient space to store all of the color-offset pairs, fColors\n     *  and fColorOffsets will not be altered.  fColorOffsets specifies\n     *  where on the range of 0 to 1 to transition to the given color.\n     *  The meaning of fPoint and fRadius is dependant on the type of gradient.\n     *\n     *  None:\n     *      info is ignored.\n     *  Color:\n     *      fColorOffsets[0] is meaningless.\n     *  Linear:\n     *      fPoint[0] and fPoint[1] are the end-points of the gradient\n     *  Radial:\n     *      fPoint[0] and fRadius[0] are the center and radius\n     *  Conical:\n     *      fPoint[0] and fRadius[0] are the center and radius of the 1st circle\n     *      fPoint[1] and fRadius[1] are the center and radius of the 2nd circle\n     *  Sweep:\n     *      fPoint[0] is the center of the sweep.\n     */\n\n    enum GradientType {\n        kNone_GradientType,\n        kColor_GradientType,\n        kLinear_GradientType,\n        kRadial_GradientType,\n        kSweep_GradientType,\n        kConical_GradientType,\n        kLast_GradientType = kConical_GradientType\n    };\n\n    struct GradientInfo {\n        int         fColorCount;    //!< In-out parameter, specifies passed size\n                                    //   of fColors/fColorOffsets on input, and\n                                    //   actual number of colors/offsets on\n                                    //   output.\n        SkColor*    fColors;        //!< The colors in the gradient.\n        SkScalar*   fColorOffsets;  //!< The unit offset for color transitions.\n        SkPoint     fPoint[2];      //!< Type specific, see above.\n        SkScalar    fRadius[2];     //!< Type specific, see above.\n        TileMode    fTileMode;      //!< The tile mode used.\n        uint32_t    fGradientFlags; //!< see SkGradientShader::Flags\n    };\n\n    virtual GradientType asAGradient(GradientInfo* info) const;\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    struct ComposeRec {\n        const SkShader*     fShaderA;\n        const SkShader*     fShaderB;\n        SkBlendMode         fBlendMode;\n    };\n    virtual bool asACompose(ComposeRec*) const { return false; }\n#endif\n\n    //////////////////////////////////////////////////////////////////////////\n    //  Methods to create combinations or variants of shaders\n\n    /**\n     *  Return a shader that will apply the specified localMatrix to this shader.\n     *  The specified matrix will be applied before any matrix associated with this shader.\n     */\n    sk_sp<SkShader> makeWithLocalMatrix(const SkMatrix&) const;\n\n    /**\n     *  Create a new shader that produces the same colors as invoking this shader and then applying\n     *  the colorfilter.\n     */\n    sk_sp<SkShader> makeWithColorFilter(sk_sp<SkColorFilter>) const;\n\n    //////////////////////////////////////////////////////////////////////////\n    //  Factory methods for stock shaders\n\n    /**\n     *  Call this to create a new \"empty\" shader, that will not draw anything.\n     */\n    static sk_sp<SkShader> MakeEmptyShader();\n\n    /**\n     *  Call this to create a new shader that just draws the specified color. This should always\n     *  draw the same as a paint with this color (and no shader).\n     */\n    static sk_sp<SkShader> MakeColorShader(SkColor);\n\n    /**\n     *  Create a shader that draws the specified color (in the specified colorspace).\n     *\n     *  This works around the limitation that SkPaint::setColor() only takes byte values, and does\n     *  not support specific colorspaces.\n     */\n    static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);\n\n    /**\n     *  Compose two shaders together, using two operators: mode and lerp. The resulting colors\n     *  are computed by first combining the src and dst shaders using mode, and then linearly\n     *  interpolating between the dst and result colors using lerp.\n     *\n     *      result = dst * (1 - lerp) + (src (mode) dst) * lerp\n     *\n     *  If either shader is nullptr, then this returns nullptr.\n     *  If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].\n     */\n    static sk_sp<SkShader> MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src,\n                                       SkBlendMode mode, float lerp = 1);\n\n    /*\n     *  DEPRECATED: call MakeCompose.\n     */\n    static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,\n                                             SkBlendMode mode) {\n        return MakeCompose(std::move(dst), std::move(src), mode, 1);\n    }\n\n    /**\n     *  Compose two shaders together using a weighted average.\n     *\n     *  result = dst * (1 - lerp) + src * lerp\n     *\n     *  If either shader is nullptr, then this returns nullptr.\n     *  If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].\n     */\n    static sk_sp<SkShader> MakeMixer(sk_sp<SkShader> dst, sk_sp<SkShader> src, float lerp) {\n        return MakeCompose(std::move(dst), std::move(src), SkBlendMode::kSrc, lerp);\n    }\n\n    /** Call this to create a new shader that will draw with the specified bitmap.\n     *\n     *  If the bitmap cannot be used (e.g. has no pixels, or its dimensions\n     *  exceed implementation limits (currently at 64K - 1)) then SkEmptyShader\n     *  may be returned.\n     *\n     *  If the src is kA8_Config then that mask will be colorized using the color on\n     *  the paint.\n     *\n     *  @param src  The bitmap to use inside the shader\n     *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.\n     *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.\n     *  @return     Returns a new shader object. Note: this function never returns null.\n    */\n    static sk_sp<SkShader> MakeBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,\n                                            const SkMatrix* localMatrix = nullptr);\n\n    // NOTE: You can create an SkImage Shader with SkImage::newShader().\n\n    /** Call this to create a new shader that will draw with the specified picture.\n     *\n     *  @param src  The picture to use inside the shader (if not NULL, its ref count\n     *              is incremented). The SkPicture must not be changed after\n     *              successfully creating a picture shader.\n     *  @param tmx  The tiling mode to use when sampling the bitmap in the x-direction.\n     *  @param tmy  The tiling mode to use when sampling the bitmap in the y-direction.\n     *  @param tile The tile rectangle in picture coordinates: this represents the subset\n     *              (or superset) of the picture used when building a tile. It is not\n     *              affected by localMatrix and does not imply scaling (only translation\n     *              and cropping). If null, the tile rect is considered equal to the picture\n     *              bounds.\n     *  @return     Returns a new shader object. Note: this function never returns null.\n    */\n    static sk_sp<SkShader> MakePictureShader(sk_sp<SkPicture> src, TileMode tmx, TileMode tmy,\n                                             const SkMatrix* localMatrix, const SkRect* tile);\n\n    /**\n     *  If this shader can be represented by another shader + a localMatrix, return that shader and\n     *  the localMatrix. If not, return nullptr and ignore the localMatrix parameter.\n     */\n    // TODO: clean up clients, move to SkShaderBase.\n    virtual sk_sp<SkShader> makeAsALocalMatrixShader(SkMatrix* localMatrix) const;\n\nprivate:\n    SkShader() = default;\n    friend class SkShaderBase;\n\n    typedef SkFlattenable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkSize.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSize_DEFINED\n#define SkSize_DEFINED\n\n#include \"SkScalar.h\"\n\nstruct SkISize {\n    int32_t fWidth;\n    int32_t fHeight;\n\n    static SkISize Make(int32_t w, int32_t h) { return {w, h}; }\n\n    static SkISize MakeEmpty() { return {0, 0}; }\n\n    void set(int32_t w, int32_t h) { *this = SkISize{w, h}; }\n\n    /** Returns true iff fWidth == 0 && fHeight == 0\n     */\n    bool isZero() const { return 0 == fWidth && 0 == fHeight; }\n\n    /** Returns true if either widht or height are <= 0 */\n    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }\n\n    /** Set the width and height to 0 */\n    void setEmpty() { fWidth = fHeight = 0; }\n\n    int32_t width() const { return fWidth; }\n    int32_t height() const { return fHeight; }\n\n    bool equals(int32_t w, int32_t h) const { return fWidth == w && fHeight == h; }\n};\n\nstatic inline bool operator==(const SkISize& a, const SkISize& b) {\n    return a.fWidth == b.fWidth && a.fHeight == b.fHeight;\n}\n\nstatic inline bool operator!=(const SkISize& a, const SkISize& b) { return !(a == b); }\n\n///////////////////////////////////////////////////////////////////////////////\n\nstruct SkSize {\n    SkScalar fWidth;\n    SkScalar fHeight;\n\n    static SkSize Make(SkScalar w, SkScalar h) { return {w, h}; }\n\n    static SkSize Make(const SkISize& src) {\n        return {SkIntToScalar(src.width()), SkIntToScalar(src.height())};\n    }\n\n    SkSize& operator=(const SkISize& src) {\n        return *this = SkSize{SkIntToScalar(src.fWidth), SkIntToScalar(src.fHeight)};\n    }\n\n    static SkSize MakeEmpty() { return {0, 0}; }\n\n    void set(SkScalar w, SkScalar h) { *this = SkSize{w, h}; }\n\n    /** Returns true iff fWidth == 0 && fHeight == 0\n     */\n    bool isZero() const { return 0 == fWidth && 0 == fHeight; }\n\n    /** Returns true if either widht or height are <= 0 */\n    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }\n\n    /** Set the width and height to 0 */\n    void setEmpty() { *this = SkSize{0, 0}; }\n\n    SkScalar width() const { return fWidth; }\n    SkScalar height() const { return fHeight; }\n\n    bool equals(SkScalar w, SkScalar h) const { return fWidth == w && fHeight == h; }\n\n    SkISize toRound() const { return {SkScalarRoundToInt(fWidth), SkScalarRoundToInt(fHeight)}; }\n\n    SkISize toCeil() const { return {SkScalarCeilToInt(fWidth), SkScalarCeilToInt(fHeight)}; }\n\n    SkISize toFloor() const { return {SkScalarFloorToInt(fWidth), SkScalarFloorToInt(fHeight)}; }\n};\n\nstatic inline bool operator==(const SkSize& a, const SkSize& b) {\n    return a.fWidth == b.fWidth && a.fHeight == b.fHeight;\n}\n\nstatic inline bool operator!=(const SkSize& a, const SkSize& b) { return !(a == b); }\n#endif\n"
  },
  {
    "path": "include/core/SkStream.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkStream_DEFINED\n#define SkStream_DEFINED\n\n#include \"SkData.h\"\n#include \"SkRefCnt.h\"\n#include \"SkScalar.h\"\n\n#include <memory.h>\n\nclass SkStream;\nclass SkStreamRewindable;\nclass SkStreamSeekable;\nclass SkStreamAsset;\nclass SkStreamMemory;\n\n/**\n *  SkStream -- abstraction for a source of bytes. Subclasses can be backed by\n *  memory, or a file, or something else.\n *\n *  NOTE:\n *\n *  Classic \"streams\" APIs are sort of async, in that on a request for N\n *  bytes, they may return fewer than N bytes on a given call, in which case\n *  the caller can \"try again\" to get more bytes, eventually (modulo an error)\n *  receiving their total N bytes.\n *\n *  Skia streams behave differently. They are effectively synchronous, and will\n *  always return all N bytes of the request if possible. If they return fewer\n *  (the read() call returns the number of bytes read) then that means there is\n *  no more data (at EOF or hit an error). The caller should *not* call again\n *  in hopes of fulfilling more of the request.\n */\nclass SK_API SkStream : public SkNoncopyable {\npublic:\n    virtual ~SkStream() {}\n\n    /**\n     *  Attempts to open the specified file as a stream, returns nullptr on failure.\n     */\n    static std::unique_ptr<SkStreamAsset> MakeFromFile(const char path[]);\n\n    /** Reads or skips size number of bytes.\n     *  If buffer == NULL, skip size bytes, return how many were skipped.\n     *  If buffer != NULL, copy size bytes into buffer, return how many were copied.\n     *  @param buffer when NULL skip size bytes, otherwise copy size bytes into buffer\n     *  @param size the number of bytes to skip or copy\n     *  @return the number of bytes actually read.\n     */\n    virtual size_t read(void* buffer, size_t size) = 0;\n\n    /** Skip size number of bytes.\n     *  @return the actual number bytes that could be skipped.\n     */\n    size_t skip(size_t size) {\n        return this->read(nullptr, size);\n    }\n\n    /**\n     *  Attempt to peek at size bytes.\n     *  If this stream supports peeking, copy min(size, peekable bytes) into\n     *  buffer, and return the number of bytes copied.\n     *  If the stream does not support peeking, or cannot peek any bytes,\n     *  return 0 and leave buffer unchanged.\n     *  The stream is guaranteed to be in the same visible state after this\n     *  call, regardless of success or failure.\n     *  @param buffer Must not be NULL, and must be at least size bytes. Destination\n     *      to copy bytes.\n     *  @param size Number of bytes to copy.\n     *  @return The number of bytes peeked/copied.\n     */\n    virtual size_t peek(void* /*buffer*/, size_t /*size*/) const { return 0; }\n\n    /** Returns true when all the bytes in the stream have been read.\n     *  This may return true early (when there are no more bytes to be read)\n     *  or late (after the first unsuccessful read).\n     */\n    virtual bool isAtEnd() const = 0;\n\n    bool SK_WARN_UNUSED_RESULT readS8(int8_t*);\n    bool SK_WARN_UNUSED_RESULT readS16(int16_t*);\n    bool SK_WARN_UNUSED_RESULT readS32(int32_t*);\n\n    bool SK_WARN_UNUSED_RESULT readU8(uint8_t* i) { return this->readS8((int8_t*)i); }\n    bool SK_WARN_UNUSED_RESULT readU16(uint16_t* i) { return this->readS16((int16_t*)i); }\n    bool SK_WARN_UNUSED_RESULT readU32(uint32_t* i) { return this->readS32((int32_t*)i); }\n\n    bool SK_WARN_UNUSED_RESULT readBool(bool* b) {\n        uint8_t i;\n        if (!this->readU8(&i)) { return false; }\n        *b = (i != 0);\n        return true;\n    }\n    bool SK_WARN_UNUSED_RESULT readScalar(SkScalar*);\n    bool SK_WARN_UNUSED_RESULT readPackedUInt(size_t*);\n\n//SkStreamRewindable\n    /** Rewinds to the beginning of the stream. Returns true if the stream is known\n     *  to be at the beginning after this call returns.\n     */\n    virtual bool rewind() { return false; }\n\n    /** Duplicates this stream. If this cannot be done, returns NULL.\n     *  The returned stream will be positioned at the beginning of its data.\n     */\n    std::unique_ptr<SkStream> duplicate() const {\n        return std::unique_ptr<SkStream>(this->onDuplicate());\n    }\n    /** Duplicates this stream. If this cannot be done, returns NULL.\n     *  The returned stream will be positioned the same as this stream.\n     */\n    std::unique_ptr<SkStream> fork() const {\n        return std::unique_ptr<SkStream>(this->onFork());\n    }\n\n//SkStreamSeekable\n    /** Returns true if this stream can report it's current position. */\n    virtual bool hasPosition() const { return false; }\n    /** Returns the current position in the stream. If this cannot be done, returns 0. */\n    virtual size_t getPosition() const { return 0; }\n\n    /** Seeks to an absolute position in the stream. If this cannot be done, returns false.\n     *  If an attempt is made to seek past the end of the stream, the position will be set\n     *  to the end of the stream.\n     */\n    virtual bool seek(size_t /*position*/) { return false; }\n\n    /** Seeks to an relative offset in the stream. If this cannot be done, returns false.\n     *  If an attempt is made to move to a position outside the stream, the position will be set\n     *  to the closest point within the stream (beginning or end).\n     */\n    virtual bool move(long /*offset*/) { return false; }\n\n//SkStreamAsset\n    /** Returns true if this stream can report it's total length. */\n    virtual bool hasLength() const { return false; }\n    /** Returns the total length of the stream. If this cannot be done, returns 0. */\n    virtual size_t getLength() const { return 0; }\n\n//SkStreamMemory\n    /** Returns the starting address for the data. If this cannot be done, returns NULL. */\n    //TODO: replace with virtual const SkData* getData()\n    virtual const void* getMemoryBase() { return nullptr; }\n\nprivate:\n    virtual SkStream* onDuplicate() const { return nullptr; }\n    virtual SkStream* onFork() const { return nullptr; }\n};\n\n/** SkStreamRewindable is a SkStream for which rewind and duplicate are required. */\nclass SK_API SkStreamRewindable : public SkStream {\npublic:\n    bool rewind() override = 0;\n    std::unique_ptr<SkStreamRewindable> duplicate() const {\n        return std::unique_ptr<SkStreamRewindable>(this->onDuplicate());\n    }\nprivate:\n    SkStreamRewindable* onDuplicate() const override = 0;\n};\n\n/** SkStreamSeekable is a SkStreamRewindable for which position, seek, move, and fork are required. */\nclass SK_API SkStreamSeekable : public SkStreamRewindable {\npublic:\n    std::unique_ptr<SkStreamSeekable> duplicate() const {\n        return std::unique_ptr<SkStreamSeekable>(this->onDuplicate());\n    }\n\n    bool hasPosition() const override { return true; }\n    size_t getPosition() const override = 0;\n    bool seek(size_t position) override = 0;\n    bool move(long offset) override = 0;\n\n    std::unique_ptr<SkStreamSeekable> fork() const {\n        return std::unique_ptr<SkStreamSeekable>(this->onFork());\n    }\nprivate:\n    SkStreamSeekable* onDuplicate() const override = 0;\n    SkStreamSeekable* onFork() const override = 0;\n};\n\n/** SkStreamAsset is a SkStreamSeekable for which getLength is required. */\nclass SK_API SkStreamAsset : public SkStreamSeekable {\npublic:\n    bool hasLength() const override { return true; }\n    size_t getLength() const override = 0;\n\n    std::unique_ptr<SkStreamAsset> duplicate() const {\n        return std::unique_ptr<SkStreamAsset>(this->onDuplicate());\n    }\n    std::unique_ptr<SkStreamAsset> fork() const {\n        return std::unique_ptr<SkStreamAsset>(this->onFork());\n    }\nprivate:\n    SkStreamAsset* onDuplicate() const override = 0;\n    SkStreamAsset* onFork() const override = 0;\n};\n\n/** SkStreamMemory is a SkStreamAsset for which getMemoryBase is required. */\nclass SK_API SkStreamMemory : public SkStreamAsset {\npublic:\n    const void* getMemoryBase() override = 0;\n\n    std::unique_ptr<SkStreamMemory> duplicate() const {\n        return std::unique_ptr<SkStreamMemory>(this->onDuplicate());\n    }\n    std::unique_ptr<SkStreamMemory> fork() const {\n        return std::unique_ptr<SkStreamMemory>(this->onFork());\n    }\nprivate:\n    SkStreamMemory* onDuplicate() const override = 0;\n    SkStreamMemory* onFork() const override = 0;\n};\n\nclass SK_API SkWStream : SkNoncopyable {\npublic:\n    virtual ~SkWStream();\n\n    /** Called to write bytes to a SkWStream. Returns true on success\n        @param buffer the address of at least size bytes to be written to the stream\n        @param size The number of bytes in buffer to write to the stream\n        @return true on success\n    */\n    virtual bool write(const void* buffer, size_t size) = 0;\n    virtual void flush();\n\n    virtual size_t bytesWritten() const = 0;\n\n    // helpers\n\n    bool write8(U8CPU value)   {\n        uint8_t v = SkToU8(value);\n        return this->write(&v, 1);\n    }\n    bool write16(U16CPU value) {\n        uint16_t v = SkToU16(value);\n        return this->write(&v, 2);\n    }\n    bool write32(uint32_t v) {\n        return this->write(&v, 4);\n    }\n\n    bool writeText(const char text[]) {\n        SkASSERT(text);\n        return this->write(text, strlen(text));\n    }\n\n    bool newline() { return this->write(\"\\n\", strlen(\"\\n\")); }\n\n    bool writeDecAsText(int32_t);\n    bool writeBigDecAsText(int64_t, int minDigits = 0);\n    bool writeHexAsText(uint32_t, int minDigits = 0);\n    bool writeScalarAsText(SkScalar);\n\n    bool writeBool(bool v) { return this->write8(v); }\n    bool writeScalar(SkScalar);\n    bool writePackedUInt(size_t);\n\n    bool writeStream(SkStream* input, size_t length);\n\n    /**\n     * This returns the number of bytes in the stream required to store\n     * 'value'.\n     */\n    static int SizeOfPackedUInt(size_t value);\n};\n\nclass SK_API SkNullWStream : public SkWStream {\npublic:\n    SkNullWStream() : fBytesWritten(0) {}\n\n    bool write(const void*, size_t n) override { fBytesWritten += n; return true; }\n    void flush() override {}\n    size_t bytesWritten() const override { return fBytesWritten; }\n\nprivate:\n    size_t fBytesWritten;\n};\n\n////////////////////////////////////////////////////////////////////////////////////////\n\n#include <stdio.h>\n\n/** A stream that wraps a C FILE* file stream. */\nclass SK_API SkFILEStream : public SkStreamAsset {\npublic:\n    /** Initialize the stream by calling sk_fopen on the specified path.\n     *  This internal stream will be closed in the destructor.\n     */\n    explicit SkFILEStream(const char path[] = nullptr);\n\n    /** Initialize the stream with an existing C FILE stream.\n     *  The current position of the C FILE stream will be considered the\n     *  beginning of the SkFILEStream.\n     *  The C FILE stream will be closed in the destructor.\n     */\n    explicit SkFILEStream(FILE* file);\n\n    ~SkFILEStream() override;\n\n    static std::unique_ptr<SkFILEStream> Make(const char path[]) {\n        std::unique_ptr<SkFILEStream> stream(new SkFILEStream(path));\n        return stream->isValid() ? std::move(stream) : nullptr;\n    }\n\n    /** Returns true if the current path could be opened. */\n    bool isValid() const { return fFILE != nullptr; }\n\n    /** Close this SkFILEStream. */\n    void close();\n\n    size_t read(void* buffer, size_t size) override;\n    bool isAtEnd() const override;\n\n    bool rewind() override;\n    std::unique_ptr<SkStreamAsset> duplicate() const {\n        return std::unique_ptr<SkStreamAsset>(this->onDuplicate());\n    }\n\n    size_t getPosition() const override;\n    bool seek(size_t position) override;\n    bool move(long offset) override;\n\n    std::unique_ptr<SkStreamAsset> fork() const {\n        return std::unique_ptr<SkStreamAsset>(this->onFork());\n    }\n\n    size_t getLength() const override;\n\nprivate:\n    explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset);\n    explicit SkFILEStream(std::shared_ptr<FILE>, size_t size, size_t offset, size_t originalOffset);\n\n    SkStreamAsset* onDuplicate() const override;\n    SkStreamAsset* onFork() const override;\n\n    std::shared_ptr<FILE> fFILE;\n    // My own council will I keep on sizes and offsets.\n    size_t fSize;\n    size_t fOffset;\n    size_t fOriginalOffset;\n\n    typedef SkStreamAsset INHERITED;\n};\n\nclass SK_API SkMemoryStream : public SkStreamMemory {\npublic:\n    SkMemoryStream();\n\n    /** We allocate (and free) the memory. Write to it via getMemoryBase() */\n    SkMemoryStream(size_t length);\n\n    /** If copyData is true, the stream makes a private copy of the data. */\n    SkMemoryStream(const void* data, size_t length, bool copyData = false);\n\n    /** Creates the stream to read from the specified data */\n    SkMemoryStream(sk_sp<SkData>);\n\n    /** Returns a stream with a copy of the input data. */\n    static std::unique_ptr<SkMemoryStream> MakeCopy(const void* data, size_t length);\n\n    /** Returns a stream with a bare pointer reference to the input data. */\n    static std::unique_ptr<SkMemoryStream> MakeDirect(const void* data, size_t length);\n\n    /** Returns a stream with a shared reference to the input data. */\n    static std::unique_ptr<SkMemoryStream> Make(sk_sp<SkData> data);\n\n    /** Resets the stream to the specified data and length,\n        just like the constructor.\n        if copyData is true, the stream makes a private copy of the data\n    */\n    virtual void setMemory(const void* data, size_t length,\n                           bool copyData = false);\n    /** Replace any memory buffer with the specified buffer. The caller\n        must have allocated data with sk_malloc or sk_realloc, since it\n        will be freed with sk_free.\n    */\n    void setMemoryOwned(const void* data, size_t length);\n\n    sk_sp<SkData> asData() const { return fData; }\n    void setData(sk_sp<SkData>);\n\n    void skipToAlign4();\n    const void* getAtPos();\n\n    size_t read(void* buffer, size_t size) override;\n    bool isAtEnd() const override;\n\n    size_t peek(void* buffer, size_t size) const override;\n\n    bool rewind() override;\n\n    std::unique_ptr<SkMemoryStream> duplicate() const {\n        return std::unique_ptr<SkMemoryStream>(this->onDuplicate());\n    }\n\n    size_t getPosition() const override;\n    bool seek(size_t position) override;\n    bool move(long offset) override;\n\n    std::unique_ptr<SkMemoryStream> fork() const {\n        return std::unique_ptr<SkMemoryStream>(this->onFork());\n    }\n\n    size_t getLength() const override;\n\n    const void* getMemoryBase() override;\n\nprivate:\n    SkMemoryStream* onDuplicate() const override;\n    SkMemoryStream* onFork() const override;\n\n    sk_sp<SkData>   fData;\n    size_t          fOffset;\n\n    typedef SkStreamMemory INHERITED;\n};\n\n/////////////////////////////////////////////////////////////////////////////////////////////\n\nclass SK_API SkFILEWStream : public SkWStream {\npublic:\n    SkFILEWStream(const char path[]);\n    ~SkFILEWStream() override;\n\n    /** Returns true if the current path could be opened.\n    */\n    bool isValid() const { return fFILE != nullptr; }\n\n    bool write(const void* buffer, size_t size) override;\n    void flush() override;\n    void fsync();\n    size_t bytesWritten() const override;\n\nprivate:\n    FILE* fFILE;\n\n    typedef SkWStream INHERITED;\n};\n\nclass SK_API SkDynamicMemoryWStream : public SkWStream {\npublic:\n    SkDynamicMemoryWStream();\n    ~SkDynamicMemoryWStream() override;\n\n    bool write(const void* buffer, size_t size) override;\n    size_t bytesWritten() const override;\n\n    bool read(void* buffer, size_t offset, size_t size);\n\n    /** More efficient version of read(dst, 0, bytesWritten()). */\n    void copyTo(void* dst) const;\n    bool writeToStream(SkWStream* dst) const;\n\n    /** Equivalent to copyTo() followed by reset(), but may save memory use. */\n    void copyToAndReset(void* dst);\n\n    /** Equivalent to writeToStream() followed by reset(), but may save memory use. */\n    bool writeToAndReset(SkWStream* dst);\n\n    /** Return the contents as SkData, and then reset the stream. */\n    sk_sp<SkData> detachAsData();\n\n    /** Reset, returning a reader stream with the current content. */\n    std::unique_ptr<SkStreamAsset> detachAsStream();\n\n    /** Reset the stream to its original, empty, state. */\n    void reset();\n    void padToAlign4();\nprivate:\n    struct Block;\n    Block*  fHead;\n    Block*  fTail;\n    size_t  fBytesWrittenBeforeTail;\n\n#ifdef SK_DEBUG\n    void validate() const;\n#else\n    void validate() const {}\n#endif\n\n    // For access to the Block type.\n    friend class SkBlockMemoryStream;\n    friend class SkBlockMemoryRefCnt;\n\n    typedef SkWStream INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkString.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkString_DEFINED\n#define SkString_DEFINED\n\n#include \"../private/SkTArray.h\"\n#include \"SkScalar.h\"\n#include \"SkRefCnt.h\"\n\n#include <atomic>\n#include <stdarg.h>\n\n/*  Some helper functions for C strings\n*/\n\nstatic bool SkStrStartsWith(const char string[], const char prefixStr[]) {\n    SkASSERT(string);\n    SkASSERT(prefixStr);\n    return !strncmp(string, prefixStr, strlen(prefixStr));\n}\nstatic bool SkStrStartsWith(const char string[], const char prefixChar) {\n    SkASSERT(string);\n    return (prefixChar == *string);\n}\n\nbool SkStrEndsWith(const char string[], const char suffixStr[]);\nbool SkStrEndsWith(const char string[], const char suffixChar);\n\nint SkStrStartsWithOneOf(const char string[], const char prefixes[]);\n\nstatic int SkStrFind(const char string[], const char substring[]) {\n    const char *first = strstr(string, substring);\n    if (nullptr == first) return -1;\n    return SkToInt(first - &string[0]);\n}\n\nstatic int SkStrFindLastOf(const char string[], const char subchar) {\n    const char* last = strrchr(string, subchar);\n    if (nullptr == last) return -1;\n    return SkToInt(last - &string[0]);\n}\n\nstatic bool SkStrContains(const char string[], const char substring[]) {\n    SkASSERT(string);\n    SkASSERT(substring);\n    return (-1 != SkStrFind(string, substring));\n}\nstatic bool SkStrContains(const char string[], const char subchar) {\n    SkASSERT(string);\n    char tmp[2];\n    tmp[0] = subchar;\n    tmp[1] = '\\0';\n    return (-1 != SkStrFind(string, tmp));\n}\n\nstatic inline char *SkStrDup(const char string[]) {\n    char *ret = (char *) sk_malloc_throw(strlen(string)+1);\n    memcpy(ret,string,strlen(string)+1);\n    return ret;\n}\n\n/*\n *  The SkStrAppend... methods will write into the provided buffer, assuming it is large enough.\n *  Each method has an associated const (e.g. SkStrAppendU32_MaxSize) which will be the largest\n *  value needed for that method's buffer.\n *\n *  char storage[SkStrAppendU32_MaxSize];\n *  SkStrAppendU32(storage, value);\n *\n *  Note : none of the SkStrAppend... methods write a terminating 0 to their buffers. Instead,\n *  the methods return the ptr to the end of the written part of the buffer. This can be used\n *  to compute the length, and/or know where to write a 0 if that is desired.\n *\n *  char storage[SkStrAppendU32_MaxSize + 1];\n *  char* stop = SkStrAppendU32(storage, value);\n *  size_t len = stop - storage;\n *  *stop = 0;   // valid, since storage was 1 byte larger than the max.\n */\n\n#define SkStrAppendU32_MaxSize  10\nchar*   SkStrAppendU32(char buffer[], uint32_t);\n#define SkStrAppendU64_MaxSize  20\nchar*   SkStrAppendU64(char buffer[], uint64_t, int minDigits);\n\n#define SkStrAppendS32_MaxSize  (SkStrAppendU32_MaxSize + 1)\nchar*   SkStrAppendS32(char buffer[], int32_t);\n#define SkStrAppendS64_MaxSize  (SkStrAppendU64_MaxSize + 1)\nchar*   SkStrAppendS64(char buffer[], int64_t, int minDigits);\n\n/**\n *  Floats have at most 8 significant digits, so we limit our %g to that.\n *  However, the total string could be 15 characters: -1.2345678e-005\n *\n *  In theory we should only expect up to 2 digits for the exponent, but on\n *  some platforms we have seen 3 (as in the example above).\n */\n#define SkStrAppendScalar_MaxSize  15\n\n/**\n *  Write the scaler in decimal format into buffer, and return a pointer to\n *  the next char after the last one written. Note: a terminating 0 is not\n *  written into buffer, which must be at least SkStrAppendScalar_MaxSize.\n *  Thus if the caller wants to add a 0 at the end, buffer must be at least\n *  SkStrAppendScalar_MaxSize + 1 bytes large.\n */\n#define SkStrAppendScalar SkStrAppendFloat\n\nchar* SkStrAppendFloat(char buffer[], float);\n\n/** \\class SkString\n\n    Light weight class for managing strings. Uses reference\n    counting to make string assignments and copies very fast\n    with no extra RAM cost. Assumes UTF8 encoding.\n*/\nclass SK_API SkString {\npublic:\n                SkString();\n    explicit    SkString(size_t len);\n    explicit    SkString(const char text[]);\n                SkString(const char text[], size_t len);\n                SkString(const SkString&);\n                SkString(SkString&&);\n                ~SkString();\n\n    bool        isEmpty() const { return 0 == fRec->fLength; }\n    size_t      size() const { return (size_t) fRec->fLength; }\n    const char* c_str() const { return fRec->data(); }\n    char operator[](size_t n) const { return this->c_str()[n]; }\n\n    bool equals(const SkString&) const;\n    bool equals(const char text[]) const;\n    bool equals(const char text[], size_t len) const;\n\n    bool startsWith(const char prefixStr[]) const {\n        return SkStrStartsWith(fRec->data(), prefixStr);\n    }\n    bool startsWith(const char prefixChar) const {\n        return SkStrStartsWith(fRec->data(), prefixChar);\n    }\n    bool endsWith(const char suffixStr[]) const {\n        return SkStrEndsWith(fRec->data(), suffixStr);\n    }\n    bool endsWith(const char suffixChar) const {\n        return SkStrEndsWith(fRec->data(), suffixChar);\n    }\n    bool contains(const char substring[]) const {\n        return SkStrContains(fRec->data(), substring);\n    }\n    bool contains(const char subchar) const {\n        return SkStrContains(fRec->data(), subchar);\n    }\n    int find(const char substring[]) const {\n        return SkStrFind(fRec->data(), substring);\n    }\n    int findLastOf(const char subchar) const {\n        return SkStrFindLastOf(fRec->data(), subchar);\n    }\n\n    friend bool operator==(const SkString& a, const SkString& b) {\n        return a.equals(b);\n    }\n    friend bool operator!=(const SkString& a, const SkString& b) {\n        return !a.equals(b);\n    }\n\n    // these methods edit the string\n\n    SkString& operator=(const SkString&);\n    SkString& operator=(SkString&&);\n    SkString& operator=(const char text[]);\n\n    char* writable_str();\n    char& operator[](size_t n) { return this->writable_str()[n]; }\n\n    void reset();\n    /** Destructive resize, does not preserve contents. */\n    void resize(size_t len) { this->set(nullptr, len); }\n    void set(const SkString& src) { *this = src; }\n    void set(const char text[]);\n    void set(const char text[], size_t len);\n\n    void insert(size_t offset, const SkString& src) { this->insert(offset, src.c_str(), src.size()); }\n    void insert(size_t offset, const char text[]);\n    void insert(size_t offset, const char text[], size_t len);\n    void insertUnichar(size_t offset, SkUnichar);\n    void insertS32(size_t offset, int32_t value);\n    void insertS64(size_t offset, int64_t value, int minDigits = 0);\n    void insertU32(size_t offset, uint32_t value);\n    void insertU64(size_t offset, uint64_t value, int minDigits = 0);\n    void insertHex(size_t offset, uint32_t value, int minDigits = 0);\n    void insertScalar(size_t offset, SkScalar);\n\n    void append(const SkString& str) { this->insert((size_t)-1, str); }\n    void append(const char text[]) { this->insert((size_t)-1, text); }\n    void append(const char text[], size_t len) { this->insert((size_t)-1, text, len); }\n    void appendUnichar(SkUnichar uni) { this->insertUnichar((size_t)-1, uni); }\n    void appendS32(int32_t value) { this->insertS32((size_t)-1, value); }\n    void appendS64(int64_t value, int minDigits = 0) { this->insertS64((size_t)-1, value, minDigits); }\n    void appendU32(uint32_t value) { this->insertU32((size_t)-1, value); }\n    void appendU64(uint64_t value, int minDigits = 0) { this->insertU64((size_t)-1, value, minDigits); }\n    void appendHex(uint32_t value, int minDigits = 0) { this->insertHex((size_t)-1, value, minDigits); }\n    void appendScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }\n\n    void prepend(const SkString& str) { this->insert(0, str); }\n    void prepend(const char text[]) { this->insert(0, text); }\n    void prepend(const char text[], size_t len) { this->insert(0, text, len); }\n    void prependUnichar(SkUnichar uni) { this->insertUnichar(0, uni); }\n    void prependS32(int32_t value) { this->insertS32(0, value); }\n    void prependS64(int32_t value, int minDigits = 0) { this->insertS64(0, value, minDigits); }\n    void prependHex(uint32_t value, int minDigits = 0) { this->insertHex(0, value, minDigits); }\n    void prependScalar(SkScalar value) { this->insertScalar((size_t)-1, value); }\n\n    void printf(const char format[], ...) SK_PRINTF_LIKE(2, 3);\n    void appendf(const char format[], ...) SK_PRINTF_LIKE(2, 3);\n    void appendVAList(const char format[], va_list);\n    void prependf(const char format[], ...) SK_PRINTF_LIKE(2, 3);\n    void prependVAList(const char format[], va_list);\n\n    void remove(size_t offset, size_t length);\n\n    SkString& operator+=(const SkString& s) { this->append(s); return *this; }\n    SkString& operator+=(const char text[]) { this->append(text); return *this; }\n    SkString& operator+=(const char c) { this->append(&c, 1); return *this; }\n\n    /**\n     *  Swap contents between this and other. This function is guaranteed\n     *  to never fail or throw.\n     */\n    void swap(SkString& other);\n\nprivate:\n    struct Rec {\n    public:\n        constexpr Rec(uint32_t len, int32_t refCnt)\n            : fLength(len), fRefCnt(refCnt), fBeginningOfData(0)\n        { }\n        static sk_sp<Rec> Make(const char text[], size_t len);\n        uint32_t    fLength; // logically size_t, but we want it to stay 32bits\n        mutable std::atomic<int32_t> fRefCnt;\n        char        fBeginningOfData;\n\n        char* data() { return &fBeginningOfData; }\n        const char* data() const { return &fBeginningOfData; }\n\n        void ref() const;\n        void unref() const;\n        bool unique() const;\n    private:\n        // Ensure the unsized delete is called.\n        void operator delete(void* p) { ::operator delete(p); }\n    };\n    sk_sp<Rec> fRec;\n\n#ifdef SK_DEBUG\n    void validate() const;\n#else\n    void validate() const {}\n#endif\n\n    static const Rec gEmptyRec;\n};\n\n/// Creates a new string and writes into it using a printf()-style format.\nSkString SkStringPrintf(const char* format, ...);\n/// This makes it easier to write a caller as a VAR_ARGS function where the format string is\n/// optional.\nstatic inline SkString SkStringPrintf() { return SkString(); }\n\n// Specialized to take advantage of SkString's fast swap path. The unspecialized function is\n// declared in SkTypes.h and called by SkTSort.\ntemplate <> inline void SkTSwap(SkString& a, SkString& b) {\n    a.swap(b);\n}\n\nenum SkStrSplitMode {\n    // Strictly return all results. If the input is \",,\" and the separator is ',' this will return\n    // an array of three empty strings.\n    kStrict_SkStrSplitMode,\n\n    // Only nonempty results will be added to the results. Multiple separators will be\n    // coalesced. Separators at the beginning and end of the input will be ignored.  If the input is\n    // \",,\" and the separator is ',', this will return an empty vector.\n    kCoalesce_SkStrSplitMode\n};\n\n// Split str on any characters in delimiters into out.  (Think, strtok with a sane API.)\nvoid SkStrSplit(const char* str, const char* delimiters, SkStrSplitMode splitMode,\n                SkTArray<SkString>* out);\ninline void SkStrSplit(const char* str, const char* delimiters, SkTArray<SkString>* out) {\n    SkStrSplit(str, delimiters, kCoalesce_SkStrSplitMode, out);\n}\n\n#endif\n"
  },
  {
    "path": "include/core/SkStrokeRec.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkStrokeRec_DEFINED\n#define SkStrokeRec_DEFINED\n\n#include \"SkPaint.h\"\n\nclass SkPath;\n\nSK_BEGIN_REQUIRE_DENSE\nclass SkStrokeRec {\npublic:\n    enum InitStyle {\n        kHairline_InitStyle,\n        kFill_InitStyle\n    };\n    SkStrokeRec(InitStyle style);\n    SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1);\n    explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1);\n\n    enum Style {\n        kHairline_Style,\n        kFill_Style,\n        kStroke_Style,\n        kStrokeAndFill_Style\n    };\n\n    static constexpr int kStyleCount = kStrokeAndFill_Style + 1;\n\n    Style getStyle() const;\n    SkScalar getWidth() const { return fWidth; }\n    SkScalar getMiter() const { return fMiterLimit; }\n    SkPaint::Cap getCap() const { return (SkPaint::Cap)fCap; }\n    SkPaint::Join getJoin() const { return (SkPaint::Join)fJoin; }\n\n    bool isHairlineStyle() const {\n        return kHairline_Style == this->getStyle();\n    }\n\n    bool isFillStyle() const {\n        return kFill_Style == this->getStyle();\n    }\n\n    void setFillStyle();\n    void setHairlineStyle();\n    /**\n     *  Specify the strokewidth, and optionally if you want stroke + fill.\n     *  Note, if width==0, then this request is taken to mean:\n     *      strokeAndFill==true -> new style will be Fill\n     *      strokeAndFill==false -> new style will be Hairline\n     */\n    void setStrokeStyle(SkScalar width, bool strokeAndFill = false);\n\n    void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) {\n        fCap = cap;\n        fJoin = join;\n        fMiterLimit = miterLimit;\n    }\n\n    SkScalar getResScale() const {\n        return fResScale;\n    }\n\n    void setResScale(SkScalar rs) {\n        SkASSERT(rs > 0 && SkScalarIsFinite(rs));\n        fResScale = rs;\n    }\n\n    /**\n     *  Returns true if this specifes any thick stroking, i.e. applyToPath()\n     *  will return true.\n     */\n    bool needToApply() const {\n        Style style = this->getStyle();\n        return (kStroke_Style == style) || (kStrokeAndFill_Style == style);\n    }\n\n    /**\n     *  Apply these stroke parameters to the src path, returning the result\n     *  in dst.\n     *\n     *  If there was no change (i.e. style == hairline or fill) this returns\n     *  false and dst is unchanged. Otherwise returns true and the result is\n     *  stored in dst.\n     *\n     *  src and dst may be the same path.\n     */\n    bool applyToPath(SkPath* dst, const SkPath& src) const;\n\n    /**\n     *  Apply these stroke parameters to a paint.\n     */\n    void applyToPaint(SkPaint* paint) const;\n\n    /**\n     * Gives a conservative value for the outset that should applied to a\n     * geometries bounds to account for any inflation due to applying this\n     * strokeRec to the geometry.\n     */\n    SkScalar getInflationRadius() const;\n\n    /**\n     * Equivalent to:\n     *   SkStrokeRec rec(paint, style);\n     *   rec.getInflationRadius();\n     * This does not account for other effects on the paint (i.e. path\n     * effect).\n     */\n    static SkScalar GetInflationRadius(const SkPaint&, SkPaint::Style);\n\n    /**\n     * Compare if two SkStrokeRecs have an equal effect on a path.\n     * Equal SkStrokeRecs produce equal paths. Equality of produced\n     * paths does not take the ResScale parameter into account.\n     */\n    bool hasEqualEffect(const SkStrokeRec& other) const {\n        if (!this->needToApply()) {\n            return this->getStyle() == other.getStyle();\n        }\n        return fWidth == other.fWidth &&\n               fMiterLimit == other.fMiterLimit &&\n               fCap == other.fCap &&\n               fJoin == other.fJoin &&\n               fStrokeAndFill == other.fStrokeAndFill;\n    }\n\nprivate:\n    void init(const SkPaint&, SkPaint::Style, SkScalar resScale);\n\n    SkScalar        fResScale;\n    SkScalar        fWidth;\n    SkScalar        fMiterLimit;\n    // The following three members are packed together into a single u32.\n    // This is to avoid unnecessary padding and ensure binary equality for\n    // hashing (because the padded areas might contain garbage values).\n    //\n    // fCap and fJoin are larger than needed to avoid having to initialize\n    // any pad values\n    uint32_t        fCap : 16;             // SkPaint::Cap\n    uint32_t        fJoin : 15;            // SkPaint::Join\n    uint32_t        fStrokeAndFill : 1;    // bool\n};\nSK_END_REQUIRE_DENSE\n\n#endif\n"
  },
  {
    "path": "include/core/SkSurface.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSurface_DEFINED\n#define SkSurface_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkImage.h\"\n#include \"SkSurfaceProps.h\"\n\n#include \"GrTypes.h\"\n\nclass SkCanvas;\nclass SkDeferredDisplayList;\nclass SkPaint;\nclass SkSurfaceCharacterization;\nclass GrBackendRenderTarget;\nclass GrBackendSemaphore;\nclass GrBackendTexture;\nclass GrContext;\nclass GrRenderTarget;\n\n/** \\class SkSurface\n    SkSurface is responsible for managing the pixels that a canvas draws into. The pixels can be\n    allocated either in CPU memory (a raster surface) or on the GPU (a GrRenderTarget surface).\n    SkSurface takes care of allocating a SkCanvas that will draw into the surface. Call\n    surface->getCanvas() to use that canvas (but don't delete it, it is owned by the surface).\n    SkSurface always has non-zero dimensions. If there is a request for a new surface, and either\n    of the requested dimensions are zero, then nullptr will be returned.\n*/\nclass SK_API SkSurface : public SkRefCnt {\npublic:\n\n    /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.\n\n        SkSurface is returned if all parameters are valid.\n        Valid parameters include:\n        info dimensions are greater than zero;\n        info contains SkColorType and SkAlphaType supported by raster surface;\n        pixels is not nullptr;\n        rowBytes is large enough to contain info width pixels of SkColorType.\n\n        Pixel buffer size should be info height times computed rowBytes.\n        Pixels are not initialized.\n        To access pixels after drawing, call flush() or peekPixels().\n\n        @param imageInfo     width, height, SkColorType, SkAlphaType, SkColorSpace,\n                             of raster surface; width and height must be greater than zero\n        @param pixels        pointer to destination pixels buffer\n        @param rowBytes      interval from one SkSurface row to the next\n        @param surfaceProps  LCD striping orientation and setting for device independent fonts;\n                             may be nullptr\n        @return              SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRasterDirect(const SkImageInfo& imageInfo, void* pixels,\n                                             size_t rowBytes,\n                                             const SkSurfaceProps* surfaceProps = nullptr);\n\n    /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.\n        releaseProc is called with pixels and context when SkSurface is deleted.\n\n        SkSurface is returned if all parameters are valid.\n        Valid parameters include:\n        info dimensions are greater than zero;\n        info contains SkColorType and SkAlphaType supported by raster surface;\n        pixels is not nullptr;\n        rowBytes is large enough to contain info width pixels of SkColorType.\n\n        Pixel buffer size should be info height times computed rowBytes.\n        Pixels are not initialized.\n        To access pixels after drawing, call flush() or peekPixels().\n\n        @param imageInfo     width, height, SkColorType, SkAlphaType, SkColorSpace,\n                             of raster surface; width and height must be greater than zero\n        @param pixels        pointer to destination pixels buffer\n        @param rowBytes      interval from one SkSurface row to the next\n        @param releaseProc   called when SkSurface is deleted; may be nullptr\n        @param context       passed to releaseProc; may be nullptr\n        @param surfaceProps  LCD striping orientation and setting for device independent fonts;\n                             may be nullptr\n        @return              SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRasterDirectReleaseProc(const SkImageInfo& imageInfo, void* pixels,\n                                    size_t rowBytes,\n                                    void (*releaseProc)(void* pixels, void* context),\n                                    void* context, const SkSurfaceProps* surfaceProps = nullptr);\n\n    /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.\n        Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times\n        rowBytes, or times imageInfo.minRowBytes() if rowBytes is zero.\n        Pixel memory is deleted when SkSurface is deleted.\n\n        SkSurface is returned if all parameters are valid.\n        Valid parameters include:\n        info dimensions are greater than zero;\n        info contains SkColorType and SkAlphaType supported by raster surface;\n        rowBytes is large enough to contain info width pixels of SkColorType, or is zero.\n\n        If rowBytes is not zero, subsequent images returned by makeImageSnapshot()\n        have the same rowBytes.\n\n        @param imageInfo     width, height, SkColorType, SkAlphaType, SkColorSpace,\n                             of raster surface; width and height must be greater than zero\n        @param rowBytes      interval from one SkSurface row to the next; may be zero\n        @param surfaceProps  LCD striping orientation and setting for device independent fonts;\n                             may be nullptr\n        @return              SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo, size_t rowBytes,\n                                       const SkSurfaceProps* surfaceProps);\n\n    /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.\n        Allocates and zeroes pixel memory. Pixel memory size is imageInfo.height() times\n        imageInfo.minRowBytes().\n        Pixel memory is deleted when SkSurface is deleted.\n\n        SkSurface is returned if all parameters are valid.\n        Valid parameters include:\n        info dimensions are greater than zero;\n        info contains SkColorType and SkAlphaType supported by raster surface.\n\n        @param imageInfo  width, height, SkColorType, SkAlphaType, SkColorSpace,\n                          of raster surface; width and height must be greater than zero\n        @param props      LCD striping orientation and setting for device independent fonts;\n                          may be nullptr\n        @return           SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRaster(const SkImageInfo& imageInfo,\n                                       const SkSurfaceProps* props = nullptr) {\n        return MakeRaster(imageInfo, 0, props);\n    }\n\n    /** Allocates raster SkSurface. SkCanvas returned by SkSurface draws directly into pixels.\n        Allocates and zeroes pixel memory. Pixel memory size is height times width times\n        four. Pixel memory is deleted when SkSurface is deleted.\n\n        Internally, sets SkImageInfo to width, height, native color type, and\n        kPremul_SkAlphaType.\n\n        SkSurface is returned if width and height are greater than zero.\n\n        Use to create SkSurface that matches SkPMColor, the native pixel arrangement on\n        the platform. SkSurface drawn to output device skips converting its pixel format.\n\n        @param width         pixel column count; must be greater than zero\n        @param height        pixel row count; must be greater than zero\n        @param surfaceProps  LCD striping orientation and setting for device independent\n                             fonts; may be nullptr\n        @return              SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRasterN32Premul(int width, int height,\n                                                const SkSurfaceProps* surfaceProps = nullptr) {\n        return MakeRaster(SkImageInfo::MakeN32Premul(width, height), surfaceProps);\n    }\n\n    /** Wraps a GPU-backed texture into SkSurface. Caller must ensure the texture is\n        valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,\n        creates an intermediate MSAA SkSurface which is used for drawing backendTexture.\n\n        SkSurface is returned if all parameters are valid. backendTexture is valid if\n        its pixel configuration agrees with colorSpace and context; for instance, if\n        backendTexture has an sRGB configuration, then context must support sRGB,\n        and colorSpace must be present. Further, backendTexture width and height must\n        not exceed context capabilities, and the context must be able to support\n        back-end textures.\n\n        If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.\n\n        @param context         GPU context\n        @param backendTexture  texture residing on GPU\n        @param origin          one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param sampleCnt       samples per pixel, or 0 to disable full scene anti-aliasing\n        @param colorType       one of:\n                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                               kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param colorSpace      range of colors; may be nullptr\n        @param surfaceProps    LCD striping orientation and setting for device independent\n                               fonts; may be nullptr\n        @return                SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeFromBackendTexture(GrContext* context,\n                                                   const GrBackendTexture& backendTexture,\n                                                   GrSurfaceOrigin origin, int sampleCnt,\n                                                   SkColorType colorType,\n                                                   sk_sp<SkColorSpace> colorSpace,\n                                                   const SkSurfaceProps* surfaceProps);\n\n    /** Wraps a GPU-backed buffer into SkSurface. Caller must ensure backendRenderTarget\n        is valid for the lifetime of returned SkSurface.\n\n        SkSurface is returned if all parameters are valid. backendRenderTarget is valid if\n        its pixel configuration agrees with colorSpace and context; for instance, if\n        backendRenderTarget has an sRGB configuration, then context must support sRGB,\n        and colorSpace must be present. Further, backendRenderTarget width and height must\n        not exceed context capabilities, and the context must be able to support\n        back-end render targets.\n\n        If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.\n\n        @param context              GPU context\n        @param backendRenderTarget  GPU intermediate memory buffer\n        @param origin               one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param colorType            one of:\n                                    kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                                    kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                                    kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                                    kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param colorSpace           range of colors\n        @param surfaceProps         LCD striping orientation and setting for device independent\n                                    fonts; may be nullptr\n        @return                     SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeFromBackendRenderTarget(GrContext* context,\n                                                const GrBackendRenderTarget& backendRenderTarget,\n                                                GrSurfaceOrigin origin,\n                                                SkColorType colorType,\n                                                sk_sp<SkColorSpace> colorSpace,\n                                                const SkSurfaceProps* surfaceProps);\n\n    /** Wraps a GPU-backed texture into SkSurface. Caller must ensure backendTexture is\n        valid for the lifetime of returned SkSurface. If sampleCnt greater than zero,\n        creates an intermediate MSAA SkSurface which is used for drawing backendTexture.\n\n        SkSurface is returned if all parameters are valid. backendTexture is valid if\n        its pixel configuration agrees with colorSpace and context; for instance, if\n        backendTexture has an sRGB configuration, then context must support sRGB,\n        and colorSpace must be present. Further, backendTexture width and height must\n        not exceed context capabilities.\n\n        Returned SkSurface is available only for drawing into, and cannot generate an\n        SkImage.\n\n        If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.\n\n        @param context         GPU context\n        @param backendTexture  texture residing on GPU\n        @param origin          one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param sampleCnt       samples per pixel, or 0 to disable full scene anti-aliasing\n        @param colorType       one of:\n                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,\n                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,\n                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,\n                               kGray_8_SkColorType, kRGBA_F16_SkColorType\n        @param colorSpace      range of colors; may be nullptr\n        @param surfaceProps    LCD striping orientation and setting for device independent\n                               fonts; may be nullptr\n        @return                SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeFromBackendTextureAsRenderTarget(GrContext* context,\n                                                            const GrBackendTexture& backendTexture,\n                                                            GrSurfaceOrigin origin,\n                                                            int sampleCnt,\n                                                            SkColorType colorType,\n                                                            sk_sp<SkColorSpace> colorSpace,\n                                                            const SkSurfaceProps* surfaceProps);\n\n    /** Returns SkSurface on GPU indicated by context. Allocates memory for\n        pixels, based on the width, height, and SkColorType in ImageInfo.  budgeted\n        selects whether allocation for pixels is tracked by context. imageInfo\n        describes the pixel format in SkColorType, and transparency in\n        SkAlphaType, and color matching in SkColorSpace.\n\n        sampleCount requests the number of samples per pixel.\n        Pass zero to disable Multi_Sample_Anti_Aliasing.  The request is rounded\n        up to the next supported count, or rounded down if it is larger than the\n        maximum supported count.\n\n        surfaceOrigin pins either the top-left or the bottom-left corner to the origin.\n\n        shouldCreateWithMips hints that SkImage returned by makeImageSnapshot() is Mip_Map.\n\n        If SK_SUPPORT_GPU is defined as zero, has no effect and returns nullptr.\n\n        @param context               GPU context\n        @param budgeted              one of: SkBudgeted::kNo, SkBudgeted::kYes\n        @param imageInfo             width, height, SkColorType, SkAlphaType, SkColorSpace;\n                                     width, or height, or both, may be zero\n        @param sampleCount           samples per pixel, or 0 to disable full scene anti-aliasing\n        @param surfaceOrigin         one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin\n        @param surfaceProps          LCD striping orientation and setting for device independent\n                                     fonts; may be nullptr\n        @param shouldCreateWithMips  hint that SkSurface will host Mip_Map images\n        @return                      SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,\n                                             const SkImageInfo& imageInfo,\n                                             int sampleCount, GrSurfaceOrigin surfaceOrigin,\n                                             const SkSurfaceProps* surfaceProps,\n                                             bool shouldCreateWithMips = false);\n\n    /** Returns SkSurface on GPU indicated by context. Allocates memory for\n        pixels, based on the width, height, and SkColorType in ImageInfo.  budgeted\n        selects whether allocation for pixels is tracked by context. imageInfo\n        describes the pixel format in SkColorType, and transparency in\n        SkAlphaType, and color matching in SkColorSpace.\n\n        sampleCount requests the number of samples per pixel.\n        Pass zero to disable Multi_Sample_Anti_Aliasing.  The request is rounded\n        up to the next supported count, or rounded down if it is larger than the\n        maximum supported count.\n\n        SkSurface bottom-left corner is pinned to the origin.\n\n        @param context      GPU context\n        @param budgeted     one of: SkBudgeted::kNo, SkBudgeted::kYes\n        @param imageInfo    width, height, SkColorType, SkAlphaType, SkColorSpace,\n                            of raster surface; width, or height, or both, may be zero\n        @param sampleCount  samples per pixel, or 0 to disable Multi_Sample_Anti_Aliasing\n        @param props        LCD striping orientation and setting for device independent\n                            fonts; may be nullptr\n        @return             SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,\n                                             const SkImageInfo& imageInfo, int sampleCount,\n                                             const SkSurfaceProps* props) {\n        return MakeRenderTarget(context, budgeted, imageInfo, sampleCount,\n                                kBottomLeft_GrSurfaceOrigin, props);\n    }\n\n    /** Returns SkSurface on GPU indicated by context. Allocates memory for\n        pixels, based on the width, height, and SkColorType in ImageInfo.  budgeted\n        selects whether allocation for pixels is tracked by context. imageInfo\n        describes the pixel format in SkColorType, and transparency in\n        SkAlphaType, and color matching in SkColorSpace.\n\n        SkSurface bottom-left corner is pinned to the origin.\n\n        @param context    GPU context\n        @param budgeted   one of: SkBudgeted::kNo, SkBudgeted::kYes\n        @param imageInfo  width, height, SkColorType, SkAlphaType, SkColorSpace,\n                          of raster surface; width, or height, or both, may be zero\n        @return           SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRenderTarget(GrContext* context, SkBudgeted budgeted,\n                                             const SkImageInfo& imageInfo) {\n        if (!imageInfo.width() || !imageInfo.height()) {\n            return nullptr;\n        }\n        return MakeRenderTarget(context, budgeted, imageInfo, 0, kBottomLeft_GrSurfaceOrigin,\n                                nullptr);\n    }\n\n    /** Returns SkSurface on GPU indicated by context that is compatible with the provided\n        characterization. budgeted selects whether allocation for pixels is tracked by context.\n\n        @param context           GPU context\n        @param characterization  description of the desired SkSurface\n        @param budgeted          one of: SkBudgeted::kNo, SkBudgeted::kYes\n        @return                  SkSurface if all parameters are valid; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeRenderTarget(GrContext* context,\n                                             const SkSurfaceCharacterization& characterization,\n                                             SkBudgeted budgeted);\n\n    /** Returns SkSurface without backing pixels. Drawing to SkCanvas returned from SkSurface\n        has no effect. Calling makeImageSnapshot() on returned SkSurface returns nullptr.\n\n        @param width   one or greater\n        @param height  one or greater\n        @return        SkSurface if width and height are positive; otherwise, nullptr\n    */\n    static sk_sp<SkSurface> MakeNull(int width, int height);\n\n    /** Returns pixel count in each row; may be zero or greater.\n\n        @return  number of pixel columns\n    */\n    int width() const { return fWidth; }\n\n    /** Returns pixel row count; may be zero or greater.\n\n        @return  number of pixel rows\n    */\n    int height() const { return fHeight; }\n\n    /** Returns unique value identifying the content of SkSurface. Returned value changes\n        each time the content changes. Content is changed by drawing, or by calling\n        notifyContentWillChange().\n\n        @return  unique content identifier\n    */\n    uint32_t generationID();\n\n    /** \\enum SkSurface::ContentChangeMode\n        ContentChangeMode members are parameters to notifyContentWillChange().\n    */\n    enum ContentChangeMode {\n        kDiscard_ContentChangeMode, //!< discards surface on change\n        kRetain_ContentChangeMode,  //!< preserves surface on change\n    };\n\n    /** Notifies that SkSurface contents will be changed by code outside of Skia.\n        Subsequent calls to generationID() return a different value.\n\n        mode is normally passed as kRetain_ContentChangeMode.\n        Can we deprecate this?\n\n        @param mode  one of: kDiscard_ContentChangeMode, kRetain_ContentChangeMode\n    */\n    void notifyContentWillChange(ContentChangeMode mode);\n\n    enum BackendHandleAccess {\n        kFlushRead_BackendHandleAccess,    //!< back-end object is readable\n        kFlushWrite_BackendHandleAccess,   //!< back-end object is writable\n        kDiscardWrite_BackendHandleAccess, //!< back-end object must be overwritten\n    };\n\n    /** Deprecated.\n    */\n    static const BackendHandleAccess kFlushRead_TextureHandleAccess =\n            kFlushRead_BackendHandleAccess;\n\n    /** Deprecated.\n    */\n    static const BackendHandleAccess kFlushWrite_TextureHandleAccess =\n            kFlushWrite_BackendHandleAccess;\n\n    /** Deprecated.\n    */\n    static const BackendHandleAccess kDiscardWrite_TextureHandleAccess =\n            kDiscardWrite_BackendHandleAccess;\n\n    /** Retrieves the back-end texture. If SkSurface has no back-end texture, an invalid\n        object is returned. Call GrBackendTexture::isValid to determine if the result\n        is valid.\n\n        The returned GrBackendTexture should be discarded if the SkSurface is drawn to or deleted.\n\n        @param backendHandleAccess  one of:  kFlushRead_BackendHandleAccess,\n                                    kFlushWrite_BackendHandleAccess, kDiscardWrite_BackendHandleAccess\n        @return                     GPU texture reference; invalid on failure\n    */\n    GrBackendTexture getBackendTexture(BackendHandleAccess backendHandleAccess);\n\n    /** Retrieves the back-end render target. If SkSurface has no back-end render target, an invalid\n        object is returned. Call GrBackendRenderTarget::isValid to determine if the result\n        is valid.\n\n        The returned GrBackendRenderTarget should be discarded if the SkSurface is drawn to\n        or deleted.\n\n        @param backendHandleAccess  one of:  kFlushRead_BackendHandleAccess,\n                                    kFlushWrite_BackendHandleAccess, kDiscardWrite_BackendHandleAccess\n        @return                     GPU render target reference; invalid on failure\n    */\n    GrBackendRenderTarget getBackendRenderTarget(BackendHandleAccess backendHandleAccess);\n\n    /** Returns SkCanvas that draws into SkSurface. Subsequent calls return the same SkCanvas.\n        SkCanvas returned is managed and owned by SkSurface, and is deleted when SkSurface\n        is deleted.\n\n        @return  drawing SkCanvas for SkSurface\n    */\n    SkCanvas* getCanvas();\n\n    /** Returns a compatible SkSurface, or nullptr. Returned SkSurface contains\n        the same raster, GPU, or null properties as the original. Returned SkSurface\n        does not share the same pixels.\n\n        Returns nullptr if imageInfo width or height are zero, or if imageInfo\n        is incompatible with SkSurface.\n\n        @param imageInfo  width, height, SkColorType, SkAlphaType, SkColorSpace,\n                          of SkSurface; width and height must be greater than zero\n        @return           compatible SkSurface or nullptr\n    */\n    sk_sp<SkSurface> makeSurface(const SkImageInfo& imageInfo);\n\n    /** Returns SkImage capturing SkSurface contents. Subsequent drawing to SkSurface contents\n        are not captured. SkImage allocation is accounted for if SkSurface was created with\n        SkBudgeted::kYes.\n\n        @return  SkImage initialized with SkSurface contents\n    */\n    sk_sp<SkImage> makeImageSnapshot();\n\n    /** Draws SkSurface contents to canvas, with its top-left corner at (x, y).\n\n        If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter,\n        SkBlendMode, and SkDrawLooper.\n\n        @param canvas  SkCanvas drawn into\n        @param x       horizontal offset in SkCanvas\n        @param y       vertical offset in SkCanvas\n        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,\n                       and so on; or nullptr\n    */\n    void draw(SkCanvas* canvas, SkScalar x, SkScalar y, const SkPaint* paint);\n\n    /** Copies SkSurface pixel address, row bytes, and SkImageInfo to SkPixmap, if address\n        is available, and returns true. If pixel address is not available, return\n        false and leave SkPixmap unchanged.\n\n        pixmap contents become invalid on any future change to SkSurface.\n\n        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored\n        @return        true if SkSurface has direct access to pixels\n    */\n    bool peekPixels(SkPixmap* pixmap);\n\n    /** Copies SkRect of pixels to dst.\n\n        Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).\n        Destination SkRect corners are (0, 0) and (dst.width(), dst.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to dst.colorType() and dst.alphaType() if required.\n\n        Pixels are readable when SkSurface is raster, or backed by a GPU.\n\n        The destination pixel storage must be allocated by the caller.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. dst contents outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down destination.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkPixmap pixels could not be allocated.\n        - dst.rowBytes() is too small to contain one row of pixels.\n\n        @param dst   storage for pixels copied from SkSurface\n        @param srcX  offset into readable pixels in x; may be negative\n        @param srcY  offset into readable pixels in y; may be negative\n        @return      true if pixels were copied\n    */\n    bool readPixels(const SkPixmap& dst, int srcX, int srcY);\n\n    /** Copies SkRect of pixels from SkCanvas into dstPixels.\n\n        Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).\n        Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to dstInfo.colorType() and dstInfo.alphaType() if required.\n\n        Pixels are readable when SkSurface is raster, or backed by a GPU.\n\n        The destination pixel storage must be allocated by the caller.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. dstPixels contents outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down destination.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkSurface pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().\n        - dstRowBytes is too small to contain one row of pixels.\n\n        @param dstInfo      width, height, SkColorType, and SkAlphaType of dstPixels\n        @param dstPixels    storage for pixels; dstInfo.height() times dstRowBytes, or larger\n        @param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger\n        @param srcX         offset into readable pixels in x; may be negative\n        @param srcY         offset into readable pixels in y; may be negative\n        @return             true if pixels were copied\n    */\n    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,\n                    int srcX, int srcY);\n\n    /** Copies SkRect of pixels from SkSurface into bitmap.\n\n        Source SkRect corners are (srcX, srcY) and SkSurface (width(), height()).\n        Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to bitmap.colorType() and bitmap.alphaType() if required.\n\n        Pixels are readable when SkSurface is raster, or backed by a GPU.\n\n        The destination pixel storage must be allocated by the caller.\n\n        Pixel values are converted only if SkColorType and SkAlphaType\n        do not match. Only pixels within both source and destination rectangles\n        are copied. dst contents outside SkRect intersection are unchanged.\n\n        Pass negative values for srcX or srcY to offset pixels across or down destination.\n\n        Does not copy, and returns false if:\n        - Source and destination rectangles do not intersect.\n        - SkSurface pixels could not be converted to dst.colorType() or dst.alphaType().\n        - dst pixels could not be allocated.\n        - dst.rowBytes() is too small to contain one row of pixels.\n\n        @param dst   storage for pixels copied from SkSurface\n        @param srcX  offset into readable pixels in x; may be negative\n        @param srcY  offset into readable pixels in y; may be negative\n        @return      true if pixels were copied\n    */\n    bool readPixels(const SkBitmap& dst, int srcX, int srcY);\n\n    /** Copies SkRect of pixels from the src SkPixmap to the SkSurface.\n\n        Source SkRect corners are (0, 0) and (src.width(), src.height()).\n        Destination SkRect corners are (dstX, dstY) and (dstX + Surface width(), dstY + Surface height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to SkSurface colorType() and SkSurface alphaType() if required.\n\n        @param src   storage for pixels to copy to SkSurface\n        @param dstX  x position relative to SkSurface to begin copy; may be negative\n        @param dstY  x position relative to SkSurface to begin copy; may be negative\n    */\n    void writePixels(const SkPixmap& src, int dstX, int dstY);\n\n    /** Copies SkRect of pixels from the src SkBitmap to the SkSurface.\n\n        Source SkRect corners are (0, 0) and (src.width(), src.height()).\n        Destination SkRect corners are (dstX, dstY) and (dstX + Surface width(), dstY + Surface height()).\n        Copies each readable pixel intersecting both rectangles, without scaling,\n        converting to SkSurface colorType() and SkSurface alphaType() if required.\n\n        @param src   storage for pixels to copy to SkSurface\n        @param dstX  x position relative to SkSurface to begin copy; may be negative\n        @param dstY  x position relative to SkSurface to begin copy; may be negative\n    */\n    void writePixels(const SkBitmap& src, int dstX, int dstY);\n\n    /** Returns SkSurfaceProps for surface.\n\n        @return  LCD striping orientation and setting for device independent fonts\n    */\n    const SkSurfaceProps& props() const { return fProps; }\n\n    /** To be deprecated soon.\n    */\n    void prepareForExternalIO();\n\n    /** Issues pending SkSurface commands to the GPU-backed API and resolves any SkSurface MSAA.\n\n        Skia flushes as needed, so it is not necessary to call this if Skia manages\n        drawing and object lifetime. Call when interleaving Skia calls with native\n        GPU calls.\n    */\n    void flush();\n\n    /** Issues pending SkSurface commands to the GPU-backed API and resolves any SkSurface MSAA.\n        After issuing all commands, signalSemaphores of count numSemaphores semaphores\n        are signaled by the GPU.\n\n        For each GrBackendSemaphore in signalSemaphores:\n        if GrBackendSemaphore is initialized, the GPU back-end uses the semaphore as is;\n        otherwise, a new semaphore is created and initializes GrBackendSemaphore.\n\n        The caller must delete the semaphores created and returned in signalSemaphores.\n        GrBackendSemaphore can be deleted as soon as this function returns.\n\n        If the back-end API is OpenGL only uninitialized backend semaphores are supported.\n\n        If the back-end API is Vulkan semaphores may be initialized or uninitialized.\n        If uninitialized, created semaphores are valid only with the VkDevice\n        with which they were created.\n\n        If GrSemaphoresSubmitted::kNo is returned, the GPU back-end did not create or\n        add any semaphores to signal on the GPU; the caller should not instruct the GPU\n        to wait on any of the semaphores.\n\n        Pending surface commands are flushed regardless of the return result.\n\n        @param numSemaphores     size of signalSemaphores array\n        @param signalSemaphores  array of semaphore containers\n        @return                  one of: GrSemaphoresSubmitted::kYes, GrSemaphoresSubmitted::kNo\n    */\n    GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,\n                                                   GrBackendSemaphore signalSemaphores[]);\n\n    /** Inserts a list of GPU semaphores that the current GPU-backed API must wait on before\n        executing any more commands on the GPU for this surface. Skia will take ownership of the\n        underlying semaphores and delete them once they have been signaled and waited on.\n        If this call returns false, then the GPU back-end will not wait on any passed in semaphores,\n        and the client will still own the semaphores.\n\n        @param numSemaphores   size of waitSemaphores array\n        @param waitSemaphores  array of semaphore containers\n        @return                true if GPU is waiting on semaphores\n    */\n    bool wait(int numSemaphores, const GrBackendSemaphore* waitSemaphores);\n\n    /** Initializes SkSurfaceCharacterization that can be used to perform GPU back-end\n        processing in a separate thread. Typically this is used to divide drawing\n        into multiple tiles. DeferredDisplayListRecorder records the drawing commands\n        for each tile.\n\n        Return true if SkSurface supports characterization. raster surface returns false.\n\n        @param characterization  properties for parallel drawing\n        @return                  true if supported\n    */\n    bool characterize(SkSurfaceCharacterization* characterization) const;\n\n    /** Draws deferred display list created using SkDeferredDisplayListRecorder.\n        Has no effect and returns false if SkSurfaceCharacterization stored in\n        deferredDisplayList is not compatible with SkSurface.\n\n        raster surface returns false.\n\n        @param deferredDisplayList  drawing commands\n        @return                     false if deferredDisplayList is not compatible\n    */\n    bool draw(SkDeferredDisplayList* deferredDisplayList);\n\nprotected:\n    SkSurface(int width, int height, const SkSurfaceProps* surfaceProps);\n    SkSurface(const SkImageInfo& imageInfo, const SkSurfaceProps* surfaceProps);\n\n    // called by subclass if their contents have changed\n    void dirtyGenerationID() {\n        fGenerationID = 0;\n    }\n\nprivate:\n    const SkSurfaceProps fProps;\n    const int            fWidth;\n    const int            fHeight;\n    uint32_t             fGenerationID;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkSurfaceCharacterization.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSurfaceCharacterization_DEFINED\n#define SkSurfaceCharacterization_DEFINED\n\n#include \"GrTypes.h\"\n\n#include \"SkColorSpace.h\"\n#include \"SkRefCnt.h\"\n#include \"SkSurfaceProps.h\"\n\nclass SkColorSpace;\n\n#if SK_SUPPORT_GPU\n#include \"GrContext.h\"\n\n/** \\class SkSurfaceCharacterization\n    A surface characterization contains all the information Ganesh requires to makes its internal\n    rendering decisions. When passed into a SkDeferredDisplayListRecorder it will copy the\n    data and pass it on to the SkDeferredDisplayList if/when it is created. Note that both of\n    those objects (the Recorder and the DisplayList) will take a ref on the\n    GrContextThreadSafeProxy and SkColorSpace objects.\n*/\nclass SK_API SkSurfaceCharacterization {\npublic:\n    enum class Textureable : bool { kNo = false, kYes = true };\n    enum class MipMapped : bool { kNo = false, kYes = true };\n    enum class UsesGLFBO0 : bool { kNo = false, kYes = true };\n\n    SkSurfaceCharacterization()\n            : fCacheMaxResourceBytes(0)\n            , fOrigin(kBottomLeft_GrSurfaceOrigin)\n            , fConfig(kUnknown_GrPixelConfig)\n            , fFSAAType(GrFSAAType::kNone)\n            , fStencilCnt(0)\n            , fIsTextureable(Textureable::kYes)\n            , fIsMipMapped(MipMapped::kYes)\n            , fUsesGLFBO0(UsesGLFBO0::kNo)\n            , fSurfaceProps(0, kUnknown_SkPixelGeometry) {\n    }\n\n    SkSurfaceCharacterization(SkSurfaceCharacterization&&) = default;\n    SkSurfaceCharacterization& operator=(SkSurfaceCharacterization&&) = default;\n\n    SkSurfaceCharacterization(const SkSurfaceCharacterization&) = default;\n    SkSurfaceCharacterization& operator=(const SkSurfaceCharacterization& other) = default;\n    bool operator==(const SkSurfaceCharacterization& other) const;\n    bool operator!=(const SkSurfaceCharacterization& other) const {\n        return !(*this == other);\n    }\n\n    SkSurfaceCharacterization createResized(int width, int height) const;\n\n    GrContextThreadSafeProxy* contextInfo() const { return fContextInfo.get(); }\n    sk_sp<GrContextThreadSafeProxy> refContextInfo() const { return fContextInfo; }\n    size_t cacheMaxResourceBytes() const { return fCacheMaxResourceBytes; }\n\n    bool isValid() const { return kUnknown_SkColorType != fImageInfo.colorType(); }\n\n    const SkImageInfo& imageInfo() const { return fImageInfo; }\n    GrSurfaceOrigin origin() const { return fOrigin; }\n    int width() const { return fImageInfo.width(); }\n    int height() const { return fImageInfo.height(); }\n    SkColorType colorType() const { return fImageInfo.colorType(); }\n    GrFSAAType fsaaType() const { return fFSAAType; }\n    int stencilCount() const { return fStencilCnt; }\n    bool isTextureable() const { return Textureable::kYes == fIsTextureable; }\n    bool isMipMapped() const { return MipMapped::kYes == fIsMipMapped; }\n    bool usesGLFBO0() const { return UsesGLFBO0::kYes == fUsesGLFBO0; }\n    SkColorSpace* colorSpace() const { return fImageInfo.colorSpace(); }\n    sk_sp<SkColorSpace> refColorSpace() const { return fImageInfo.refColorSpace(); }\n    const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }\n\nprivate:\n    friend class SkSurface_Gpu; // for 'set' & 'config'\n    friend class GrContextThreadSafeProxy; // for private ctor\n    friend class SkDeferredDisplayListRecorder; // for 'config'\n    friend class SkSurface; // for 'config'\n\n    GrPixelConfig config() const { return fConfig; }\n\n    SkSurfaceCharacterization(sk_sp<GrContextThreadSafeProxy> contextInfo,\n                              size_t cacheMaxResourceBytes,\n                              const SkImageInfo& ii,\n                              GrSurfaceOrigin origin,\n                              GrPixelConfig config,\n                              GrFSAAType FSAAType, int stencilCnt,\n                              Textureable isTextureable, MipMapped isMipMapped,\n                              UsesGLFBO0 usesGLFBO0,\n                              const SkSurfaceProps& surfaceProps)\n            : fContextInfo(std::move(contextInfo))\n            , fCacheMaxResourceBytes(cacheMaxResourceBytes)\n            , fImageInfo(ii)\n            , fOrigin(origin)\n            , fConfig(config)\n            , fFSAAType(FSAAType)\n            , fStencilCnt(stencilCnt)\n            , fIsTextureable(isTextureable)\n            , fIsMipMapped(isMipMapped)\n            , fUsesGLFBO0(usesGLFBO0)\n            , fSurfaceProps(surfaceProps) {\n    }\n\n    void set(sk_sp<GrContextThreadSafeProxy> contextInfo,\n             size_t cacheMaxResourceBytes,\n             const SkImageInfo& ii,\n             GrSurfaceOrigin origin,\n             GrPixelConfig config,\n             GrFSAAType fsaaType,\n             int stencilCnt,\n             Textureable isTextureable,\n             MipMapped isMipMapped,\n             UsesGLFBO0 usesGLFBO0,\n             const SkSurfaceProps& surfaceProps) {\n        SkASSERT(MipMapped::kNo == isMipMapped || Textureable::kYes == isTextureable);\n        SkASSERT(Textureable::kNo == isTextureable || UsesGLFBO0::kNo == usesGLFBO0);\n\n        fContextInfo = contextInfo;\n        fCacheMaxResourceBytes = cacheMaxResourceBytes;\n\n        fImageInfo = ii;\n        fOrigin = origin;\n        fConfig = config;\n        fFSAAType = fsaaType;\n        fStencilCnt = stencilCnt;\n        fIsTextureable = isTextureable;\n        fIsMipMapped = isMipMapped;\n        fUsesGLFBO0 = usesGLFBO0;\n        fSurfaceProps = surfaceProps;\n    }\n\n    sk_sp<GrContextThreadSafeProxy> fContextInfo;\n    size_t                          fCacheMaxResourceBytes;\n\n    SkImageInfo                     fImageInfo;\n    GrSurfaceOrigin                 fOrigin;\n    GrPixelConfig                   fConfig;\n    GrFSAAType                      fFSAAType;\n    int                             fStencilCnt;\n    Textureable                     fIsTextureable;\n    MipMapped                       fIsMipMapped;\n    UsesGLFBO0                      fUsesGLFBO0;\n    SkSurfaceProps                  fSurfaceProps;\n};\n\n#else// !SK_SUPPORT_GPU\n\nclass SK_API SkSurfaceCharacterization {\npublic:\n    SkSurfaceCharacterization() : fSurfaceProps(0, kUnknown_SkPixelGeometry) { }\n\n    SkSurfaceCharacterization createResized(int width, int height) const {\n        return *this;\n    }\n\n    bool operator==(const SkSurfaceCharacterization& other) const { return false; }\n    bool operator!=(const SkSurfaceCharacterization& other) const {\n        return !(*this == other);\n    }\n\n    size_t cacheMaxResourceBytes() const { return 0; }\n\n    bool isValid() const { return false; }\n\n    int width() const { return 0; }\n    int height() const { return 0; }\n    int stencilCount() const { return 0; }\n    bool isTextureable() const { return false; }\n    bool isMipMapped() const { return false; }\n    bool usesGLFBO0() const { return false; }\n    SkColorSpace* colorSpace() const { return nullptr; }\n    sk_sp<SkColorSpace> refColorSpace() const { return nullptr; }\n    const SkSurfaceProps& surfaceProps()const { return fSurfaceProps; }\n\nprivate:\n    SkSurfaceProps fSurfaceProps;\n};\n\n#endif\n\n#endif\n"
  },
  {
    "path": "include/core/SkSurfaceProps.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSurfaceProps_DEFINED\n#define SkSurfaceProps_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n *  Description of how the LCD strips are arranged for each pixel. If this is unknown, or the\n *  pixels are meant to be \"portable\" and/or transformed before showing (e.g. rotated, scaled)\n *  then use kUnknown_SkPixelGeometry.\n */\nenum SkPixelGeometry {\n    kUnknown_SkPixelGeometry,\n    kRGB_H_SkPixelGeometry,\n    kBGR_H_SkPixelGeometry,\n    kRGB_V_SkPixelGeometry,\n    kBGR_V_SkPixelGeometry,\n};\n\n// Returns true iff geo is a known geometry and is RGB.\nstatic inline bool SkPixelGeometryIsRGB(SkPixelGeometry geo) {\n    return kRGB_H_SkPixelGeometry == geo || kRGB_V_SkPixelGeometry == geo;\n}\n\n// Returns true iff geo is a known geometry and is BGR.\nstatic inline bool SkPixelGeometryIsBGR(SkPixelGeometry geo) {\n    return kBGR_H_SkPixelGeometry == geo || kBGR_V_SkPixelGeometry == geo;\n}\n\n// Returns true iff geo is a known geometry and is horizontal.\nstatic inline bool SkPixelGeometryIsH(SkPixelGeometry geo) {\n    return kRGB_H_SkPixelGeometry == geo || kBGR_H_SkPixelGeometry == geo;\n}\n\n// Returns true iff geo is a known geometry and is vertical.\nstatic inline bool SkPixelGeometryIsV(SkPixelGeometry geo) {\n    return kRGB_V_SkPixelGeometry == geo || kBGR_V_SkPixelGeometry == geo;\n}\n\n/**\n *  Describes properties and constraints of a given SkSurface. The rendering engine can parse these\n *  during drawing, and can sometimes optimize its performance (e.g. disabling an expensive\n *  feature).\n */\nclass SK_API SkSurfaceProps {\npublic:\n    enum Flags {\n        kUseDeviceIndependentFonts_Flag = 1 << 0,\n    };\n    /** Deprecated alias used by Chromium. Will be removed. */\n    static const Flags kUseDistanceFieldFonts_Flag = kUseDeviceIndependentFonts_Flag;\n\n    SkSurfaceProps(uint32_t flags, SkPixelGeometry);\n\n    enum InitType {\n        kLegacyFontHost_InitType\n    };\n    SkSurfaceProps(InitType);\n    SkSurfaceProps(uint32_t flags, InitType);\n    SkSurfaceProps(const SkSurfaceProps& other);\n\n    uint32_t flags() const { return fFlags; }\n    SkPixelGeometry pixelGeometry() const { return fPixelGeometry; }\n\n    bool isUseDeviceIndependentFonts() const {\n        return SkToBool(fFlags & kUseDeviceIndependentFonts_Flag);\n    }\n\n    bool operator==(const SkSurfaceProps& that) const {\n        return fFlags == that.fFlags && fPixelGeometry == that.fPixelGeometry;\n    }\n\nprivate:\n    SkSurfaceProps();\n\n    uint32_t        fFlags;\n    SkPixelGeometry fPixelGeometry;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkSwizzle.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSwizzle_DEFINED\n#define SkSwizzle_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n  Swizzles byte order of |count| 32-bit pixels, swapping R and B.\n  (RGBA <-> BGRA)\n*/\nSK_API void SkSwapRB(uint32_t* dest, const uint32_t* src, int count);\n\n#endif\n"
  },
  {
    "path": "include/core/SkTLazy.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTLazy_DEFINED\n#define SkTLazy_DEFINED\n\n#include \"../private/SkTemplates.h\"\n#include \"SkTypes.h\"\n#include <new>\n#include <utility>\n\n/**\n *  Efficient way to defer allocating/initializing a class until it is needed\n *  (if ever).\n */\ntemplate <typename T> class SkTLazy {\npublic:\n    SkTLazy() : fPtr(nullptr) {}\n\n    explicit SkTLazy(const T* src)\n        : fPtr(src ? new (fStorage.get()) T(*src) : nullptr) {}\n\n    SkTLazy(const SkTLazy& that) : fPtr(nullptr) { *this = that; }\n    SkTLazy(SkTLazy&& that) : fPtr(nullptr) { *this = std::move(that); }\n\n    ~SkTLazy() {\n        if (this->isValid()) {\n            fPtr->~T();\n        }\n    }\n\n    SkTLazy& operator=(const SkTLazy& that) {\n        if (that.isValid()) {\n            this->set(*that.get());\n        } else {\n            this->reset();\n        }\n        return *this;\n    }\n\n    SkTLazy& operator=(SkTLazy&& that) {\n        if (that.isValid()) {\n            this->set(std::move(*that.get()));\n        } else {\n            this->reset();\n        }\n        return *this;\n    }\n\n    /**\n     *  Return a pointer to an instance of the class initialized with 'args'.\n     *  If a previous instance had been initialized (either from init() or\n     *  set()) it will first be destroyed, so that a freshly initialized\n     *  instance is always returned.\n     */\n    template <typename... Args> T* init(Args&&... args) {\n        if (this->isValid()) {\n            fPtr->~T();\n        }\n        fPtr = new (SkTCast<T*>(fStorage.get())) T(std::forward<Args>(args)...);\n        return fPtr;\n    }\n\n    /**\n     *  Copy src into this, and return a pointer to a copy of it. Note this\n     *  will always return the same pointer, so if it is called on a lazy that\n     *  has already been initialized, then this will copy over the previous\n     *  contents.\n     */\n    T* set(const T& src) {\n        if (this->isValid()) {\n            *fPtr = src;\n        } else {\n            fPtr = new (SkTCast<T*>(fStorage.get())) T(src);\n        }\n        return fPtr;\n    }\n\n    T* set(T&& src) {\n        if (this->isValid()) {\n            *fPtr = std::move(src);\n        } else {\n            fPtr = new (SkTCast<T*>(fStorage.get())) T(std::move(src));\n        }\n        return fPtr;\n    }\n\n    /**\n     * Destroy the lazy object (if it was created via init() or set())\n     */\n    void reset() {\n        if (this->isValid()) {\n            fPtr->~T();\n            fPtr = nullptr;\n        }\n    }\n\n    /**\n     *  Returns true if a valid object has been initialized in the SkTLazy,\n     *  false otherwise.\n     */\n    bool isValid() const { return SkToBool(fPtr); }\n\n    /**\n     * Returns the object. This version should only be called when the caller\n     * knows that the object has been initialized.\n     */\n    T* get() const { SkASSERT(this->isValid()); return fPtr; }\n\n    /**\n     * Like above but doesn't assert if object isn't initialized (in which case\n     * nullptr is returned).\n     */\n    T* getMaybeNull() const { return fPtr; }\n\nprivate:\n    SkAlignedSTStorage<1, T> fStorage;\n    T*                       fPtr; // nullptr or fStorage\n};\n\n/**\n * A helper built on top of SkTLazy to do copy-on-first-write. The object is initialized\n * with a const pointer but provides a non-const pointer accessor. The first time the\n * accessor is called (if ever) the object is cloned.\n *\n * In the following example at most one copy of constThing is made:\n *\n * SkTCopyOnFirstWrite<Thing> thing(&constThing);\n * ...\n * function_that_takes_a_const_thing_ptr(thing); // constThing is passed\n * ...\n * if (need_to_modify_thing()) {\n *    thing.writable()->modifyMe(); // makes a copy of constThing\n * }\n * ...\n * x = thing->readSomething();\n * ...\n * if (need_to_modify_thing_now()) {\n *    thing.writable()->changeMe(); // makes a copy of constThing if we didn't call modifyMe()\n * }\n *\n * consume_a_thing(thing); // could be constThing or a modified copy.\n */\ntemplate <typename T>\nclass SkTCopyOnFirstWrite {\npublic:\n    explicit SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {}\n\n    explicit SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {}\n\n    // Constructor for delayed initialization.\n    SkTCopyOnFirstWrite() : fObj(nullptr) {}\n\n    SkTCopyOnFirstWrite(const SkTCopyOnFirstWrite&  that) { *this = that;            }\n    SkTCopyOnFirstWrite(      SkTCopyOnFirstWrite&& that) { *this = std::move(that); }\n\n    SkTCopyOnFirstWrite& operator=(const SkTCopyOnFirstWrite& that) {\n        fLazy = that.fLazy;\n        fObj  = fLazy.isValid() ? fLazy.get() : that.fObj;\n        return *this;\n    }\n\n    SkTCopyOnFirstWrite& operator=(SkTCopyOnFirstWrite&& that) {\n        fLazy = std::move(that.fLazy);\n        fObj  = fLazy.isValid() ? fLazy.get() : that.fObj;\n        return *this;\n    }\n\n    // Should only be called once, and only if the default constructor was used.\n    void init(const T& initial) {\n        SkASSERT(nullptr == fObj);\n        SkASSERT(!fLazy.isValid());\n        fObj = &initial;\n    }\n\n    /**\n     * Returns a writable T*. The first time this is called the initial object is cloned.\n     */\n    T* writable() {\n        SkASSERT(fObj);\n        if (!fLazy.isValid()) {\n            fLazy.set(*fObj);\n            fObj = fLazy.get();\n        }\n        return const_cast<T*>(fObj);\n    }\n\n    const T* get() const { return fObj; }\n\n    /**\n     * Operators for treating this as though it were a const pointer.\n     */\n\n    const T *operator->() const { return fObj; }\n\n    operator const T*() const { return fObj; }\n\n    const T& operator *() const { return *fObj; }\n\nprivate:\n    const T*    fObj;\n    SkTLazy<T>  fLazy;\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkTextBlob.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTextBlob_DEFINED\n#define SkTextBlob_DEFINED\n\n#include \"../private/SkTemplates.h\"\n#include \"../private/SkAtomics.h\"\n#include \"SkPaint.h\"\n#include \"SkString.h\"\n#include \"SkRefCnt.h\"\n\nclass SkReadBuffer;\nclass SkWriteBuffer;\n\nstruct SkSerialProcs;\nstruct SkDeserialProcs;\n\ntypedef void (*SkTypefaceCatalogerProc)(SkTypeface*, void* ctx);\ntypedef sk_sp<SkTypeface> (*SkTypefaceResolverProc)(uint32_t id, void* ctx);\n\n/** \\class SkTextBlob\n\n    SkTextBlob combines multiple text runs into an immutable, ref-counted structure.\n*/\nclass SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> {\npublic:\n    /**\n     *  Returns a conservative blob bounding box.\n     */\n    const SkRect& bounds() const { return fBounds; }\n\n    /**\n     *  Return a non-zero, unique value representing the text blob.\n     */\n    uint32_t uniqueID() const { return fUniqueID; }\n\n    /**\n     *  Serialize to a buffer.\n     */\n    void flatten(SkWriteBuffer&) const;\n\n    /**\n     *  Recreate an SkTextBlob that was serialized into a buffer.\n     *\n     *  @param  SkReadBuffer Serialized blob data.\n     *  @return A new SkTextBlob representing the serialized data, or NULL if the buffer is\n     *          invalid.\n     */\n    static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);\n\n    enum GlyphPositioning : uint8_t {\n        kDefault_Positioning      = 0, // Default glyph advances -- zero scalars per glyph.\n        kHorizontal_Positioning   = 1, // Horizontal positioning -- one scalar per glyph.\n        kFull_Positioning         = 2  // Point positioning -- two scalars per glyph.\n    };\n\n    /**\n     *  Serialize the typeface into a data blob, storing type uniqueID of each referenced typeface.\n     *  During this process, each time a typeface is encountered, it is passed to the catalog,\n     *  allowing the caller to what typeface IDs will need to be resolved in Deserialize().\n     */\n    sk_sp<SkData> serialize(SkTypefaceCatalogerProc, void* ctx) const;\n\n    /**\n     *  Similar to serialize above, but writes directly into |memory|. Returns bytes written or 0u\n     *  if serialization failed due to insufficient size.\n     */\n    size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const;\n\n    /**\n     *  Re-create a text blob previously serialized. Since the serialized form records the uniqueIDs\n     *  of its typefaces, deserialization requires that the caller provide the corresponding\n     *  SkTypefaces for those IDs.\n     */\n    static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size,\n                                         SkTypefaceResolverProc, void* ctx);\n\n    sk_sp<SkData> serialize(const SkSerialProcs&) const;\n    sk_sp<SkData> serialize() const;\n    static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, const SkDeserialProcs&);\n    static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size);\n\nprivate:\n    friend class SkNVRefCnt<SkTextBlob>;\n    class RunRecord;\n\n    explicit SkTextBlob(const SkRect& bounds);\n\n    ~SkTextBlob();\n\n    // Memory for objects of this class is created with sk_malloc rather than operator new and must\n    // be freed with sk_free.\n    void operator delete(void* p) { sk_free(p); }\n    void* operator new(size_t) {\n        SK_ABORT(\"All blobs are created by placement new.\");\n        return sk_malloc_throw(0);\n    }\n    void* operator new(size_t, void* p) { return p; }\n\n    static unsigned ScalarsPerGlyph(GlyphPositioning pos);\n\n    // Call when this blob is part of the key to a cache entry. This allows the cache\n    // to know automatically those entries can be purged when this SkTextBlob is deleted.\n    void notifyAddedToCache(uint32_t cacheID) const {\n        fCacheID.store(cacheID);\n    }\n\n    friend class GrTextBlobCache;\n    friend class SkTextBlobBuilder;\n    friend class SkTextBlobRunIterator;\n\n    const SkRect               fBounds;\n    const uint32_t             fUniqueID;\n    mutable SkAtomic<uint32_t> fCacheID;\n\n    SkDEBUGCODE(size_t fStorageSize;)\n\n    // The actual payload resides in externally-managed storage, following the object.\n    // (see the .cpp for more details)\n\n    typedef SkRefCnt INHERITED;\n};\n\n/** \\class SkTextBlobBuilder\n\n    Helper class for constructing SkTextBlobs.\n */\nclass SK_API SkTextBlobBuilder {\npublic:\n    SkTextBlobBuilder();\n\n    ~SkTextBlobBuilder();\n\n    /**\n     *  Returns an immutable SkTextBlob for the current runs/glyphs,\n     *  or nullptr if no runs were allocated.\n     *\n     *  The builder is reset and can be reused.\n     */\n    sk_sp<SkTextBlob> make();\n\n    /**\n     *  Glyph and position buffers associated with a run.\n     *\n     *  A run is a sequence of glyphs sharing the same font metrics\n     *  and positioning mode.\n     *\n     *  If textByteCount is 0, utf8text and clusters will be NULL (no\n     *  character information will be associated with the glyphs).\n     *\n     *  utf8text will point to a buffer of size textByteCount bytes.\n     *\n     *  clusters (if not NULL) will point to an array of size count.\n     *  For each glyph, give the byte-offset into the text for the\n     *  first byte in the first character in that glyph's cluster.\n     *  Each value in the array should be an integer less than\n     *  textByteCount.  Values in the array should either be\n     *  monotonically increasing (left-to-right text) or monotonically\n     *  decreasing (right-to-left text).  This definiton is conviently\n     *  the same as used by Harfbuzz's hb_glyph_info_t::cluster field,\n     *  except that Harfbuzz interleaves glyphs and clusters.\n     */\n    struct RunBuffer {\n        SkGlyphID* glyphs;\n        SkScalar* pos;\n        char* utf8text;\n        uint32_t* clusters;\n    };\n\n    /**\n     *  Allocates a new default-positioned run and returns its writable glyph buffer\n     *  for direct manipulation.\n     *\n     *  @param font    The font to be used for this run.\n     *  @param count   Number of glyphs.\n     *  @param x,y     Position within the blob.\n     *  @param textByteCount length of the original UTF-8 text that\n     *                 corresponds to this sequence of glyphs.  If 0,\n     *                 text will not be included in the textblob.\n     *  @param lang    Language code, currently unimplemented.\n     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will\n     *                 be used when computing the blob bounds, to avoid re-measuring.\n     *\n     *  @return        A writable glyph buffer, valid until the next allocRun() or\n     *                 build() call. The buffer is guaranteed to hold @count@ glyphs.\n     */\n    const RunBuffer& allocRunText(const SkPaint& font,\n                                  int count,\n                                  SkScalar x,\n                                  SkScalar y,\n                                  int textByteCount,\n                                  SkString lang,\n                                  const SkRect* bounds = nullptr);\n    const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y,\n                              const SkRect* bounds = nullptr) {\n        return this->allocRunText(font, count, x, y, 0, SkString(), bounds);\n    }\n\n    /**\n     *  Allocates a new horizontally-positioned run and returns its writable glyph and position\n     *  buffers for direct manipulation.\n     *\n     *  @param font    The font to be used for this run.\n     *  @param count   Number of glyphs.\n     *  @param y       Vertical offset within the blob.\n     *  @param textByteCount length of the original UTF-8 text that\n     *                 corresponds to this sequence of glyphs.  If 0,\n     *                 text will not be included in the textblob.\n     *  @param lang    Language code, currently unimplemented.\n     *  @param bounds  Optional run bounding box. If known in advance (!= NULL), it will\n     *                 be used when computing the blob bounds, to avoid re-measuring.\n     *\n     *  @return        Writable glyph and position buffers, valid until the next allocRun()\n     *                 or build() call. The buffers are guaranteed to hold @count@ elements.\n     */\n    const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y,\n                                      int textByteCount, SkString lang,\n                                      const SkRect* bounds = nullptr);\n    const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y,\n                                  const SkRect* bounds = nullptr) {\n        return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds);\n    }\n\n    /**\n     *  Allocates a new fully-positioned run and returns its writable glyph and position\n     *  buffers for direct manipulation.\n     *\n     *  @param font   The font to be used for this run.\n     *  @param count  Number of glyphs.\n     *  @param textByteCount length of the original UTF-8 text that\n     *                 corresponds to this sequence of glyphs.  If 0,\n     *                 text will not be included in the textblob.\n     *  @param lang    Language code, currently unimplemented.\n     *  @param bounds Optional run bounding box. If known in advance (!= NULL), it will\n     *                be used when computing the blob bounds, to avoid re-measuring.\n     *\n     *  @return       Writable glyph and position buffers, valid until the next allocRun()\n     *                or build() call. The glyph buffer and position buffer are\n     *                guaranteed to hold @count@ and 2 * @count@ elements, respectively.\n     */\n    const RunBuffer& allocRunTextPos(const SkPaint& font, int count,\n                                     int textByteCount, SkString lang,\n                                     const SkRect* bounds = nullptr);\n    const RunBuffer& allocRunPos(const SkPaint& font, int count,\n                                 const SkRect* bounds = nullptr) {\n        return this->allocRunTextPos(font, count, 0, SkString(), bounds);\n    }\n\nprivate:\n    void reserve(size_t size);\n    void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,\n                       int count, int textBytes, SkPoint offset, const SkRect* bounds);\n    bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning,\n                  uint32_t count, SkPoint offset);\n    void updateDeferredBounds();\n\n    static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&);\n    static SkRect TightRunBounds(const SkTextBlob::RunRecord&);\n\n    SkAutoTMalloc<uint8_t> fStorage;\n    size_t                 fStorageSize;\n    size_t                 fStorageUsed;\n\n    SkRect                 fBounds;\n    int                    fRunCount;\n    bool                   fDeferredBounds;\n    size_t                 fLastRun; // index into fStorage\n\n    RunBuffer              fCurrentRunBuffer;\n};\n\n#endif // SkTextBlob_DEFINED\n"
  },
  {
    "path": "include/core/SkTime.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkTime_DEFINED\n#define SkTime_DEFINED\n\n#include \"SkTypes.h\"\n\nclass SkString;\n\n/** \\class SkTime\n    Platform-implemented utilities to return time of day, and millisecond counter.\n*/\nclass SK_API SkTime {\npublic:\n    struct DateTime {\n        int16_t  fTimeZoneMinutes;  // The number of minutes that GetDateTime()\n                                    // is ahead of or behind UTC.\n        uint16_t fYear;          //!< e.g. 2005\n        uint8_t  fMonth;         //!< 1..12\n        uint8_t  fDayOfWeek;     //!< 0..6, 0==Sunday\n        uint8_t  fDay;           //!< 1..31\n        uint8_t  fHour;          //!< 0..23\n        uint8_t  fMinute;        //!< 0..59\n        uint8_t  fSecond;        //!< 0..59\n\n        void toISO8601(SkString* dst) const;\n    };\n    static void GetDateTime(DateTime*);\n\n    static double GetSecs() { return GetNSecs() * 1e-9; }\n    static double GetMSecs() { return GetNSecs() * 1e-6; }\n    static double GetNSecs();\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\nclass SkAutoTime {\npublic:\n    // The label is not deep-copied, so its address must remain valid for the\n    // lifetime of this object\n    SkAutoTime(const char* label = nullptr)\n        : fLabel(label)\n        , fNow(SkTime::GetMSecs()) {}\n    ~SkAutoTime() {\n        uint64_t dur = static_cast<uint64_t>(SkTime::GetMSecs() - fNow);\n        SkDebugf(\"%s %ld\\n\", fLabel ? fLabel : \"\", dur);\n    }\nprivate:\n    const char* fLabel;\n    double      fNow;\n};\n#define SkAutoTime(...) SK_REQUIRE_LOCAL_VAR(SkAutoTime)\n\n#endif\n"
  },
  {
    "path": "include/core/SkTraceMemoryDump.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTraceMemoryDump_DEFINED\n#define SkTraceMemoryDump_DEFINED\n\n#include \"SkTypes.h\"\n\nclass SkDiscardableMemory;\n\n/**\n * Interface for memory tracing.\n * This interface is meant to be passed as argument to the memory dump methods of Skia objects.\n * The implementation of this interface is provided by the embedder.\n */\nclass SK_API SkTraceMemoryDump {\npublic:\n    /**\n     * Enum to specify the level of the requested details for the dump from the Skia objects.\n     */\n    enum LevelOfDetail {\n        // Dump only the minimal details to get the total memory usage (Usually just the totals).\n        kLight_LevelOfDetail,\n\n        // Dump the detailed breakdown of the objects in the caches.\n        kObjectsBreakdowns_LevelOfDetail\n    };\n\n    /**\n     *  Appends a new memory dump (i.e. a row) to the trace memory infrastructure.\n     *  If dumpName does not exist yet, a new one is created. Otherwise, a new column is appended to\n     *  the previously created dump.\n     *  Arguments:\n     *    dumpName: an absolute, slash-separated, name for the item being dumped\n     *        e.g., \"skia/CacheX/EntryY\".\n     *    valueName: a string indicating the name of the column.\n     *        e.g., \"size\", \"active_size\", \"number_of_objects\".\n     *        This string is supposed to be long lived and is NOT copied.\n     *    units: a string indicating the units for the value.\n     *        e.g., \"bytes\", \"objects\".\n     *        This string is supposed to be long lived and is NOT copied.\n     *    value: the actual value being dumped.\n     */\n    virtual void dumpNumericValue(const char* dumpName,\n                                  const char* valueName,\n                                  const char* units,\n                                  uint64_t value) = 0;\n\n    virtual void dumpStringValue(const char* /*dumpName*/,\n                                 const char* /*valueName*/,\n                                 const char* /*value*/) { }\n\n    /**\n     * Sets the memory backing for an existing dump.\n     * backingType and backingObjectId are used by the embedder to associate the memory dumped via\n     * dumpNumericValue with the corresponding dump that backs the memory.\n     */\n    virtual void setMemoryBacking(const char* dumpName,\n                                  const char* backingType,\n                                  const char* backingObjectId) = 0;\n\n    /**\n     * Specialization for memory backed by discardable memory.\n     */\n    virtual void setDiscardableMemoryBacking(\n        const char* dumpName,\n        const SkDiscardableMemory& discardableMemoryObject) = 0;\n\n    /**\n     * Returns the type of details requested in the dump. The granularity of the dump is supposed to\n     * match the LevelOfDetail argument. The level of detail must not affect the total size\n     * reported, but only granularity of the child entries.\n     */\n    virtual LevelOfDetail getRequestedDetails() const = 0;\n\n    /**\n     * Returns true if we should dump wrapped objects. Wrapped objects come from outside Skia, and\n     * may be independently tracked there.\n     */\n    virtual bool shouldDumpWrappedObjects() const { return true; }\n\nprotected:\n    virtual ~SkTraceMemoryDump() { }\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkTypeface.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTypeface_DEFINED\n#define SkTypeface_DEFINED\n\n#include \"../private/SkOnce.h\"\n#include \"../private/SkWeakRefCnt.h\"\n#include \"SkFontArguments.h\"\n#include \"SkFontStyle.h\"\n#include \"SkRect.h\"\n#include \"SkString.h\"\n\nclass SkDescriptor;\nclass SkFontData;\nclass SkFontDescriptor;\nclass SkScalerContext;\nclass SkStream;\nclass SkStreamAsset;\nclass SkWStream;\nstruct SkAdvancedTypefaceMetrics;\nstruct SkScalerContextEffects;\nstruct SkScalerContextRec;\n\ntypedef uint32_t SkFontID;\n/** Machine endian. */\ntypedef uint32_t SkFontTableTag;\n\n/** \\class SkTypeface\n\n    The SkTypeface class specifies the typeface and intrinsic style of a font.\n    This is used in the paint, along with optionally algorithmic settings like\n    textSize, textSkewX, textScaleX, kFakeBoldText_Mask, to specify\n    how text appears when drawn (and measured).\n\n    Typeface objects are immutable, and so they can be shared between threads.\n*/\nclass SK_API SkTypeface : public SkWeakRefCnt {\npublic:\n    /** Returns the typeface's intrinsic style attributes. */\n    SkFontStyle fontStyle() const {\n        return fStyle;\n    }\n\n    /** Returns true if style() has the kBold bit set. */\n    bool isBold() const { return fStyle.weight() >= SkFontStyle::kSemiBold_Weight; }\n\n    /** Returns true if style() has the kItalic bit set. */\n    bool isItalic() const { return fStyle.slant() != SkFontStyle::kUpright_Slant; }\n\n    /** Returns true if the typeface claims to be fixed-pitch.\n     *  This is a style bit, advance widths may vary even if this returns true.\n     */\n    bool isFixedPitch() const { return fIsFixedPitch; }\n\n    /** Copy into 'coordinates' (allocated by the caller) the design variation coordinates.\n     *\n     *  @param coordinates the buffer into which to write the design variation coordinates.\n     *  @param coordinateCount the number of entries available through 'coordinates'.\n     *\n     *  @return The number of axes, or -1 if there is an error.\n     *  If 'coordinates != nullptr' and 'coordinateCount >= numAxes' then 'coordinates' will be\n     *  filled with the variation coordinates describing the position of this typeface in design\n     *  variation space. It is possible the number of axes can be retrieved but actual position\n     *  cannot.\n     */\n    int getVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],\n                                   int coordinateCount) const;\n\n    /** Return a 32bit value for this typeface, unique for the underlying font\n        data. Will never return 0.\n     */\n    SkFontID uniqueID() const { return fUniqueID; }\n\n    /** Return the uniqueID for the specified typeface. If the face is null,\n        resolve it to the default font and return its uniqueID. Will never\n        return 0.\n    */\n    static SkFontID UniqueID(const SkTypeface* face);\n\n    /** Returns true if the two typefaces reference the same underlying font,\n        handling either being null (treating null as the default font)\n     */\n    static bool Equal(const SkTypeface* facea, const SkTypeface* faceb);\n\n    /** Returns the default normal typeface, which is never nullptr. */\n    static sk_sp<SkTypeface> MakeDefault();\n\n    /** Creates a new reference to the typeface that most closely matches the\n        requested familyName and fontStyle. This method allows extended font\n        face specifiers as in the SkFontStyle type. Will never return null.\n\n        @param familyName  May be NULL. The name of the font family.\n        @param fontStyle   The style of the typeface.\n        @return reference to the closest-matching typeface. Call must call\n              unref() when they are done.\n    */\n    static sk_sp<SkTypeface> MakeFromName(const char familyName[], SkFontStyle fontStyle);\n\n    /** Return a new typeface given a file. If the file does not exist, or is\n        not a valid font file, returns nullptr.\n    */\n    static sk_sp<SkTypeface> MakeFromFile(const char path[], int index = 0);\n\n    /** Return a new typeface given a stream. If the stream is\n        not a valid font file, returns nullptr. Ownership of the stream is\n        transferred, so the caller must not reference it again.\n    */\n    static sk_sp<SkTypeface> MakeFromStream(SkStreamAsset* stream, int index = 0);\n\n    /** Return a new typeface given font data and configuration. If the data\n        is not valid font data, returns nullptr.\n    */\n    static sk_sp<SkTypeface> MakeFromFontData(std::unique_ptr<SkFontData>);\n\n    /** Write a unique signature to a stream, sufficient to reconstruct a\n        typeface referencing the same font when Deserialize is called.\n     */\n    void serialize(SkWStream*) const;\n\n    /** Given the data previously written by serialize(), return a new instance\n        of a typeface referring to the same font. If that font is not available,\n        return nullptr.\n        Does not affect ownership of SkStream.\n     */\n    static sk_sp<SkTypeface> MakeDeserialize(SkStream*);\n\n    enum Encoding {\n        kUTF8_Encoding,\n        kUTF16_Encoding,\n        kUTF32_Encoding\n    };\n\n    /**\n     *  Given an array of character codes, of the specified encoding,\n     *  optionally return their corresponding glyph IDs (if glyphs is not NULL).\n     *\n     *  @param chars pointer to the array of character codes\n     *  @param encoding how the characters are encoded\n     *  @param glyphs (optional) returns the corresponding glyph IDs for each\n     *          character code, up to glyphCount values. If a character code is\n     *          not found in the typeface, the corresponding glyph ID will be 0.\n     *  @param glyphCount number of code points in 'chars' to process. If glyphs\n     *          is not NULL, then it must point sufficient memory to write\n     *          glyphCount values into it.\n     *  @return the number of number of continuous non-zero glyph IDs computed\n     *          from the beginning of chars. This value is valid, even if the\n     *          glyphs parameter is NULL.\n     */\n    int charsToGlyphs(const void* chars, Encoding encoding, SkGlyphID glyphs[],\n                      int glyphCount) const;\n\n    /**\n     *  Return the number of glyphs in the typeface.\n     */\n    int countGlyphs() const;\n\n    // Table getters -- may fail if the underlying font format is not organized\n    // as 4-byte tables.\n\n    /** Return the number of tables in the font. */\n    int countTables() const;\n\n    /** Copy into tags[] (allocated by the caller) the list of table tags in\n     *  the font, and return the number. This will be the same as CountTables()\n     *  or 0 if an error occured. If tags == NULL, this only returns the count\n     *  (the same as calling countTables()).\n     */\n    int getTableTags(SkFontTableTag tags[]) const;\n\n    /** Given a table tag, return the size of its contents, or 0 if not present\n     */\n    size_t getTableSize(SkFontTableTag) const;\n\n    /** Copy the contents of a table into data (allocated by the caller). Note\n     *  that the contents of the table will be in their native endian order\n     *  (which for most truetype tables is big endian). If the table tag is\n     *  not found, or there is an error copying the data, then 0 is returned.\n     *  If this happens, it is possible that some or all of the memory pointed\n     *  to by data may have been written to, even though an error has occured.\n     *\n     *  @param fontID the font to copy the table from\n     *  @param tag  The table tag whose contents are to be copied\n     *  @param offset The offset in bytes into the table's contents where the\n     *  copy should start from.\n     *  @param length The number of bytes, starting at offset, of table data\n     *  to copy.\n     *  @param data storage address where the table contents are copied to\n     *  @return the number of bytes actually copied into data. If offset+length\n     *  exceeds the table's size, then only the bytes up to the table's\n     *  size are actually copied, and this is the value returned. If\n     *  offset > the table's size, or tag is not a valid table,\n     *  then 0 is returned.\n     */\n    size_t getTableData(SkFontTableTag tag, size_t offset, size_t length,\n                        void* data) const;\n\n    /**\n     *  Return the units-per-em value for this typeface, or zero if there is an\n     *  error.\n     */\n    int getUnitsPerEm() const;\n\n    /**\n     *  Given a run of glyphs, return the associated horizontal adjustments.\n     *  Adjustments are in \"design units\", which are integers relative to the\n     *  typeface's units per em (see getUnitsPerEm).\n     *\n     *  Some typefaces are known to never support kerning. Calling this method\n     *  with all zeros (e.g. getKerningPairAdustments(NULL, 0, NULL)) returns\n     *  a boolean indicating if the typeface might support kerning. If it\n     *  returns false, then it will always return false (no kerning) for all\n     *  possible glyph runs. If it returns true, then it *may* return true for\n     *  somne glyph runs.\n     *\n     *  If count is non-zero, then the glyphs parameter must point to at least\n     *  [count] valid glyph IDs, and the adjustments parameter must be\n     *  sized to at least [count - 1] entries. If the method returns true, then\n     *  [count-1] entries in the adjustments array will be set. If the method\n     *  returns false, then no kerning should be applied, and the adjustments\n     *  array will be in an undefined state (possibly some values may have been\n     *  written, but none of them should be interpreted as valid values).\n     */\n    bool getKerningPairAdjustments(const SkGlyphID glyphs[], int count,\n                                   int32_t adjustments[]) const;\n\n    struct LocalizedString {\n        SkString fString;\n        SkString fLanguage;\n    };\n    class LocalizedStrings : ::SkNoncopyable {\n    public:\n        virtual ~LocalizedStrings() { }\n        virtual bool next(LocalizedString* localizedString) = 0;\n        void unref() { delete this; }\n    };\n    /**\n     *  Returns an iterator which will attempt to enumerate all of the\n     *  family names specified by the font.\n     *  It is the caller's responsibility to unref() the returned pointer.\n     */\n    LocalizedStrings* createFamilyNameIterator() const;\n\n    /**\n     *  Return the family name for this typeface. It will always be returned\n     *  encoded as UTF8, but the language of the name is whatever the host\n     *  platform chooses.\n     */\n    void getFamilyName(SkString* name) const;\n\n    /**\n     *  Return a stream for the contents of the font data, or NULL on failure.\n     *  If ttcIndex is not null, it is set to the TrueTypeCollection index\n     *  of this typeface within the stream, or 0 if the stream is not a\n     *  collection.\n     *  The caller is responsible for deleting the stream.\n     */\n    SkStreamAsset* openStream(int* ttcIndex) const;\n\n    /**\n     *  Return the font data, or nullptr on failure.\n     */\n    std::unique_ptr<SkFontData> makeFontData() const;\n\n    /**\n     *  Return a scalercontext for the given descriptor. If this fails, then\n     *  if allowFailure is true, this returns NULL, else it returns a\n     *  dummy scalercontext that will not crash, but will draw nothing.\n     */\n    std::unique_ptr<SkScalerContext> createScalerContext(const SkScalerContextEffects&,\n                                                         const SkDescriptor*,\n                                                         bool allowFailure = false) const;\n\n    /**\n     *  Return a rectangle (scaled to 1-pt) that represents the union of the bounds of all\n     *  of the glyphs, but each one positioned at (0,). This may be conservatively large, and\n     *  will not take into account any hinting or other size-specific adjustments.\n     */\n    SkRect getBounds() const;\n\n    // PRIVATE / EXPERIMENTAL -- do not call\n    void filterRec(SkScalerContextRec* rec) const {\n        this->onFilterRec(rec);\n    }\n    // PRIVATE / EXPERIMENTAL -- do not call\n    void getFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {\n        this->onGetFontDescriptor(desc, isLocal);\n    }\n    // PRIVATE / EXPERIMENTAL -- do not call\n    void* internal_private_getCTFontRef() const {\n        return this->onGetCTFontRef();\n    }\n\nprotected:\n    /** uniqueID must be unique and non-zero\n    */\n    SkTypeface(const SkFontStyle& style, bool isFixedPitch = false);\n    virtual ~SkTypeface();\n\n    /** Sets the fixedPitch bit. If used, must be called in the constructor. */\n    void setIsFixedPitch(bool isFixedPitch) { fIsFixedPitch = isFixedPitch; }\n    /** Sets the font style. If used, must be called in the constructor. */\n    void setFontStyle(SkFontStyle style) { fStyle = style; }\n\n    virtual SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,\n                                                   const SkDescriptor*) const = 0;\n    virtual void onFilterRec(SkScalerContextRec*) const = 0;\n    friend class SkScalerContext;  // onFilterRec\n\n    //  Subclasses *must* override this method to work with the PDF backend.\n    virtual std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const;\n    // For type1 postscript fonts only, set the glyph names for each glyph.\n    // destination array is non-null, and points to an array of size this->countGlyphs().\n    // Backends that do not suport type1 fonts should not override.\n    virtual void getPostScriptGlyphNames(SkString*) const {}\n\n    // The mapping from glyph to Unicode; array indices are glyph ids.\n    // For each glyph, give the default Unicode value, if it exists.\n    // dstArray is non-null, and points to an array of size this->countGlyphs().\n    virtual void getGlyphToUnicodeMap(SkUnichar* dstArray) const;\n\n    virtual SkStreamAsset* onOpenStream(int* ttcIndex) const = 0;\n    // TODO: make pure virtual.\n    virtual std::unique_ptr<SkFontData> onMakeFontData() const;\n\n    virtual int onGetVariationDesignPosition(\n        SkFontArguments::VariationPosition::Coordinate coordinates[],\n        int coordinateCount) const = 0;\n\n    virtual void onGetFontDescriptor(SkFontDescriptor*, bool* isLocal) const = 0;\n\n    virtual int onCharsToGlyphs(const void* chars, Encoding, SkGlyphID glyphs[],\n                                int glyphCount) const = 0;\n    virtual int onCountGlyphs() const = 0;\n\n    virtual int onGetUPEM() const = 0;\n    virtual bool onGetKerningPairAdjustments(const SkGlyphID glyphs[], int count,\n                                             int32_t adjustments[]) const;\n\n    /** Returns the family name of the typeface as known by its font manager.\n     *  This name may or may not be produced by the family name iterator.\n     */\n    virtual void onGetFamilyName(SkString* familyName) const = 0;\n\n    /** Returns an iterator over the family names in the font. */\n    virtual LocalizedStrings* onCreateFamilyNameIterator() const = 0;\n\n    virtual int onGetTableTags(SkFontTableTag tags[]) const = 0;\n    virtual size_t onGetTableData(SkFontTableTag, size_t offset,\n                                  size_t length, void* data) const = 0;\n\n    virtual bool onComputeBounds(SkRect*) const;\n\n    virtual void* onGetCTFontRef() const { return nullptr; }\n\nprivate:\n    /** Retrieve detailed typeface metrics.  Used by the PDF backend.  */\n    std::unique_ptr<SkAdvancedTypefaceMetrics> getAdvancedMetrics() const;\n    friend class SkRandomTypeface; // getAdvancedMetrics\n    friend class SkPDFFont;        // getAdvancedMetrics\n\n    /** Style specifies the intrinsic style attributes of a given typeface */\n    enum Style {\n        kNormal = 0,\n        kBold   = 0x01,\n        kItalic = 0x02,\n\n        // helpers\n        kBoldItalic = 0x03\n    };\n    static SkFontStyle FromOldStyle(Style oldStyle);\n    static SkTypeface* GetDefaultTypeface(Style style = SkTypeface::kNormal);\n    friend class SkPaintPriv;      // GetDefaultTypeface\n\nprivate:\n    SkFontID            fUniqueID;\n    SkFontStyle         fStyle;\n    mutable SkRect      fBounds;\n    mutable SkOnce      fBoundsOnce;\n    bool                fIsFixedPitch;\n\n    typedef SkWeakRefCnt INHERITED;\n};\n#endif\n"
  },
  {
    "path": "include/core/SkTypes.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTypes_DEFINED\n#define SkTypes_DEFINED\n\n// IWYU pragma: begin_exports\n\n// In at least two known scenarios when using GCC with libc++:\n//  * GCC 4.8 targeting ARMv7 with NEON\n//  * GCC 4.9 targeting ARMv8 64 bit\n// we need to typedef float float32_t (or include <arm_neon.h> which does that)\n// before #including <memory>. This makes no sense.  I'm not very interested in\n// understanding why... these are old, bizarre platform configuration that we\n// should just let die.\n// See https://llvm.org/bugs/show_bug.cgi?id=25608 .\n#include <ciso646>  // Include something innocuous to define _LIBCPP_VERISON if it's libc++.\n#if defined(__GNUC__) && __GNUC__ == 4 \\\n && ((defined(__arm__) && (defined(__ARM_NEON__) || defined(__ARM_NEON))) || defined(__aarch64__)) \\\n && defined(_LIBCPP_VERSION)\n    typedef float float32_t;\n    #include <memory>\n#endif\n\n#include \"SkPreConfig.h\"\n#include \"SkUserConfig.h\"\n#include \"SkPostConfig.h\"\n#include <stddef.h>\n#include <stdint.h>\n// IWYU pragma: end_exports\n\n#include <string.h>\n\n/** \\file SkTypes.h\n*/\n\n/** See SkGraphics::GetVersion() to retrieve these at runtime\n */\n#define SKIA_VERSION_MAJOR  1\n#define SKIA_VERSION_MINOR  0\n#define SKIA_VERSION_PATCH  0\n\n\n/** Called internally if we hit an unrecoverable error.\n    The platform implementation must not return, but should either throw\n    an exception or otherwise exit.\n*/\nSK_API extern void sk_abort_no_print(void);\n\n#define SK_INIT_TO_AVOID_WARNING    = 0\n\n#ifndef SkDebugf\n    SK_API void SkDebugf(const char format[], ...);\n#endif\n\n// SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.\n//    uint32_t foo(int x) {\n//        SkASSERT(x > 4);\n//        return x - 4;\n//    }\n// and are also written to be compatible with constexpr functions:\n//    constexpr uint32_t foo(int x) {\n//        return SkASSERT(x > 4),\n//               x - 4;\n//    }\n#define SkASSERT_RELEASE(cond) \\\n        static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT(\"assert(\" #cond \")\"); }() )\n\n#ifdef SK_DEBUG\n    #define SkASSERT(cond) SkASSERT_RELEASE(cond)\n    #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \\\n                                          SkDebugf(fmt\"\\n\", __VA_ARGS__);        \\\n                                          SK_ABORT(\"assert(\" #cond \")\");         \\\n                                      }() )\n    #define SkDEBUGFAIL(message)        SK_ABORT(message)\n    #define SkDEBUGFAILF(fmt, ...)      SkASSERTF(false, fmt, ##__VA_ARGS__)\n    #define SkDEBUGCODE(...)            __VA_ARGS__\n    #define SkDEBUGF(args       )       SkDebugf args\n    #define SkAssertResult(cond)        SkASSERT(cond)\n#else\n    #define SkASSERT(cond)            static_cast<void>(0)\n    #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)\n    #define SkDEBUGFAIL(message)\n    #define SkDEBUGFAILF(fmt, ...)\n    #define SkDEBUGCODE(...)\n    #define SkDEBUGF(args)\n\n    // unlike SkASSERT, this guy executes its condition in the non-debug build.\n    // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.\n    #define SkAssertResult(cond)         if (cond) {} do {} while(false)\n#endif\n\n// some clients (e.g. third_party/WebKit/Source/platform/fonts/FontCustomPlatformData.h)\n// depend on SkString forward declaration below. Remove this once dependencies are fixed.\nclass SkString;\n\n/*\n *  Usage:  SK_MACRO_CONCAT(a, b)   to construct the symbol ab\n *\n *  SK_MACRO_CONCAT_IMPL_PRIV just exists to make this work. Do not use directly\n *\n */\n#define SK_MACRO_CONCAT(X, Y)           SK_MACRO_CONCAT_IMPL_PRIV(X, Y)\n#define SK_MACRO_CONCAT_IMPL_PRIV(X, Y)  X ## Y\n\n/*\n *  Usage: SK_MACRO_APPEND_LINE(foo)    to make foo123, where 123 is the current\n *                                      line number. Easy way to construct\n *                                      unique names for local functions or\n *                                      variables.\n */\n#define SK_MACRO_APPEND_LINE(name)  SK_MACRO_CONCAT(name, __LINE__)\n\n/**\n * For some classes, it's almost always an error to instantiate one without a name, e.g.\n *   {\n *       SkAutoMutexAcquire(&mutex);\n *       <some code>\n *   }\n * In this case, the writer meant to hold mutex while the rest of the code in the block runs,\n * but instead the mutex is acquired and then immediately released.  The correct usage is\n *   {\n *       SkAutoMutexAcquire lock(&mutex);\n *       <some code>\n *   }\n *\n * To prevent callers from instantiating your class without a name, use SK_REQUIRE_LOCAL_VAR\n * like this:\n *   class classname {\n *       <your class>\n *   };\n *   #define classname(...) SK_REQUIRE_LOCAL_VAR(classname)\n *\n * This won't work with templates, and you must inline the class' constructors and destructors.\n * Take a look at SkAutoFree and SkAutoMalloc in this file for examples.\n */\n#define SK_REQUIRE_LOCAL_VAR(classname) \\\n    static_assert(false, \"missing name for \" #classname)\n\n///////////////////////////////////////////////////////////////////////\n\n/**\n *  Fast type for signed 8 bits. Use for parameter passing and local variables,\n *  not for storage.\n */\ntypedef int S8CPU;\n\n/**\n *  Fast type for unsigned 8 bits. Use for parameter passing and local\n *  variables, not for storage\n */\ntypedef unsigned U8CPU;\n\n/**\n *  Fast type for signed 16 bits. Use for parameter passing and local variables,\n *  not for storage\n */\ntypedef int S16CPU;\n\n/**\n *  Fast type for unsigned 16 bits. Use for parameter passing and local\n *  variables, not for storage\n */\ntypedef unsigned U16CPU;\n\n/**\n *  Meant to be a small version of bool, for storage purposes. Will be 0 or 1\n */\ntypedef uint8_t SkBool8;\n\n#include \"../private/SkTFitsIn.h\"\ntemplate <typename D, typename S> constexpr D SkTo(S s) {\n    return SkASSERT(SkTFitsIn<D>(s)),\n           static_cast<D>(s);\n}\n#define SkToS8(x)    SkTo<int8_t>(x)\n#define SkToU8(x)    SkTo<uint8_t>(x)\n#define SkToS16(x)   SkTo<int16_t>(x)\n#define SkToU16(x)   SkTo<uint16_t>(x)\n#define SkToS32(x)   SkTo<int32_t>(x)\n#define SkToU32(x)   SkTo<uint32_t>(x)\n#define SkToInt(x)   SkTo<int>(x)\n#define SkToUInt(x)  SkTo<unsigned>(x)\n#define SkToSizeT(x) SkTo<size_t>(x)\n\n/** Returns 0 or 1 based on the condition\n*/\n#define SkToBool(cond)  ((cond) != 0)\n\n#define SK_MaxS16   32767\n#define SK_MinS16   -32767\n#define SK_MaxU16   0xFFFF\n#define SK_MinU16   0\n#define SK_MaxS32   0x7FFFFFFF\n#define SK_MinS32   -SK_MaxS32\n#define SK_MaxU32   0xFFFFFFFF\n#define SK_MinU32   0\n#define SK_NaN32    ((int) (1U << 31))\n#define SK_MaxSizeT SIZE_MAX\nstatic constexpr int64_t SK_MaxS64 = 0x7FFFFFFFFFFFFFFF;\nstatic constexpr int64_t SK_MinS64 = -SK_MaxS64;\n\nstatic inline int32_t SkLeftShift(int32_t value, int32_t shift) {\n    return (int32_t) ((uint32_t) value << shift);\n}\n\nstatic inline int64_t SkLeftShift(int64_t value, int32_t shift) {\n    return (int64_t) ((uint64_t) value << shift);\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\n/** Returns the number of entries in an array (not a pointer) */\ntemplate <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];\n#define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))\n\n// Can be used to bracket data types that must be dense, e.g. hash keys.\n#if defined(__clang__)  // This should work on GCC too, but GCC diagnostic pop didn't seem to work!\n    #define SK_BEGIN_REQUIRE_DENSE _Pragma(\"GCC diagnostic push\") \\\n                                   _Pragma(\"GCC diagnostic error \\\"-Wpadded\\\"\")\n    #define SK_END_REQUIRE_DENSE   _Pragma(\"GCC diagnostic pop\")\n#else\n    #define SK_BEGIN_REQUIRE_DENSE\n    #define SK_END_REQUIRE_DENSE\n#endif\n\n#define SkAlign2(x)     (((x) + 1) >> 1 << 1)\n#define SkIsAlign2(x)   (0 == ((x) & 1))\n\n#define SkAlign4(x)     (((x) + 3) >> 2 << 2)\n#define SkIsAlign4(x)   (0 == ((x) & 3))\n\n#define SkAlign8(x)     (((x) + 7) >> 3 << 3)\n#define SkIsAlign8(x)   (0 == ((x) & 7))\n\n#define SkAlign16(x)     (((x) + 15) >> 4 << 4)\n#define SkIsAlign16(x)   (0 == ((x) & 15))\n\n#define SkAlignPtr(x)   (sizeof(void*) == 8 ?   SkAlign8(x) :   SkAlign4(x))\n#define SkIsAlignPtr(x) (sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x))\n\ntypedef uint32_t SkFourByteTag;\n#define SkSetFourByteTag(a, b, c, d)    (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))\n\n/** 32 bit integer to hold a unicode value\n*/\ntypedef int32_t SkUnichar;\n\n/** 16 bit unsigned integer to hold a glyph index\n*/\ntypedef uint16_t SkGlyphID;\n\n/** 32 bit value to hold a millisecond duration\n *  Note that SK_MSecMax is about 25 days.\n */\ntypedef uint32_t SkMSec;\n/** 1 second measured in milliseconds\n*/\n#define SK_MSec1 1000\n/** maximum representable milliseconds; 24d 20h 31m 23.647s.\n*/\n#define SK_MSecMax 0x7FFFFFFF\n/** Returns a < b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0\n*/\n#define SkMSec_LT(a, b)     ((int32_t)(a) - (int32_t)(b) < 0)\n/** Returns a <= b for milliseconds, correctly handling wrap-around from 0xFFFFFFFF to 0\n*/\n#define SkMSec_LE(a, b)     ((int32_t)(a) - (int32_t)(b) <= 0)\n\n/** The generation IDs in Skia reserve 0 has an invalid marker.\n */\n#define SK_InvalidGenID     0\n/** The unique IDs in Skia reserve 0 has an invalid marker.\n */\n#define SK_InvalidUniqueID  0\n\n/****************************************************************************\n    The rest of these only build with C++\n*/\n#ifdef __cplusplus\n\n/** Faster than SkToBool for integral conditions. Returns 0 or 1\n*/\nstatic inline constexpr int Sk32ToBool(uint32_t n) {\n    return (n | (0-n)) >> 31;\n}\n\n/** Generic swap function. Classes with efficient swaps should specialize this function to take\n    their fast path. This function is used by SkTSort. */\ntemplate <typename T> static inline void SkTSwap(T& a, T& b) {\n    T c(std::move(a));\n    a = std::move(b);\n    b = std::move(c);\n}\n\nstatic inline int32_t SkAbs32(int32_t value) {\n    SkASSERT(value != SK_NaN32);  // The most negative int32_t can't be negated.\n    if (value < 0) {\n        value = -value;\n    }\n    return value;\n}\n\ntemplate <typename T> static inline T SkTAbs(T value) {\n    if (value < 0) {\n        value = -value;\n    }\n    return value;\n}\n\nstatic inline int32_t SkMax32(int32_t a, int32_t b) {\n    if (a < b)\n        a = b;\n    return a;\n}\n\nstatic inline int32_t SkMin32(int32_t a, int32_t b) {\n    if (a > b)\n        a = b;\n    return a;\n}\n\ntemplate <typename T> constexpr const T& SkTMin(const T& a, const T& b) {\n    return (a < b) ? a : b;\n}\n\ntemplate <typename T> constexpr const T& SkTMax(const T& a, const T& b) {\n    return (b < a) ? a : b;\n}\n\nstatic inline int32_t SkSign32(int32_t a) {\n    return (a >> 31) | ((unsigned) -a >> 31);\n}\n\nstatic inline int32_t SkFastMin32(int32_t value, int32_t max) {\n    if (value > max) {\n        value = max;\n    }\n    return value;\n}\n\n/** Returns value pinned between min and max, inclusively. */\ntemplate <typename T> static constexpr const T& SkTPin(const T& value, const T& min, const T& max) {\n    return SkTMax(SkTMin(value, max), min);\n}\n\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n *  Indicates whether an allocation should count against a cache budget.\n */\nenum class SkBudgeted : bool {\n    kNo  = false,\n    kYes = true\n};\n\n/**\n * Indicates whether a backing store needs to be an exact match or can be larger\n * than is strictly necessary\n */\nenum class SkBackingFit {\n    kApprox,\n    kExact\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\n/** Use to combine multiple bits in a bitmask in a type safe way.\n */\ntemplate <typename T>\nT SkTBitOr(T a, T b) {\n    return (T)(a | b);\n}\n\n/**\n *  Use to cast a pointer to a different type, and maintaining strict-aliasing\n */\ntemplate <typename Dst> Dst SkTCast(const void* ptr) {\n    union {\n        const void* src;\n        Dst dst;\n    } data;\n    data.src = ptr;\n    return data.dst;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\n/** \\class SkNoncopyable\n\nSkNoncopyable is the base class for objects that do not want to\nbe copied. It hides its copy-constructor and its assignment-operator.\n*/\nclass SK_API SkNoncopyable {\npublic:\n    SkNoncopyable() = default;\n\n    SkNoncopyable(SkNoncopyable&&) = default;\n    SkNoncopyable& operator =(SkNoncopyable&&) = default;\n\n    SkNoncopyable(const SkNoncopyable&) = delete;\n    SkNoncopyable& operator=(const SkNoncopyable&) = delete;\n};\n\n#endif /* C++ */\n\n#endif\n"
  },
  {
    "path": "include/core/SkUnPreMultiply.h",
    "content": "\n/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n\n\n\n#ifndef SkUnPreMultiply_DEFINED\n#define SkUnPreMultiply_DEFINED\n\n#include \"SkColor.h\"\n\nclass SK_API SkUnPreMultiply {\npublic:\n    typedef uint32_t Scale;\n\n    // index this table with alpha [0..255]\n    static const Scale* GetScaleTable() {\n        return gTable;\n    }\n\n    static Scale GetScale(U8CPU alpha) {\n        SkASSERT(alpha <= 255);\n        return gTable[alpha];\n    }\n\n    /** Usage:\n\n        const Scale* table = SkUnPreMultiply::GetScaleTable();\n\n        for (...) {\n            unsigned a = ...\n            SkUnPreMultiply::Scale scale = table[a];\n\n            red = SkUnPreMultiply::ApplyScale(scale, red);\n            ...\n            // now red is unpremultiplied\n        }\n    */\n    static U8CPU ApplyScale(Scale scale, U8CPU component) {\n        SkASSERT(component <= 255);\n        return (scale * component + (1 << 23)) >> 24;\n    }\n\n    static SkColor PMColorToColor(SkPMColor c);\n\n    static uint32_t UnPreMultiplyPreservingByteOrder(SkPMColor c);\n\nprivate:\n    static const uint32_t gTable[256];\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkVertices.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkVertices_DEFINED\n#define SkVertices_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkData.h\"\n#include \"SkPoint.h\"\n#include \"SkRect.h\"\n#include \"SkRefCnt.h\"\n\n/**\n * An immutable set of vertex data that can be used with SkCanvas::drawVertices.\n */\nclass SK_API SkVertices : public SkNVRefCnt<SkVertices> {\npublic:\n    enum VertexMode {\n        kTriangles_VertexMode,\n        kTriangleStrip_VertexMode,\n        kTriangleFan_VertexMode,\n\n        kLast_VertexMode = kTriangleFan_VertexMode,\n    };\n\n    /**\n     *  Create a vertices by copying the specified arrays. texs and colors may be nullptr,\n     *  and indices is ignored if indexCount == 0.\n     */\n    static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,\n                                      const SkPoint positions[],\n                                      const SkPoint texs[],\n                                      const SkColor colors[],\n                                      int indexCount,\n                                      const uint16_t indices[]);\n\n    static sk_sp<SkVertices> MakeCopy(VertexMode mode, int vertexCount,\n                                      const SkPoint positions[],\n                                      const SkPoint texs[],\n                                      const SkColor colors[]) {\n        return MakeCopy(mode, vertexCount, positions, texs, colors, 0, nullptr);\n    }\n\n    struct Sizes;\n\n    enum BuilderFlags {\n        kHasTexCoords_BuilderFlag   = 1 << 0,\n        kHasColors_BuilderFlag      = 1 << 1,\n    };\n    class Builder {\n    public:\n        Builder(VertexMode mode, int vertexCount, int indexCount, uint32_t flags);\n\n        bool isValid() const { return fVertices != nullptr; }\n\n        // if the builder is invalid, these will return 0\n        int vertexCount() const;\n        int indexCount() const;\n        SkPoint* positions();\n        SkPoint* texCoords();   // returns null if there are no texCoords\n        SkColor* colors();      // returns null if there are no colors\n        uint16_t* indices();    // returns null if there are no indices\n\n        // Detach the built vertices object. After the first call, this will always return null.\n        sk_sp<SkVertices> detach();\n\n    private:\n        Builder(VertexMode mode, int vertexCount, int indexCount, const Sizes&);\n\n        void init(VertexMode mode, int vertexCount, int indexCount, const Sizes&);\n\n        // holds a partially complete object. only completed in detach()\n        sk_sp<SkVertices> fVertices;\n        // Extra storage for intermediate vertices in the case where the client specifies indexed\n        // triangle fans. These get converted to indexed triangles when the Builder is finalized.\n        std::unique_ptr<uint8_t[]> fIntermediateFanIndices;\n\n        friend class SkVertices;\n    };\n\n    uint32_t uniqueID() const { return fUniqueID; }\n    VertexMode mode() const { return fMode; }\n    const SkRect& bounds() const { return fBounds; }\n\n    bool hasColors() const { return SkToBool(this->colors()); }\n    bool hasTexCoords() const { return SkToBool(this->texCoords()); }\n    bool hasIndices() const { return SkToBool(this->indices()); }\n\n    int vertexCount() const { return fVertexCnt; }\n    const SkPoint* positions() const { return fPositions; }\n    const SkPoint* texCoords() const { return fTexs; }\n    const SkColor* colors() const { return fColors; }\n\n    int indexCount() const { return fIndexCnt; }\n    const uint16_t* indices() const { return fIndices; }\n\n    // returns approximate byte size of the vertices object\n    size_t approximateSize() const;\n\n    /**\n     *  Recreate a vertices from a buffer previously created by calling encode().\n     *  Returns null if the data is corrupt or the length is incorrect for the contents.\n     */\n    static sk_sp<SkVertices> Decode(const void* buffer, size_t length);\n\n    /**\n     *  Pack the vertices object into a byte buffer. This can be used to recreate the vertices\n     *  by calling Decode() with the buffer.\n     */\n    sk_sp<SkData> encode() const;\n\nprivate:\n    SkVertices() {}\n\n    // these are needed since we've manually sized our allocation (see Builder::init)\n    friend class SkNVRefCnt<SkVertices>;\n    void operator delete(void* p);\n\n    static sk_sp<SkVertices> Alloc(int vCount, int iCount, uint32_t builderFlags,\n                                   size_t* arraySize);\n\n    // we store this first, to pair with the refcnt in our base-class, so we don't have an\n    // unnecessary pad between it and the (possibly 8-byte aligned) ptrs.\n    uint32_t fUniqueID;\n\n    // these point inside our allocation, so none of these can be \"freed\"\n    SkPoint*    fPositions;\n    SkPoint*    fTexs;\n    SkColor*    fColors;\n    uint16_t*   fIndices;\n\n    SkRect  fBounds;    // computed to be the union of the fPositions[]\n    int     fVertexCnt;\n    int     fIndexCnt;\n\n    VertexMode fMode;\n    // below here is where the actual array data is stored.\n};\n\n#endif\n"
  },
  {
    "path": "include/core/SkYUVSizeInfo.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkYUVSizeInfo_DEFINED\n#define SkYUVSizeInfo_DEFINED\n\n#include \"SkSize.h\"\n\nstruct SkYUVSizeInfo {\n    enum YUVIndex {\n        kY          = 0,\n        kU          = 1,\n        kV          = 2,\n    };\n    SkISize fSizes[3];\n\n    /**\n     * While the widths of the Y, U, and V planes are not restricted, the\n     * implementation often requires that the width of the memory allocated\n     * for each plane be a multiple of 8.\n     *\n     * This struct allows us to inform the client how many \"widthBytes\"\n     * that we need.  Note that we use the new idea of \"widthBytes\"\n     * because this idea is distinct from \"rowBytes\" (used elsewhere in\n     * Skia).  \"rowBytes\" allow the last row of the allocation to not\n     * include any extra padding, while, in this case, every single row of\n     * the allocation must be at least \"widthBytes\".\n     */\n    size_t fWidthBytes[3];\n};\n\n#endif // SkYUVSizeInfo_DEFINED\n"
  },
  {
    "path": "include/effects/Sk1DPathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef Sk1DPathEffect_DEFINED\n#define Sk1DPathEffect_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkPathEffect.h\"\n#include \"SkPath.h\"\n\nclass SkPathMeasure;\n\n// This class is not exported to java.\nclass SK_API Sk1DPathEffect : public SkPathEffect {\npublic:\n    virtual bool filterPath(SkPath* dst, const SkPath& src,\n                            SkStrokeRec*, const SkRect*) const override;\n\nprotected:\n    /** Called at the start of each contour, returns the initial offset\n        into that contour.\n    */\n    virtual SkScalar begin(SkScalar contourLength) const = 0;\n    /** Called with the current distance along the path, with the current matrix\n        for the point/tangent at the specified distance.\n        Return the distance to travel for the next call. If return <= 0, then that\n        contour is done.\n    */\n    virtual SkScalar next(SkPath* dst, SkScalar dist, SkPathMeasure&) const = 0;\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    bool exposedInAndroidJavaAPI() const override { return true; }\n#endif\n\nprivate:\n    typedef SkPathEffect INHERITED;\n};\n\nclass SK_API SkPath1DPathEffect : public Sk1DPathEffect {\npublic:\n    enum Style {\n        kTranslate_Style,   // translate the shape to each position\n        kRotate_Style,      // rotate the shape about its center\n        kMorph_Style,       // transform each point, and turn lines into curves\n\n        kLastEnum_Style = kMorph_Style,\n    };\n\n    /** Dash by replicating the specified path.\n        @param path The path to replicate (dash)\n        @param advance The space between instances of path\n        @param phase distance (mod advance) along path for its initial position\n        @param style how to transform path at each point (based on the current\n                     position and tangent)\n    */\n    static sk_sp<SkPathEffect> Make(const SkPath& path, SkScalar advance, SkScalar phase, Style);\n\n    virtual bool filterPath(SkPath*, const SkPath&,\n                            SkStrokeRec*, const SkRect*) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    SkPath1DPathEffect(const SkPath& path, SkScalar advance, SkScalar phase, Style);\n    void flatten(SkWriteBuffer&) const override;\n\n    // overrides from Sk1DPathEffect\n    SkScalar begin(SkScalar contourLength) const override;\n    SkScalar next(SkPath*, SkScalar, SkPathMeasure&) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkPath      fPath;          // copied from constructor\n    SkScalar    fAdvance;       // copied from constructor\n    SkScalar    fInitialOffset; // computed from phase\n    Style       fStyle;         // copied from constructor\n\n    typedef Sk1DPathEffect INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/Sk2DPathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef Sk2DPathEffect_DEFINED\n#define Sk2DPathEffect_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkPath.h\"\n#include \"SkPathEffect.h\"\n#include \"SkMatrix.h\"\n\nclass SK_API Sk2DPathEffect : public SkPathEffect {\npublic:\n    bool filterPath(SkPath*, const SkPath&, SkStrokeRec*, const SkRect*) const override;\n\nprotected:\n    /** New virtual, to be overridden by subclasses.\n        This is called once from filterPath, and provides the\n        uv parameter bounds for the path. Subsequent calls to\n        next() will receive u and v values within these bounds,\n        and then a call to end() will signal the end of processing.\n    */\n    virtual void begin(const SkIRect& uvBounds, SkPath* dst) const;\n    virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const;\n    virtual void end(SkPath* dst) const;\n\n    /** Low-level virtual called per span of locations in the u-direction.\n        The default implementation calls next() repeatedly with each\n        location.\n    */\n    virtual void nextSpan(int u, int v, int ucount, SkPath* dst) const;\n\n    const SkMatrix& getMatrix() const { return fMatrix; }\n\n    // protected so that subclasses can call this during unflattening\n    explicit Sk2DPathEffect(const SkMatrix& mat);\n    void flatten(SkWriteBuffer&) const override;\n\n    void toString(SkString* str) const override;\n\nprivate:\n    SkMatrix    fMatrix, fInverse;\n    bool        fMatrixIsInvertible;\n\n    // illegal\n    Sk2DPathEffect(const Sk2DPathEffect&);\n    Sk2DPathEffect& operator=(const Sk2DPathEffect&);\n\n    friend class Sk2DPathEffectBlitter;\n    typedef SkPathEffect INHERITED;\n};\n\nclass SK_API SkLine2DPathEffect : public Sk2DPathEffect {\npublic:\n    static sk_sp<SkPathEffect> Make(SkScalar width, const SkMatrix& matrix) {\n        if (!(width >= 0)) {\n            return nullptr;\n        }\n        return sk_sp<SkPathEffect>(new SkLine2DPathEffect(width, matrix));\n    }\n\n    virtual bool filterPath(SkPath* dst, const SkPath& src,\n                            SkStrokeRec*, const SkRect*) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    SkLine2DPathEffect(SkScalar width, const SkMatrix& matrix)\n        : Sk2DPathEffect(matrix), fWidth(width) {\n            SkASSERT(width >= 0);\n        }\n    void flatten(SkWriteBuffer&) const override;\n\n    void nextSpan(int u, int v, int ucount, SkPath*) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkScalar fWidth;\n\n    typedef Sk2DPathEffect INHERITED;\n};\n\nclass SK_API SkPath2DPathEffect : public Sk2DPathEffect {\npublic:\n    /**\n     *  Stamp the specified path to fill the shape, using the matrix to define\n     *  the latice.\n     */\n    static sk_sp<SkPathEffect> Make(const SkMatrix& matrix, const SkPath& path) {\n        return sk_sp<SkPathEffect>(new SkPath2DPathEffect(matrix, path));\n    }\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    SkPath2DPathEffect(const SkMatrix&, const SkPath&);\n    void flatten(SkWriteBuffer&) const override;\n\n    void next(const SkPoint&, int u, int v, SkPath*) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkPath  fPath;\n\n    typedef Sk2DPathEffect INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkAlphaThresholdFilter.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAlphaThresholdFilter_DEFINED\n#define SkAlphaThresholdFilter_DEFINED\n\n#include \"SkImageFilter.h\"\n\nclass SkRegion;\n\nclass SK_API SkAlphaThresholdFilter {\npublic:\n    /**\n     * Creates an image filter that samples a region. If the sample is inside the\n     * region the alpha of the image is boosted up to a threshold value. If it is\n     * outside the region then the alpha is decreased to the threshold value.\n     * The 0,0 point of the region corresponds to the upper left corner of the\n     * source image.\n     */\n    static sk_sp<SkImageFilter> Make(const SkRegion& region, SkScalar innerMin,\n                                     SkScalar outerMax, sk_sp<SkImageFilter> input,\n                                     const SkImageFilter::CropRect* cropRect = nullptr);\n\n\n    static void InitializeFlattenables();\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkArithmeticImageFilter.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkArithmeticImageFilter_DEFINED\n#define SkArithmeticImageFilter_DEFINED\n\n#include \"SkImageFilter.h\"\n\nclass SK_API SkArithmeticImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(float k1, float k2, float k3, float k4, bool enforcePMColor,\n                                     sk_sp<SkImageFilter> background,\n                                     sk_sp<SkImageFilter> foreground,\n                                     const SkImageFilter::CropRect* cropRect);\n\n    static void InitializeFlattenables();\n\nprivate:\n    SkArithmeticImageFilter();  // can't instantiate\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkBlurDrawLooper.h",
    "content": "/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkBlurDrawLooper_DEFINED\n#define SkBlurDrawLooper_DEFINED\n\n#include \"SkDrawLooper.h\"\n\n/**\n *  Draws a shadow of the object (possibly offset), and then draws the original object in\n *  its original position.\n */\nnamespace SkBlurDrawLooper {\n    sk_sp<SkDrawLooper> SK_API Make(SkColor color, SkScalar sigma, SkScalar dx, SkScalar dy);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkBlurImageFilter.h",
    "content": "/*\n * Copyright 2011 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBlurImageFilter_DEFINED\n#define SkBlurImageFilter_DEFINED\n\n#include \"SkImageFilter.h\"\n\nclass SK_API SkBlurImageFilter {\npublic:\n    /*! \\enum TileMode */\n    enum TileMode {\n      kClamp_TileMode = 0,    /*!< Clamp to the image's edge pixels. */\n                              /*!< This re-weights the filter so samples outside have no effect */\n      kRepeat_TileMode,       /*!< Wrap around to the image's opposite edge. */\n      kClampToBlack_TileMode, /*!< Fill with transparent black. */\n      kLast_TileMode = kClampToBlack_TileMode,\n\n      // TODO: remove kMax - it is non-standard but Chromium uses it\n      kMax_TileMode = kClampToBlack_TileMode\n    };\n\n    static sk_sp<SkImageFilter> Make(SkScalar sigmaX, SkScalar sigmaY,\n                                     sk_sp<SkImageFilter> input,\n                                     const SkImageFilter::CropRect* cropRect = nullptr,\n                                     TileMode tileMode = TileMode::kClampToBlack_TileMode);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkBlurMaskFilter.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkBlurMaskFilter_DEFINED\n#define SkBlurMaskFilter_DEFINED\n\n// we include this since our callers will need to at least be able to ref/unref\n#include \"SkMaskFilter.h\"\n#include \"SkRect.h\"\n#include \"SkScalar.h\"\n#include \"SkBlurTypes.h\"\n\nclass SkRRect;\n\nclass SK_API SkBlurMaskFilter {\npublic:\n#ifdef SK_SUPPORT_LEGACY_EMBOSSMASKFILTER\n    /** Create an emboss maskfilter\n        @param blurSigma    standard deviation of the Gaussian blur to apply\n                            before applying lighting (e.g. 3)\n        @param direction    array of 3 scalars [x, y, z] specifying the direction of the light source\n        @param ambient      0...1 amount of ambient light\n        @param specular     coefficient for specular highlights (e.g. 8)\n        @return the emboss maskfilter\n    */\n    static sk_sp<SkMaskFilter> MakeEmboss(SkScalar blurSigma, const SkScalar direction[3],\n                                          SkScalar ambient, SkScalar specular);\n#endif\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkColorFilterImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorFilterImageFilter_DEFINED\n#define SkColorFilterImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n\nclass SkColorFilter;\n\nclass SK_API SkColorFilterImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(sk_sp<SkColorFilter> cf,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    bool onIsColorFilterNode(SkColorFilter**) const override;\n    bool onCanHandleComplexCTM() const override { return true; }\n    bool affectsTransparentBlack() const override;\n\nprivate:\n    SkColorFilterImageFilter(sk_sp<SkColorFilter> cf,\n                             sk_sp<SkImageFilter> input,\n                             const CropRect* cropRect);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    sk_sp<SkColorFilter> fColorFilter;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkColorMatrix.h",
    "content": "/*\n * Copyright 2007 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorMatrix_DEFINED\n#define SkColorMatrix_DEFINED\n\n#include \"SkScalar.h\"\n\nclass SK_API SkColorMatrix {\npublic:\n    enum {\n        kCount = 20\n    };\n    SkScalar    fMat[kCount];\n\n    enum Elem {\n        kR_Scale    = 0,\n        kG_Scale    = 6,\n        kB_Scale    = 12,\n        kA_Scale    = 18,\n\n        kR_Trans    = 4,\n        kG_Trans    = 9,\n        kB_Trans    = 14,\n        kA_Trans    = 19,\n    };\n\n    void setIdentity();\n    void setScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,\n                  SkScalar aScale = SK_Scalar1);\n    void preScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,\n                  SkScalar aScale = SK_Scalar1);\n    void postScale(SkScalar rScale, SkScalar gScale, SkScalar bScale,\n                   SkScalar aScale = SK_Scalar1);\n    void postTranslate(SkScalar rTrans, SkScalar gTrans, SkScalar bTrans,\n                       SkScalar aTrans = 0);\n\n    enum Axis {\n        kR_Axis = 0,\n        kG_Axis = 1,\n        kB_Axis = 2\n    };\n    void setRotate(Axis, SkScalar degrees);\n    void setSinCos(Axis, SkScalar sine, SkScalar cosine);\n    void preRotate(Axis, SkScalar degrees);\n    void postRotate(Axis, SkScalar degrees);\n\n    void setConcat(const SkColorMatrix& a, const SkColorMatrix& b);\n    void preConcat(const SkColorMatrix& mat) { this->setConcat(*this, mat); }\n    void postConcat(const SkColorMatrix& mat) { this->setConcat(mat, *this); }\n\n    void setSaturation(SkScalar sat);\n    void setRGB2YUV();\n    void setYUV2RGB();\n\n    bool operator==(const SkColorMatrix& other) const {\n        return 0 == memcmp(fMat, other.fMat, sizeof(fMat));\n    }\n\n    bool operator!=(const SkColorMatrix& other) const { return !((*this) == other); }\n\n    static bool NeedsClamping(const SkScalar[20]);\n    static void SetConcat(SkScalar result[20], const SkScalar outer[20], const SkScalar inner[20]);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkColorMatrixFilter.h",
    "content": "/*\n * Copyright 2007 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkColorMatrixFilter_DEFINED\n#define SkColorMatrixFilter_DEFINED\n\n#include \"SkColorFilter.h\"\n#include \"SkColorMatrix.h\"\n\nclass SK_API SkColorMatrixFilter : public SkColorFilter {\npublic:\n    /**\n     *  Create a colorfilter that multiplies the RGB channels by one color, and\n     *  then adds a second color, pinning the result for each component to\n     *  [0..255]. The alpha components of the mul and add arguments\n     *  are ignored.\n     */\n    static sk_sp<SkColorFilter> MakeLightingFilter(SkColor mul, SkColor add);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkComposeImageFilter.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkComposeImageFilter_DEFINED\n#define SkComposeImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n\nclass SK_API SkComposeImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> outer, sk_sp<SkImageFilter> inner);\n\n    SkRect computeFastBounds(const SkRect& src) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    explicit SkComposeImageFilter(sk_sp<SkImageFilter> inputs[2]) : INHERITED(inputs, 2, nullptr) {\n        SkASSERT(inputs[0].get());\n        SkASSERT(inputs[1].get());\n    }\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,\n                           MapDirection, const SkIRect* inputRect) const override;\n    bool onCanHandleComplexCTM() const override { return true; }\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkCornerPathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCornerPathEffect_DEFINED\n#define SkCornerPathEffect_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkPathEffect.h\"\n\n/** \\class SkCornerPathEffect\n\n    SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners\n    into various treatments (e.g. rounded corners)\n*/\nclass SK_API SkCornerPathEffect : public SkPathEffect {\npublic:\n    /** radius must be > 0 to have an effect. It specifies the distance from each corner\n        that should be \"rounded\".\n    */\n    static sk_sp<SkPathEffect> Make(SkScalar radius) {\n        return radius > 0 ? sk_sp<SkPathEffect>(new SkCornerPathEffect(radius)) : nullptr;\n    }\n\n    virtual bool filterPath(SkPath* dst, const SkPath& src,\n                            SkStrokeRec*, const SkRect*) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    bool exposedInAndroidJavaAPI() const override { return true; }\n#endif\n\nprotected:\n    ~SkCornerPathEffect() override;\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    explicit SkCornerPathEffect(SkScalar radius);\n    void flatten(SkWriteBuffer&) const override;\n\nprivate:\n    SkScalar    fRadius;\n\n    typedef SkPathEffect INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkDashPathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDashPathEffect_DEFINED\n#define SkDashPathEffect_DEFINED\n\n#include \"SkPathEffect.h\"\n\nclass SK_API SkDashPathEffect {\npublic:\n    /** intervals: array containing an even number of entries (>=2), with\n         the even indices specifying the length of \"on\" intervals, and the odd\n         indices specifying the length of \"off\" intervals.\n        count: number of elements in the intervals array\n        phase: offset into the intervals array (mod the sum of all of the\n         intervals).\n\n        For example: if intervals[] = {10, 20}, count = 2, and phase = 25,\n         this will set up a dashed path like so:\n         5 pixels off\n         10 pixels on\n         20 pixels off\n         10 pixels on\n         20 pixels off\n         ...\n        A phase of -5, 25, 55, 85, etc. would all result in the same path,\n         because the sum of all the intervals is 30.\n\n        Note: only affects stroked paths.\n    */\n    static sk_sp<SkPathEffect> Make(const SkScalar intervals[], int count, SkScalar phase);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkDiscretePathEffect.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDiscretePathEffect_DEFINED\n#define SkDiscretePathEffect_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkPathEffect.h\"\n\n/** \\class SkDiscretePathEffect\n\n    This path effect chops a path into discrete segments, and randomly displaces them.\n*/\nclass SK_API SkDiscretePathEffect : public SkPathEffect {\npublic:\n    /** Break the path into segments of segLength length, and randomly move the endpoints\n        away from the original path by a maximum of deviation.\n        Note: works on filled or framed paths\n\n        @param seedAssist This is a caller-supplied seedAssist that modifies\n                          the seed value that is used to randomize the path\n                          segments' endpoints. If not supplied it defaults to 0,\n                          in which case filtering a path multiple times will\n                          result in the same set of segments (this is useful for\n                          testing). If a caller does not want this behaviour\n                          they can pass in a different seedAssist to get a\n                          different set of path segments.\n    */\n    static sk_sp<SkPathEffect> Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist = 0);\n\n    virtual bool filterPath(SkPath* dst, const SkPath& src,\n                            SkStrokeRec*, const SkRect*) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\n#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK\n    bool exposedInAndroidJavaAPI() const override { return true; }\n#endif\n\nprotected:\n    SkDiscretePathEffect(SkScalar segLength,\n                         SkScalar deviation,\n                         uint32_t seedAssist);\n    void flatten(SkWriteBuffer&) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkScalar fSegLength, fPerterb;\n\n    /* Caller-supplied 32 bit seed assist */\n    uint32_t fSeedAssist;\n\n    typedef SkPathEffect INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkDisplacementMapEffect.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDisplacementMapEffect_DEFINED\n#define SkDisplacementMapEffect_DEFINED\n\n#include \"SkImageFilter.h\"\n\nclass SK_API SkDisplacementMapEffect : public SkImageFilter {\npublic:\n    enum ChannelSelectorType {\n        kUnknown_ChannelSelectorType,\n        kR_ChannelSelectorType,\n        kG_ChannelSelectorType,\n        kB_ChannelSelectorType,\n        kA_ChannelSelectorType,\n\n        kLast_ChannelSelectorType = kA_ChannelSelectorType\n    };\n\n    ~SkDisplacementMapEffect() override;\n\n    static sk_sp<SkImageFilter> Make(ChannelSelectorType xChannelSelector,\n                                     ChannelSelectorType yChannelSelector,\n                                     SkScalar scale,\n                                     sk_sp<SkImageFilter> displacement,\n                                     sk_sp<SkImageFilter> color,\n                                     const CropRect* cropRect = nullptr);\n\n    SkRect computeFastBounds(const SkRect& src) const override;\n\n    virtual SkIRect onFilterBounds(const SkIRect& src, const SkMatrix& ctm,\n                                   MapDirection, const SkIRect* inputRect) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n\n    SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,\n                            ChannelSelectorType yChannelSelector,\n                            SkScalar scale, sk_sp<SkImageFilter> inputs[2],\n                            const CropRect* cropRect);\n    void flatten(SkWriteBuffer&) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    ChannelSelectorType fXChannelSelector;\n    ChannelSelectorType fYChannelSelector;\n    SkScalar fScale;\n    typedef SkImageFilter INHERITED;\n    const SkImageFilter* getDisplacementInput() const { return getInput(0); }\n    const SkImageFilter* getColorInput() const { return getInput(1); }\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkDropShadowImageFilter.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDropShadowImageFilter_DEFINED\n#define SkDropShadowImageFilter_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkScalar.h\"\n\nclass SK_API SkDropShadowImageFilter : public SkImageFilter {\npublic:\n    enum ShadowMode {\n        kDrawShadowAndForeground_ShadowMode,\n        kDrawShadowOnly_ShadowMode,\n\n        kLast_ShadowMode = kDrawShadowOnly_ShadowMode\n    };\n\n    static const int kShadowModeCount = kLast_ShadowMode+1;\n\n    static sk_sp<SkImageFilter> Make(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY,\n                                     SkColor color, ShadowMode shadowMode,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    SkRect computeFastBounds(const SkRect&) const override;\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    SkIRect onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n\nprivate:\n    SkDropShadowImageFilter(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor,\n                            ShadowMode shadowMode, sk_sp<SkImageFilter> input,\n                            const CropRect* cropRect);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkScalar fDx, fDy, fSigmaX, fSigmaY;\n    SkColor fColor;\n    ShadowMode fShadowMode;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkGradientShader.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkGradientShader_DEFINED\n#define SkGradientShader_DEFINED\n\n#include \"SkShader.h\"\n\n/** \\class SkGradientShader\n\n    SkGradientShader hosts factories for creating subclasses of SkShader that\n    render linear and radial gradients.\n*/\nclass SK_API SkGradientShader {\npublic:\n    enum Flags {\n        /** By default gradients will interpolate their colors in unpremul space\n         *  and then premultiply each of the results. By setting this flag, the\n         *  gradients will premultiply their colors first, and then interpolate\n         *  between them.\n         */\n        kInterpolateColorsInPremul_Flag = 1 << 0,\n    };\n\n    /** Returns a shader that generates a linear gradient between the two specified points.\n        <p />\n        @param  pts     The start and end points for the gradient.\n        @param  colors  The array[count] of colors, to be distributed between the two points\n        @param  pos     May be NULL. array[count] of SkScalars, or NULL, of the relative position of\n                        each corresponding color in the colors array. If this is NULL,\n                        the the colors are distributed evenly between the start and end point.\n                        If this is not null, the values must begin with 0, end with 1.0, and\n                        intermediate values must be strictly increasing.\n        @param  count   Must be >=2. The number of colors (and pos if not NULL) entries.\n        @param  mode    The tiling mode\n    */\n    static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],\n                                      const SkColor colors[], const SkScalar pos[], int count,\n                                      SkShader::TileMode mode,\n                                      uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],\n                                      const SkColor colors[], const SkScalar pos[], int count,\n                                      SkShader::TileMode mode) {\n        return MakeLinear(pts, colors, pos, count, mode, 0, nullptr);\n    }\n\n    /** Returns a shader that generates a linear gradient between the two specified points.\n        <p />\n        @param  pts     The start and end points for the gradient.\n        @param  colors  The array[count] of colors, to be distributed between the two points\n        @param  pos     May be NULL. array[count] of SkScalars, or NULL, of the relative position of\n                        each corresponding color in the colors array. If this is NULL,\n                        the the colors are distributed evenly between the start and end point.\n                        If this is not null, the values must begin with 0, end with 1.0, and\n                        intermediate values must be strictly increasing.\n        @param  count   Must be >=2. The number of colors (and pos if not NULL) entries.\n        @param  mode    The tiling mode\n    */\n    static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],\n                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                      const SkScalar pos[], int count, SkShader::TileMode mode,\n                                      uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeLinear(const SkPoint pts[2],\n                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                      const SkScalar pos[], int count, SkShader::TileMode mode) {\n        return MakeLinear(pts, colors, std::move(colorSpace), pos, count, mode, 0, nullptr);\n    }\n\n    /** Returns a shader that generates a radial gradient given the center and radius.\n        <p />\n        @param  center  The center of the circle for this gradient\n        @param  radius  Must be positive. The radius of the circle for this gradient\n        @param  colors  The array[count] of colors, to be distributed between the center and edge of the circle\n        @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of\n                        each corresponding color in the colors array. If this is NULL,\n                        the the colors are distributed evenly between the center and edge of the circle.\n                        If this is not null, the values must begin with 0, end with 1.0, and\n                        intermediate values must be strictly increasing.\n        @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries\n        @param  mode    The tiling mode\n    */\n    static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,\n                                      const SkColor colors[], const SkScalar pos[], int count,\n                                      SkShader::TileMode mode,\n                                      uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,\n                                      const SkColor colors[], const SkScalar pos[], int count,\n                                      SkShader::TileMode mode) {\n        return MakeRadial(center, radius, colors, pos, count, mode, 0, nullptr);\n    }\n\n    /** Returns a shader that generates a radial gradient given the center and radius.\n        <p />\n        @param  center  The center of the circle for this gradient\n        @param  radius  Must be positive. The radius of the circle for this gradient\n        @param  colors  The array[count] of colors, to be distributed between the center and edge of the circle\n        @param  pos     May be NULL. The array[count] of SkScalars, or NULL, of the relative position of\n                        each corresponding color in the colors array. If this is NULL,\n                        the the colors are distributed evenly between the center and edge of the circle.\n                        If this is not null, the values must begin with 0, end with 1.0, and\n                        intermediate values must be strictly increasing.\n        @param  count   Must be >= 2. The number of colors (and pos if not NULL) entries\n        @param  mode    The tiling mode\n    */\n    static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,\n                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                      const SkScalar pos[], int count, SkShader::TileMode mode,\n                                      uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeRadial(const SkPoint& center, SkScalar radius,\n                                      const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                      const SkScalar pos[], int count, SkShader::TileMode mode) {\n        return MakeRadial(center, radius, colors, std::move(colorSpace), pos, count, mode,\n                          0, nullptr);\n    }\n\n    /**\n     *  Returns a shader that generates a conical gradient given two circles, or\n     *  returns NULL if the inputs are invalid. The gradient interprets the\n     *  two circles according to the following HTML spec.\n     *  http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient\n     */\n    static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,\n                                               const SkPoint& end, SkScalar endRadius,\n                                               const SkColor colors[], const SkScalar pos[],\n                                               int count, SkShader::TileMode mode,\n                                               uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,\n                                               const SkPoint& end, SkScalar endRadius,\n                                               const SkColor colors[], const SkScalar pos[],\n                                               int count, SkShader::TileMode mode) {\n        return MakeTwoPointConical(start, startRadius, end, endRadius, colors, pos, count, mode,\n                                   0, nullptr);\n    }\n\n    /**\n     *  Returns a shader that generates a conical gradient given two circles, or\n     *  returns NULL if the inputs are invalid. The gradient interprets the\n     *  two circles according to the following HTML spec.\n     *  http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient\n     */\n    static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,\n                                               const SkPoint& end, SkScalar endRadius,\n                                               const SkColor4f colors[],\n                                               sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],\n                                               int count, SkShader::TileMode mode,\n                                               uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeTwoPointConical(const SkPoint& start, SkScalar startRadius,\n                                               const SkPoint& end, SkScalar endRadius,\n                                               const SkColor4f colors[],\n                                               sk_sp<SkColorSpace> colorSpace, const SkScalar pos[],\n                                               int count, SkShader::TileMode mode) {\n        return MakeTwoPointConical(start, startRadius, end, endRadius, colors,\n                                   std::move(colorSpace), pos, count, mode, 0, nullptr);\n    }\n\n    /** Returns a shader that generates a sweep gradient given a center.\n        <p />\n        @param  cx         The X coordinate of the center of the sweep\n        @param  cx         The Y coordinate of the center of the sweep\n        @param  colors     The array[count] of colors, to be distributed around the center, within\n                           the gradient angle range.\n        @param  pos        May be NULL. The array[count] of SkScalars, or NULL, of the relative\n                           position of each corresponding color in the colors array. If this is\n                           NULL, then the colors are distributed evenly within the angular range.\n                           If this is not null, the values must begin with 0, end with 1.0, and\n                           intermediate values must be strictly increasing.\n        @param  count      Must be >= 2. The number of colors (and pos if not NULL) entries\n        @param  mode       Tiling mode: controls drawing outside of the gradient angular range.\n        @param  startAngle Start of the angular range, corresponding to pos == 0.\n        @param  endAngle   End of the angular range, corresponding to pos == 1.\n    */\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor colors[], const SkScalar pos[], int count,\n                                     SkShader::TileMode mode,\n                                     SkScalar startAngle, SkScalar endAngle,\n                                     uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor colors[], const SkScalar pos[], int count,\n                                     uint32_t flags, const SkMatrix* localMatrix) {\n        return MakeSweep(cx, cy, colors, pos, count, SkShader::kClamp_TileMode, 0, 360, flags,\n                         localMatrix);\n    }\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor colors[], const SkScalar pos[], int count) {\n        return MakeSweep(cx, cy, colors, pos, count, 0, nullptr);\n    }\n\n    /** Returns a shader that generates a sweep gradient given a center.\n        <p />\n        @param  cx         The X coordinate of the center of the sweep\n        @param  cx         The Y coordinate of the center of the sweep\n        @param  colors     The array[count] of colors, to be distributed around the center, within\n                           the gradient angle range.\n        @param  pos        May be NULL. The array[count] of SkScalars, or NULL, of the relative\n                           position of each corresponding color in the colors array. If this is\n                           NULL, then the colors are distributed evenly within the angular range.\n                           If this is not null, the values must begin with 0, end with 1.0, and\n                           intermediate values must be strictly increasing.\n        @param  count      Must be >= 2. The number of colors (and pos if not NULL) entries\n        @param  mode       Tiling mode: controls drawing outside of the gradient angular range.\n        @param  startAngle Start of the angular range, corresponding to pos == 0.\n        @param  endAngle   End of the angular range, corresponding to pos == 1.\n    */\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                     const SkScalar pos[], int count,\n                                     SkShader::TileMode mode,\n                                     SkScalar startAngle, SkScalar endAngle,\n                                     uint32_t flags, const SkMatrix* localMatrix);\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                     const SkScalar pos[], int count,\n                                     uint32_t flags, const SkMatrix* localMatrix) {\n        return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count,\n                         SkShader::kClamp_TileMode, 0, 360, flags, localMatrix);\n    }\n    static sk_sp<SkShader> MakeSweep(SkScalar cx, SkScalar cy,\n                                     const SkColor4f colors[], sk_sp<SkColorSpace> colorSpace,\n                                     const SkScalar pos[], int count) {\n        return MakeSweep(cx, cy, colors, std::move(colorSpace), pos, count, 0, nullptr);\n    }\n\n    static void InitializeFlattenables();\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkHighContrastFilter.h",
    "content": "/*\n* Copyright 2017 Google Inc.\n*\n* Use of this source code is governed by a BSD-style license that can be\n* found in the LICENSE file.\n*/\n\n#ifndef SkHighContrastFilter_DEFINED\n#define SkHighContrastFilter_DEFINED\n\n#include \"SkColorFilter.h\"\n#include \"SkPaint.h\"\n\n/**\n *  Configuration struct for SkHighContrastFilter.\n *\n *  Provides transformations to improve contrast for users with low vision.\n */\nstruct SkHighContrastConfig {\n    enum class InvertStyle {\n        kNoInvert,\n        kInvertBrightness,\n        kInvertLightness,\n\n        kLast = kInvertLightness\n    };\n\n    SkHighContrastConfig() {\n        fGrayscale = false;\n        fInvertStyle = InvertStyle::kNoInvert;\n        fContrast = 0.0f;\n    }\n\n    SkHighContrastConfig(bool grayscale,\n                         InvertStyle invertStyle,\n                         SkScalar contrast)\n        : fGrayscale(grayscale),\n          fInvertStyle(invertStyle),\n          fContrast(contrast) {}\n\n    // Returns true if all of the fields are set within the valid range.\n    bool isValid() const {\n        return fInvertStyle >= InvertStyle::kNoInvert &&\n            fInvertStyle <= InvertStyle::kInvertLightness &&\n            fContrast >= -1.0 &&\n            fContrast <= 1.0;\n    }\n\n    // If true, the color will be converted to grayscale.\n    bool fGrayscale;\n\n    // Whether to invert brightness, lightness, or neither.\n    InvertStyle fInvertStyle;\n\n    // After grayscale and inverting, the contrast can be adjusted linearly.\n    // The valid range is -1.0 through 1.0, where 0.0 is no adjustment.\n    SkScalar  fContrast;\n};\n\n/**\n *  Color filter that provides transformations to improve contrast\n *  for users with low vision.\n *\n *  Applies the following transformations in this order. Each of these\n *  can be configured using SkHighContrastConfig.\n *\n *    - Conversion to grayscale\n *    - Color inversion (either in RGB or HSL space)\n *    - Increasing the resulting contrast.\n *\n * Calling SkHighContrastFilter::Make will return nullptr if the config is\n * not valid, e.g. if you try to call it with a contrast outside the range of\n * -1.0 to 1.0.\n */\n\nclass SK_API SkHighContrastFilter {\npublic:\n    // Returns the filter, or nullptr if the config is invalid.\n    static sk_sp<SkColorFilter> Make(const SkHighContrastConfig& config);\n\n    static void InitializeFlattenables();\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkImageSource.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageSource_DEFINED\n#define SkImageSource_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImage.h\"\n#include \"SkImageFilter.h\"\n\nclass SK_API SkImageSource : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image);\n    static sk_sp<SkImageFilter> Make(sk_sp<SkImage> image,\n                                     const SkRect& srcRect,\n                                     const SkRect& dstRect,\n                                     SkFilterQuality filterQuality);\n\n    SkRect computeFastBounds(const SkRect& src) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n\n    SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n\nprivate:\n    explicit SkImageSource(sk_sp<SkImage>);\n    SkImageSource(sk_sp<SkImage>,\n                  const SkRect& srcRect,\n                  const SkRect& dstRect,\n                  SkFilterQuality);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    sk_sp<SkImage>   fImage;\n    SkRect           fSrcRect, fDstRect;\n    SkFilterQuality  fFilterQuality;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkLayerDrawLooper.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkLayerDrawLooper_DEFINED\n#define SkLayerDrawLooper_DEFINED\n\n#include \"SkDrawLooper.h\"\n#include \"SkPaint.h\"\n#include \"SkPoint.h\"\n#include \"SkBlendMode.h\"\n\nclass SK_API SkLayerDrawLooper : public SkDrawLooper {\npublic:\n    ~SkLayerDrawLooper() override;\n\n    /**\n     *  Bits specifies which aspects of the layer's paint should replace the\n     *  corresponding aspects on the draw's paint.\n     *  kEntirePaint_Bits means use the layer's paint completely.\n     *  0 means ignore the layer's paint... except for fColorMode, which is\n     *  always applied.\n     */\n    enum Bits {\n        kStyle_Bit      = 1 << 0,   //!< use this layer's Style/stroke settings\n        kTextSkewX_Bit  = 1 << 1,   //!< use this layer's textskewx\n        kPathEffect_Bit = 1 << 2,   //!< use this layer's patheffect\n        kMaskFilter_Bit = 1 << 3,   //!< use this layer's maskfilter\n        kShader_Bit     = 1 << 4,   //!< use this layer's shader\n        kColorFilter_Bit = 1 << 5,  //!< use this layer's colorfilter\n        kXfermode_Bit   = 1 << 6,   //!< use this layer's xfermode\n\n        /**\n         *  Use the layer's paint entirely, with these exceptions:\n         *  - We never override the draw's paint's text_encoding, since that is\n         *    used to interpret the text/len parameters in draw[Pos]Text.\n         *  - Color is always computed using the LayerInfo's fColorMode.\n         */\n        kEntirePaint_Bits = -1\n\n    };\n    typedef int32_t BitFlags;\n\n    /**\n     *  Info for how to apply the layer's paint and offset.\n     *\n     *  fColorMode controls how we compute the final color for the layer:\n     *      The layer's paint's color is treated as the SRC\n     *      The draw's paint's color is treated as the DST\n     *      final-color = Mode(layers-color, draws-color);\n     *  Any SkBlendMode will work. Two common choices are:\n     *      kSrc: to use the layer's color, ignoring the draw's\n     *      kDst: to just keep the draw's color, ignoring the layer's\n     */\n    struct SK_API LayerInfo {\n        BitFlags    fPaintBits;\n        SkBlendMode fColorMode;\n        SkVector    fOffset;\n        bool        fPostTranslate; //!< applies to fOffset\n\n        /**\n         *  Initial the LayerInfo. Defaults to settings that will draw the\n         *  layer with no changes: e.g.\n         *      fPaintBits == 0\n         *      fColorMode == kDst_Mode\n         *      fOffset == (0, 0)\n         */\n        LayerInfo();\n    };\n\n    SkDrawLooper::Context* makeContext(SkCanvas*, SkArenaAlloc*) const override;\n\n    bool asABlurShadow(BlurShadowRec* rec) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer);\n\nprotected:\n    sk_sp<SkDrawLooper> onMakeColorSpace(SkColorSpaceXformer*) const override;\n\n    SkLayerDrawLooper();\n\n    void flatten(SkWriteBuffer&) const override;\n\nprivate:\n    struct Rec {\n        Rec*    fNext;\n        SkPaint fPaint;\n        LayerInfo fInfo;\n    };\n    Rec*    fRecs;\n    int     fCount;\n\n    // state-machine during the init/next cycle\n    class LayerDrawLooperContext : public SkDrawLooper::Context {\n    public:\n        explicit LayerDrawLooperContext(const SkLayerDrawLooper* looper);\n\n    protected:\n        bool next(SkCanvas*, SkPaint* paint) override;\n\n    private:\n        Rec* fCurrRec;\n\n        static void ApplyInfo(SkPaint* dst, const SkPaint& src, const LayerInfo&);\n    };\n\n    typedef SkDrawLooper INHERITED;\n\npublic:\n    class SK_API Builder {\n    public:\n        Builder();\n        ~Builder();\n\n        /**\n         *  Call for each layer you want to add (from top to bottom).\n         *  This returns a paint you can modify, but that ptr is only valid until\n         *  the next call made to addLayer().\n         */\n        SkPaint* addLayer(const LayerInfo&);\n\n        /**\n         *  This layer will draw with the original paint, at the specified offset\n         */\n        void addLayer(SkScalar dx, SkScalar dy);\n\n        /**\n         *  This layer will with the original paint and no offset.\n         */\n        void addLayer() { this->addLayer(0, 0); }\n\n        /// Similar to addLayer, but adds a layer to the top.\n        SkPaint* addLayerOnTop(const LayerInfo&);\n\n        /**\n          * Pass list of layers on to newly built looper and return it. This will\n          * also reset the builder, so it can be used to build another looper.\n          */\n        sk_sp<SkDrawLooper> detach();\n\n    private:\n        Rec* fRecs;\n        Rec* fTopRec;\n        int  fCount;\n    };\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkLightingImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkLightingImageFilter_DEFINED\n#define SkLightingImageFilter_DEFINED\n\n#include \"SkImageFilter.h\"\n#include \"SkColor.h\"\n\n\nclass SkImageFilterLight;\nstruct SkPoint3;\n\nclass SK_API SkLightingImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> MakeDistantLitDiffuse(const SkPoint3& direction,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar kd,\n        sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    static sk_sp<SkImageFilter> MakePointLitDiffuse(const SkPoint3& location,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar kd,\n        sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    static sk_sp<SkImageFilter> MakeSpotLitDiffuse(const SkPoint3& location,\n        const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar kd,\n        sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    static sk_sp<SkImageFilter> MakeDistantLitSpecular(const SkPoint3& direction,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar ks,\n        SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    static sk_sp<SkImageFilter> MakePointLitSpecular(const SkPoint3& location,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar ks,\n        SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    static sk_sp<SkImageFilter> MakeSpotLitSpecular(const SkPoint3& location,\n        const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,\n        SkColor lightColor, SkScalar surfaceScale, SkScalar ks,\n        SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect* cropRect = nullptr);\n    ~SkLightingImageFilter() override;\n\n    static void InitializeFlattenables();\n\nprotected:\n    SkLightingImageFilter(sk_sp<SkImageFilterLight> light,\n                          SkScalar surfaceScale,\n                          sk_sp<SkImageFilter> input,\n                          const CropRect* cropRect);\n    void flatten(SkWriteBuffer&) const override;\n    const SkImageFilterLight* light() const { return fLight.get(); }\n    inline sk_sp<const SkImageFilterLight> refLight() const;\n    SkScalar surfaceScale() const { return fSurfaceScale; }\n    bool affectsTransparentBlack() const override { return true; }\n\nprivate:\n    sk_sp<SkImageFilterLight> fLight;\n    SkScalar fSurfaceScale;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkLumaColorFilter.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkLumaColorFilter_DEFINED\n#define SkLumaColorFilter_DEFINED\n\n#include \"SkColorFilter.h\"\n#include \"SkRefCnt.h\"\n\nclass SkRasterPipeline;\n\n/**\n *  Luminance-to-alpha color filter, as defined in\n *  http://www.w3.org/TR/SVG/masking.html#Masking\n *  http://www.w3.org/TR/css-masking/#MaskValues\n *\n *  The resulting color is black with transparency equal to the\n *  luminance value modulated by alpha:\n *\n *    C' = [ Lum * a, 0, 0, 0 ]\n *\n */\n\n #include \"SkFlattenable.h\"\n\nclass SK_API SkLumaColorFilter : public SkColorFilter {\npublic:\n    static sk_sp<SkColorFilter> Make();\n\n#if SK_SUPPORT_GPU\n    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(\n            GrContext*, const GrColorSpaceInfo&) const override;\n#endif\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n\nprivate:\n    SkLumaColorFilter();\n    void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,\n                        bool shaderIsOpaque) const override;\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    typedef SkColorFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkMagnifierImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkMagnifierImageFilter_DEFINED\n#define SkMagnifierImageFilter_DEFINED\n\n#include \"SkRect.h\"\n#include \"SkImageFilter.h\"\n\nclass SK_API SkMagnifierImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(const SkRect& srcRect, SkScalar inset,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    SkMagnifierImageFilter(const SkRect& srcRect,\n                           SkScalar inset,\n                           sk_sp<SkImageFilter> input,\n                           const CropRect* cropRect);\n    void flatten(SkWriteBuffer&) const override;\n\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkRect   fSrcRect;\n    SkScalar fInset;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkMatrixConvolutionImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMatrixConvolutionImageFilter_DEFINED\n#define SkMatrixConvolutionImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkScalar.h\"\n#include \"SkSize.h\"\n#include \"SkPoint.h\"\n\nclass SkBitmap;\n\n/*! \\class SkMatrixConvolutionImageFilter\n    Matrix convolution image filter.  This filter applies an NxM image\n    processing kernel to a given input image.  This can be used to produce\n    effects such as sharpening, blurring, edge detection, etc.\n */\n\nclass SK_API SkMatrixConvolutionImageFilter : public SkImageFilter {\npublic:\n    /*! \\enum TileMode */\n    enum TileMode {\n      kClamp_TileMode = 0,         /*!< Clamp to the image's edge pixels. */\n      kRepeat_TileMode,        /*!< Wrap around to the image's opposite edge. */\n      kClampToBlack_TileMode,  /*!< Fill with transparent black. */\n      kLast_TileMode = kClampToBlack_TileMode,\n\n      // TODO: remove kMax - it is non-standard but used by Chromium!\n      kMax_TileMode = kClampToBlack_TileMode\n    };\n\n    ~SkMatrixConvolutionImageFilter() override;\n\n    /** Construct a matrix convolution image filter.\n        @param kernelSize     The kernel size in pixels, in each dimension (N by M).\n        @param kernel         The image processing kernel.  Must contain N * M\n                              elements, in row order.\n        @param gain           A scale factor applied to each pixel after\n                              convolution.  This can be used to normalize the\n                              kernel, if it does not sum to 1.\n        @param bias           A bias factor added to each pixel after convolution.\n        @param kernelOffset   An offset applied to each pixel coordinate before\n                              convolution.  This can be used to center the kernel\n                              over the image (e.g., a 3x3 kernel should have an\n                              offset of {1, 1}).\n        @param tileMode       How accesses outside the image are treated.  (@see\n                              TileMode).\n        @param convolveAlpha  If true, all channels are convolved.  If false,\n                              only the RGB channels are convolved, and\n                              alpha is copied from the source image.\n        @param input          The input image filter.  If NULL, the src bitmap\n                              passed to filterImage() is used instead.\n        @param cropRect       The rectangle to which the output processing will be limited.\n    */\n    static sk_sp<SkImageFilter> Make(const SkISize& kernelSize,\n                                     const SkScalar* kernel,\n                                     SkScalar gain,\n                                     SkScalar bias,\n                                     const SkIPoint& kernelOffset,\n                                     TileMode tileMode,\n                                     bool convolveAlpha,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    SkMatrixConvolutionImageFilter(const SkISize& kernelSize,\n                                   const SkScalar* kernel,\n                                   SkScalar gain,\n                                   SkScalar bias,\n                                   const SkIPoint& kernelOffset,\n                                   TileMode tileMode,\n                                   bool convolveAlpha,\n                                   sk_sp<SkImageFilter> input,\n                                   const CropRect* cropRect);\n    void flatten(SkWriteBuffer&) const override;\n\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n    bool affectsTransparentBlack() const override;\n\nprivate:\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkISize   fKernelSize;\n    SkScalar* fKernel;\n    SkScalar  fGain;\n    SkScalar  fBias;\n    SkIPoint  fKernelOffset;\n    TileMode  fTileMode;\n    bool      fConvolveAlpha;\n\n    template <class PixelFetcher, bool convolveAlpha>\n    void filterPixels(const SkBitmap& src,\n                      SkBitmap* result,\n                      SkIVector& offset,\n                      const SkIRect& rect,\n                      const SkIRect& bounds) const;\n    template <class PixelFetcher>\n    void filterPixels(const SkBitmap& src,\n                      SkBitmap* result,\n                      SkIVector& offset,\n                      const SkIRect& rect,\n                      const SkIRect& bounds) const;\n    void filterInteriorPixels(const SkBitmap& src,\n                              SkBitmap* result,\n                              SkIVector& offset,\n                              const SkIRect& rect,\n                              const SkIRect& bounds) const;\n    void filterBorderPixels(const SkBitmap& src,\n                            SkBitmap* result,\n                            SkIVector& offset,\n                            const SkIRect& rect,\n                            const SkIRect& bounds) const;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkMergeImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMergeImageFilter_DEFINED\n#define SkMergeImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n\nclass SK_API SkMergeImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter>* const filters, int count,\n                                     const CropRect* cropRect = nullptr);\n\n    static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilter> first, sk_sp<SkImageFilter> second,\n                                     const CropRect* cropRect = nullptr) {\n        sk_sp<SkImageFilter> array[] = {\n            std::move(first),\n            std::move(second),\n        };\n        return Make(array, 2, cropRect);\n    }\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    bool onCanHandleComplexCTM() const override { return true; }\n\nprivate:\n    SkMergeImageFilter(sk_sp<SkImageFilter>* const filters, int count, const CropRect* cropRect);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkMorphologyImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMorphologyImageFilter_DEFINED\n#define SkMorphologyImageFilter_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkSize.h\"\n\n///////////////////////////////////////////////////////////////////////////////\nclass SK_API SkMorphologyImageFilter : public SkImageFilter {\npublic:\n    SkRect computeFastBounds(const SkRect& src) const override;\n    SkIRect onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n\n    /**\n     * All morphology procs have the same signature: src is the source buffer, dst the\n     * destination buffer, radius is the morphology radius, width and height are the bounds\n     * of the destination buffer (in pixels), and srcStride and dstStride are the\n     * number of pixels per row in each buffer. All buffers are 8888.\n     */\n\n    typedef void (*Proc)(const SkPMColor* src, SkPMColor* dst, int radius,\n                         int width, int height, int srcStride, int dstStride);\n\nprotected:\n    enum Op {\n        kErode_Op,\n        kDilate_Op,\n    };\n\n    virtual Op op() const = 0;\n\n    SkMorphologyImageFilter(int radiusX, int radiusY,\n                            sk_sp<SkImageFilter> input,\n                            const CropRect* cropRect);\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source,\n                                        const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    void flatten(SkWriteBuffer&) const override;\n\n    SkISize radius() const { return fRadius; }\n\nprivate:\n    SkISize  fRadius;\n\n    typedef SkImageFilter INHERITED;\n};\n\n///////////////////////////////////////////////////////////////////////////////\nclass SK_API SkDilateImageFilter : public SkMorphologyImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(int radiusX, int radiusY,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    Op op() const override { return kDilate_Op; }\n\nprivate:\n    SkDilateImageFilter(int radiusX, int radiusY,\n                        sk_sp<SkImageFilter> input,\n                        const CropRect* cropRect)\n        : INHERITED(radiusX, radiusY, input, cropRect) {}\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    typedef SkMorphologyImageFilter INHERITED;\n};\n\n///////////////////////////////////////////////////////////////////////////////\nclass SK_API SkErodeImageFilter : public SkMorphologyImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(int radiusX, int radiusY,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    Op op() const override { return kErode_Op; }\n\nprivate:\n    SkErodeImageFilter(int radiusX, int radiusY,\n                       sk_sp<SkImageFilter> input, const CropRect* cropRect)\n        : INHERITED(radiusX, radiusY, input, cropRect) {}\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    typedef SkMorphologyImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkOffsetImageFilter.h",
    "content": "/*\n * Copyright 2012 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkOffsetImageFilter_DEFINED\n#define SkOffsetImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkPoint.h\"\n\nclass SK_API SkOffsetImageFilter : public SkImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(SkScalar dx, SkScalar dy,\n                                     sk_sp<SkImageFilter> input,\n                                     const CropRect* cropRect = nullptr);\n\n    SkRect computeFastBounds(const SkRect& src) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n    SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n\nprivate:\n    SkOffsetImageFilter(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input, const CropRect*);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkVector fOffset;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkOverdrawColorFilter.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#include \"SkColorFilter.h\"\n#include \"SkFlattenable.h\"\n\n#ifndef SkOverdrawColorFilter_DEFINED\n#define SkOverdrawColorFilter_DEFINED\n\n/**\n *  Uses the value in the src alpha channel to set the dst pixel.\n *  0             -> fColors[0]\n *  1             -> fColors[1]\n *  ...\n *  5 (or larger) -> fColors[5]\n *\n */\nclass SK_API SkOverdrawColorFilter : public SkColorFilter {\npublic:\n    static constexpr int kNumColors = 6;\n\n    static sk_sp<SkOverdrawColorFilter> Make(const SkPMColor colors[kNumColors]) {\n        return sk_sp<SkOverdrawColorFilter>(new SkOverdrawColorFilter(colors));\n    }\n\n#if SK_SUPPORT_GPU\n    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(\n            GrContext*, const GrColorSpaceInfo&) const override;\n#endif\n\n    void toString(SkString* str) const override;\n\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer);\n    Factory getFactory() const override { return CreateProc; }\n    static void InitializeFlattenables();\n\nprotected:\n    void flatten(SkWriteBuffer& buffer) const override;\n\nprivate:\n    SkOverdrawColorFilter(const SkPMColor colors[kNumColors]) {\n        memcpy(fColors, colors, kNumColors * sizeof(SkPMColor));\n    }\n\n    void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool) const override;\n\n    SkPMColor fColors[kNumColors];\n\n    typedef SkColorFilter INHERITED;\n};\n\n#endif // SkOverdrawColorFilter_DEFINED\n"
  },
  {
    "path": "include/effects/SkPaintFlagsDrawFilter.h",
    "content": "/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPaintFlagsDrawFilter_DEFINED\n#define SkPaintFlagsDrawFilter_DEFINED\n\n#include \"SkDrawFilter.h\"\n\nclass SK_API SkPaintFlagsDrawFilter : public SkDrawFilter {\npublic:\n    SkPaintFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags);\n\n    bool filter(SkPaint*, Type) override;\n\nprivate:\n    uint16_t    fClearFlags;    // user specified\n    uint16_t    fSetFlags;      // user specified\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkPaintImageFilter.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPaintImageFilter_DEFINED\n#define SkPaintImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkPaint.h\"\n\nclass SK_API SkPaintImageFilter : public SkImageFilter {\npublic:\n    /** Create a new image filter which fills the given rectangle using the\n     *  given paint. If no rectangle is specified, an output is produced with\n     *  the same bounds as the input primitive (even though the input\n     *  primitive's pixels are not used for processing).\n     *  @param paint  Paint to use when filling the rect.\n     *  @param rect   Rectangle of output pixels. If NULL or a given crop edge is\n     *                not specified, the source primitive's bounds are used\n     *                instead.\n     */\n    static sk_sp<SkImageFilter> Make(const SkPaint& paint, const CropRect* cropRect = nullptr);\n\n    bool affectsTransparentBlack() const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer* xformer) const override;\n\nprivate:\n    SkPaintImageFilter(const SkPaint& paint, const CropRect* rect);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkPaint fPaint;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkPerlinNoiseShader.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPerlinNoiseShader_DEFINED\n#define SkPerlinNoiseShader_DEFINED\n\n#include \"SkShader.h\"\n\n/** \\class SkPerlinNoiseShader\n\n    SkPerlinNoiseShader creates an image using the Perlin turbulence function.\n\n    It can produce tileable noise if asked to stitch tiles and provided a tile size.\n    In order to fill a large area with repeating noise, set the stitchTiles flag to\n    true, and render exactly a single tile of noise. Without this flag, the result\n    will contain visible seams between tiles.\n\n    The algorithm used is described here :\n    http://www.w3.org/TR/SVG/filters.html#feTurbulenceElement\n*/\nclass SK_API SkPerlinNoiseShader {\npublic:\n    /**\n     *  This will construct Perlin noise of the given type (Fractal Noise or Turbulence).\n     *\n     *  Both base frequencies (X and Y) have a usual range of (0..1) and must be non-negative.\n     *\n     *  The number of octaves provided should be fairly small, with a limit of 255 enforced.\n     *  Each octave doubles the frequency, so 10 octaves would produce noise from\n     *  baseFrequency * 1, * 2, * 4, ..., * 512, which quickly yields insignificantly small\n     *  periods and resembles regular unstructured noise rather than Perlin noise.\n     *\n     *  If tileSize isn't NULL or an empty size, the tileSize parameter will be used to modify\n     *  the frequencies so that the noise will be tileable for the given tile size. If tileSize\n     *  is NULL or an empty size, the frequencies will be used as is without modification.\n     */\n    static sk_sp<SkShader> MakeFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,\n                                            int numOctaves, SkScalar seed,\n                                            const SkISize* tileSize = nullptr);\n    static sk_sp<SkShader> MakeTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,\n                                          int numOctaves, SkScalar seed,\n                                          const SkISize* tileSize = nullptr);\n    /**\n     * Creates an Improved Perlin Noise shader. The z value is roughly equivalent to the seed of the\n     * other two types, but minor variations to z will only slightly change the noise.\n     */\n    static sk_sp<SkShader> MakeImprovedNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,\n                                             int numOctaves, SkScalar z);\n\n    static void InitializeFlattenables();\n\nprivate:\n    SkPerlinNoiseShader() = delete;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkPictureImageFilter.h",
    "content": "/*\n * Copyright 2013 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPictureImageFilter_DEFINED\n#define SkPictureImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n#include \"SkPicture.h\"\n\nclass SK_API SkPictureImageFilter : public SkImageFilter {\npublic:\n    /**\n     *  Refs the passed-in picture.\n     */\n    static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture);\n\n    /**\n     *  Refs the passed-in picture. cropRect can be used to crop or expand the destination rect when\n     *  the picture is drawn. (No scaling is implied by the dest rect; only the CTM is applied.)\n     */\n    static sk_sp<SkImageFilter> Make(sk_sp<SkPicture> picture, const SkRect& cropRect);\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    /*  Constructs an SkPictureImageFilter object from an SkReadBuffer.\n     *  Note: If the SkPictureImageFilter object construction requires bitmap\n     *  decoding, the decoder must be set on the SkReadBuffer parameter by calling\n     *  SkReadBuffer::setBitmapDecoder() before calling this constructor.\n     *  @param SkReadBuffer Serialized picture data.\n     */\n    void flatten(SkWriteBuffer&) const override;\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n\nprivate:\n    explicit SkPictureImageFilter(sk_sp<SkPicture> picture);\n    SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect, sk_sp<SkColorSpace>);\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    sk_sp<SkPicture>    fPicture;\n    SkRect              fCropRect;\n\n    // Should never be set by a public constructor.  This is only used when onMakeColorSpace()\n    // forces a deferred color space xform.\n    sk_sp<SkColorSpace>   fColorSpace;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkShaderMaskFilter.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkShaderMaskFilter_DEFINED\n#define SkShaderMaskFilter_DEFINED\n\n#include \"SkMaskFilter.h\"\n\nclass SkShader;\n\nclass SK_API SkShaderMaskFilter {\npublic:\n    static sk_sp<SkMaskFilter> Make(sk_sp<SkShader> shader);\n\nprivate:\n    static void InitializeFlattenables();\n    friend class SkFlattenable;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkTableColorFilter.h",
    "content": "/*\n* Copyright 2015 Google Inc.\n*\n* Use of this source code is governed by a BSD-style license that can be\n* found in the LICENSE file.\n*/\n\n#ifndef SkTableColorFilter_DEFINED\n#define SkTableColorFilter_DEFINED\n\n#include \"SkColorFilter.h\"\n\nclass SK_API SkTableColorFilter {\npublic:\n    /**\n     *  Create a table colorfilter, copying the table into the filter, and\n     *  applying it to all 4 components.\n     *      a' = table[a];\n     *      r' = table[r];\n     *      g' = table[g];\n     *      b' = table[b];\n     *  Compoents are operated on in unpremultiplied space. If the incomming\n     *  colors are premultiplied, they are temporarily unpremultiplied, then\n     *  the table is applied, and then the result is remultiplied.\n     */\n    static sk_sp<SkColorFilter> Make(const uint8_t table[256]);\n\n    /**\n     *  Create a table colorfilter, with a different table for each\n     *  component [A, R, G, B]. If a given table is NULL, then it is\n     *  treated as identity, with the component left unchanged. If a table\n     *  is not null, then its contents are copied into the filter.\n     */\n    static sk_sp<SkColorFilter> MakeARGB(const uint8_t tableA[256],\n                                         const uint8_t tableR[256],\n                                         const uint8_t tableG[256],\n                                         const uint8_t tableB[256]);\n\n    static void InitializeFlattenables();\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkTableMaskFilter.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTableMaskFilter_DEFINED\n#define SkTableMaskFilter_DEFINED\n\n#include \"SkMaskFilter.h\"\n#include \"SkScalar.h\"\n\n/** \\class SkTableMaskFilter\n\n    Applies a table lookup on each of the alpha values in the mask.\n    Helper methods create some common tables (e.g. gamma, clipping)\n */\nclass SK_API SkTableMaskFilter {\npublic:\n    /** Utility that sets the gamma table\n     */\n    static void MakeGammaTable(uint8_t table[256], SkScalar gamma);\n\n    /** Utility that creates a clipping table: clamps values below min to 0\n        and above max to 255, and rescales the remaining into 0..255\n     */\n    static void MakeClipTable(uint8_t table[256], uint8_t min, uint8_t max);\n\n    static SkMaskFilter* Create(const uint8_t table[256]);\n    static SkMaskFilter* CreateGamma(SkScalar gamma);\n    static SkMaskFilter* CreateClip(uint8_t min, uint8_t max);\n\n    SkTableMaskFilter() = delete;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkTileImageFilter.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTileImageFilter_DEFINED\n#define SkTileImageFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkImageFilter.h\"\n\nclass SK_API SkTileImageFilter : public SkImageFilter {\npublic:\n    /** Create a tile image filter\n        @param src  Defines the pixels to tile\n        @param dst  Defines the pixels where tiles are drawn\n        @param input    Input from which the subregion defined by srcRect will be tiled\n    */\n    static sk_sp<SkImageFilter> Make(const SkRect& src,\n                                     const SkRect& dst,\n                                     sk_sp<SkImageFilter> input);\n\n    SkIRect onFilterBounds(const SkIRect& src, const SkMatrix& ctm,\n                           MapDirection, const SkIRect* inputRect) const override;\n    SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,\n                               MapDirection, const SkIRect* inputRect) const override;\n    SkRect computeFastBounds(const SkRect& src) const override;\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprotected:\n    void flatten(SkWriteBuffer& buffer) const override;\n\n    sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,\n                                        SkIPoint* offset) const override;\n    sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;\n\nprivate:\n    SkTileImageFilter(const SkRect& srcRect, const SkRect& dstRect, sk_sp<SkImageFilter> input)\n        : INHERITED(&input, 1, nullptr), fSrcRect(srcRect), fDstRect(dstRect) {}\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    SkRect fSrcRect;\n    SkRect fDstRect;\n\n    typedef SkImageFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkToSRGBColorFilter.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkToSRGBColorFilter_DEFINED\n#define SkToSRGBColorFilter_DEFINED\n\n#include \"SkFlattenable.h\"\n#include \"SkColorFilter.h\"\n#include \"SkRefCnt.h\"\n\nclass SkColorSpace;\nclass SkRasterPipeline;\n\n/**\n *  Color filter that converts from supplied color space to sRGB (both gamut and transfer function).\n */\nclass SK_API SkToSRGBColorFilter : public SkColorFilter {\npublic:\n    static sk_sp<SkColorFilter> Make(sk_sp<SkColorSpace> srcColorSpace);\n\n#if SK_SUPPORT_GPU\n    std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(\n            GrContext*, const GrColorSpaceInfo&) const override;\n#endif\n\n    void toString(SkString* str) const override;\n\n    Factory getFactory() const override { return CreateProc; }\n\nprivate:\n    void flatten(SkWriteBuffer&) const override;\n    SkToSRGBColorFilter(sk_sp<SkColorSpace>);\n    void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,\n                        bool shaderIsOpaque) const override;\n    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);\n    friend class SkFlattenable::PrivateInitializer;\n\n    sk_sp<SkColorSpace> fSrcColorSpace;\n\n    typedef SkColorFilter INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkTrimPathEffect.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTrimPathEffect_DEFINED\n#define SkTrimPathEffect_DEFINED\n\n#include \"SkPathEffect.h\"\n\nclass SK_API SkTrimPathEffect {\npublic:\n    enum class Mode {\n        kNormal,   // return the subset path [start,stop]\n        kInverted, // return the complement/subset paths [0,start] + [stop,1]\n    };\n\n    /**\n     *  Take start and stop \"t\" values (values between 0...1), and return a path that is that\n     *  subset of the original path.\n     *\n     *  e.g.\n     *      Make(0.5, 1.0) --> return the 2nd half of the path\n     *      Make(0.33333, 0.66667) --> return the middle third of the path\n     *\n     *  The trim values apply to the entire path, so if it contains several contours, all of them\n     *  are including in the calculation.\n     *\n     *  startT and stopT must be 0..1 inclusive. If they are outside of that interval, they will\n     *  be pinned to the nearest legal value. If either is NaN, null will be returned.\n     *\n     *  Note: for Mode::kNormal, this will return one (logical) segment (even if it is spread\n     *        across multiple contours). For Mode::kInverted, this will return 2 logical\n     *        segments: 0...stopT and startT...1\n     */\n    static sk_sp<SkPathEffect> Make(SkScalar startT, SkScalar stopT, Mode = Mode::kNormal);\n};\n\n#endif\n"
  },
  {
    "path": "include/effects/SkXfermodeImageFilter.h",
    "content": "/*\n * Copyright 2013 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkXfermodeImageFilter_DEFINED\n#define SkXfermodeImageFilter_DEFINED\n\n#include \"SkArithmeticImageFilter.h\"\n#include \"SkBlendMode.h\"\n#include \"SkImageFilter.h\"\n\n/**\n * This filter takes a SkBlendMode, and uses it to composite the foreground over the background.\n * If foreground or background is NULL, the input bitmap (src) is used instead.\n */\nclass SK_API SkXfermodeImageFilter {\npublic:\n    static sk_sp<SkImageFilter> Make(SkBlendMode, sk_sp<SkImageFilter> background,\n                                     sk_sp<SkImageFilter> foreground,\n                                     const SkImageFilter::CropRect* cropRect);\n    static sk_sp<SkImageFilter> Make(SkBlendMode mode, sk_sp<SkImageFilter> background) {\n        return Make(mode, std::move(background), nullptr, nullptr);\n    }\n\n    static void InitializeFlattenables();\n\nprivate:\n    SkXfermodeImageFilter();    // can't instantiate\n};\n\n#endif\n"
  },
  {
    "path": "include/encode/SkEncoder.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEncoder_DEFINED\n#define SkEncoder_DEFINED\n\n#include \"SkPixmap.h\"\n#include \"../private/SkTemplates.h\"\n\nclass SK_API SkEncoder : SkNoncopyable {\npublic:\n\n    /**\n     *  Encode |numRows| rows of input.  If the caller requests more rows than are remaining\n     *  in the src, this will encode all of the remaining rows.  |numRows| must be greater\n     *  than zero.\n     */\n    bool encodeRows(int numRows);\n\n    virtual ~SkEncoder() {}\n\nprotected:\n\n    virtual bool onEncodeRows(int numRows) = 0;\n\n    SkEncoder(const SkPixmap& src, size_t storageBytes)\n        : fSrc(src)\n        , fCurrRow(0)\n        , fStorage(storageBytes)\n    {}\n\n    const SkPixmap&        fSrc;\n    int                    fCurrRow;\n    SkAutoTMalloc<uint8_t> fStorage;\n};\n\n#endif\n"
  },
  {
    "path": "include/encode/SkJpegEncoder.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkJpegEncoder_DEFINED\n#define SkJpegEncoder_DEFINED\n\n#include \"SkEncoder.h\"\n\nclass SkJpegEncoderMgr;\nclass SkWStream;\n\nclass SK_API SkJpegEncoder : public SkEncoder {\npublic:\n\n    enum class AlphaOption {\n        kIgnore,\n        kBlendOnBlack,\n    };\n\n    enum class Downsample {\n        /**\n         *  Reduction by a factor of two in both the horizontal and vertical directions.\n         */\n        k420,\n\n        /**\n         *  Reduction by a factor of two in the horizontal direction.\n         */\n        k422,\n\n        /**\n         *  No downsampling.\n         */\n        k444,\n    };\n\n    struct Options {\n        /**\n         *  |fQuality| must be in [0, 100] where 0 corresponds to the lowest quality.\n         */\n        int fQuality = 100;\n\n        /**\n         *  Choose the downsampling factor for the U and V components.  This is only\n         *  meaningful if the |src| is not kGray, since kGray will not be encoded as YUV.\n         *\n         *  Our default value matches the libjpeg-turbo default.\n         */\n        Downsample fDownsample = Downsample::k420;\n\n        /**\n         *  Jpegs must be opaque.  This instructs the encoder on how to handle input\n         *  images with alpha.\n         *\n         *  The default is to ignore the alpha channel and treat the image as opaque.\n         *  Another option is to blend the pixels onto a black background before encoding.\n         *  In the second case, the encoder supports linear or legacy blending.\n         */\n        AlphaOption fAlphaOption = AlphaOption::kIgnore;\n        SkTransferFunctionBehavior fBlendBehavior = SkTransferFunctionBehavior::kRespect;\n    };\n\n    /**\n     *  Encode the |src| pixels to the |dst| stream.\n     *  |options| may be used to control the encoding behavior.\n     *\n     *  Returns true on success.  Returns false on an invalid or unsupported |src|.\n     */\n    static bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);\n\n    /**\n     *  Create a jpeg encoder that will encode the |src| pixels to the |dst| stream.\n     *  |options| may be used to control the encoding behavior.\n     *\n     *  |dst| is unowned but must remain valid for the lifetime of the object.\n     *\n     *  This returns nullptr on an invalid or unsupported |src|.\n     */\n    static std::unique_ptr<SkEncoder> Make(SkWStream* dst, const SkPixmap& src,\n                                           const Options& options);\n\n    ~SkJpegEncoder() override;\n\nprotected:\n    bool onEncodeRows(int numRows) override;\n\nprivate:\n    SkJpegEncoder(std::unique_ptr<SkJpegEncoderMgr>, const SkPixmap& src);\n\n    std::unique_ptr<SkJpegEncoderMgr> fEncoderMgr;\n    typedef SkEncoder INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/encode/SkPngEncoder.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPngEncoder_DEFINED\n#define SkPngEncoder_DEFINED\n\n#include \"SkEncoder.h\"\n#include \"SkDataTable.h\"\n\nclass SkPngEncoderMgr;\nclass SkWStream;\n\nclass SK_API SkPngEncoder : public SkEncoder {\npublic:\n\n    enum class FilterFlag : int {\n        kZero  = 0x00,\n        kNone  = 0x08,\n        kSub   = 0x10,\n        kUp    = 0x20,\n        kAvg   = 0x40,\n        kPaeth = 0x80,\n        kAll   = kNone | kSub | kUp | kAvg | kPaeth,\n    };\n\n    struct Options {\n        /**\n         *  Selects which filtering strategies to use.\n         *\n         *  If a single filter is chosen, libpng will use that filter for every row.\n         *\n         *  If multiple filters are chosen, libpng will use a heuristic to guess which filter\n         *  will encode smallest, then apply that filter.  This happens on a per row basis,\n         *  different rows can use different filters.\n         *\n         *  Using a single filter (or less filters) is typically faster.  Trying all of the\n         *  filters may help minimize the output file size.\n         *\n         *  Our default value matches libpng's default.\n         */\n        FilterFlag fFilterFlags = FilterFlag::kAll;\n\n        /**\n         *  Must be in [0, 9] where 9 corresponds to maximal compression.  This value is passed\n         *  directly to zlib.  0 is a special case to skip zlib entirely, creating dramatically\n         *  larger pngs.\n         *\n         *  Our default value matches libpng's default.\n         */\n        int fZLibLevel = 6;\n\n        /**\n         *  If the input is premultiplied, this controls the unpremultiplication behavior.\n         *  The encoder can convert to linear before unpremultiplying or ignore the transfer\n         *  function and unpremultiply the input as is.\n         */\n        SkTransferFunctionBehavior fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;\n\n        /**\n         *  Represents comments in the tEXt ancillary chunk of the png.\n         *  The 2i-th entry is the keyword for the i-th comment,\n         *  and the (2i + 1)-th entry is the text for the i-th comment.\n         */\n        sk_sp<SkDataTable> fComments;\n    };\n\n    /**\n     *  Encode the |src| pixels to the |dst| stream.\n     *  |options| may be used to control the encoding behavior.\n     *\n     *  Returns true on success.  Returns false on an invalid or unsupported |src|.\n     */\n    static bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);\n\n    /**\n     *  Create a png encoder that will encode the |src| pixels to the |dst| stream.\n     *  |options| may be used to control the encoding behavior.\n     *\n     *  |dst| is unowned but must remain valid for the lifetime of the object.\n     *\n     *  This returns nullptr on an invalid or unsupported |src|.\n     */\n    static std::unique_ptr<SkEncoder> Make(SkWStream* dst, const SkPixmap& src,\n                                           const Options& options);\n\n    ~SkPngEncoder() override;\n\nprotected:\n    bool onEncodeRows(int numRows) override;\n\n    SkPngEncoder(std::unique_ptr<SkPngEncoderMgr>, const SkPixmap& src);\n\n    std::unique_ptr<SkPngEncoderMgr> fEncoderMgr;\n    typedef SkEncoder INHERITED;\n};\n\nstatic inline SkPngEncoder::FilterFlag operator|(SkPngEncoder::FilterFlag x,\n                                                 SkPngEncoder::FilterFlag y) {\n    return (SkPngEncoder::FilterFlag)((int)x | (int)y);\n}\n\n#endif\n"
  },
  {
    "path": "include/encode/SkWebpEncoder.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkWebpEncoder_DEFINED\n#define SkWebpEncoder_DEFINED\n\n#include \"SkEncoder.h\"\n\nclass SkWStream;\n\nnamespace SkWebpEncoder {\n\n    enum class Compression {\n        kLossy,\n        kLossless,\n    };\n\n    struct SK_API Options {\n        /**\n         *  |fCompression| determines whether we will use webp lossy or lossless compression.\n         *\n         *  |fQuality| must be in [0.0f, 100.0f].\n         *  If |fCompression| is kLossy, |fQuality| corresponds to the visual quality of the\n         *  encoding.  Decreasing the quality will result in a smaller encoded image.\n         *  If |fCompression| is kLossless, |fQuality| corresponds to the amount of effort\n         *  put into the encoding.  Lower values will compress faster into larger files,\n         *  while larger values will compress slower into smaller files.\n         *\n         *  This scheme is designed to match the libwebp API.\n         */\n        Compression fCompression = Compression::kLossy;\n        float fQuality = 100.0f;\n\n        /**\n         *  If the input is premultiplied, this controls the unpremultiplication behavior.\n         *  The encoder can convert to linear before unpremultiplying or ignore the transfer\n         *  function and unpremultiply the input as is.\n         */\n        SkTransferFunctionBehavior fUnpremulBehavior = SkTransferFunctionBehavior::kRespect;\n    };\n\n    /**\n     *  Encode the |src| pixels to the |dst| stream.\n     *  |options| may be used to control the encoding behavior.\n     *\n     *  Returns true on success.  Returns false on an invalid or unsupported |src|.\n     */\n    SK_API bool Encode(SkWStream* dst, const SkPixmap& src, const Options& options);\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrBackendSemaphore.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrBackendSemaphore_DEFINED\n#define GrBackendSemaphore_DEFINED\n\n#include \"GrTypes.h\"\n\n#include \"gl/GrGLTypes.h\"\n\n#ifdef SK_VULKAN\n#include \"vk/GrVkTypes.h\"\n#endif\n\n/**\n * Wrapper class for passing into and receiving data from Ganesh about a backend semaphore object.\n */\nclass GrBackendSemaphore {\npublic:\n    // For convenience we just set the backend here to OpenGL. The GrBackendSemaphore cannot be used\n    // until either initGL or initVulkan are called which will set the appropriate GrBackend.\n    GrBackendSemaphore() : fBackend(kOpenGL_GrBackend), fGLSync(0), fIsInitialized(false) {}\n\n    void initGL(GrGLsync sync) {\n        fBackend = kOpenGL_GrBackend;\n        fGLSync = sync;\n        fIsInitialized = true;\n    }\n\n#ifdef SK_VULKAN\n    void initVulkan(VkSemaphore semaphore) {\n        fBackend = kVulkan_GrBackend;\n        fVkSemaphore = semaphore;\n        fIsInitialized = true;\n    }\n#endif\n\n    bool isInitialized() const { return fIsInitialized; }\n\n    GrGLsync glSync() const {\n        if (!fIsInitialized || kOpenGL_GrBackend != fBackend) {\n            return 0;\n        }\n        return fGLSync;\n    }\n\n#ifdef SK_VULKAN\n    VkSemaphore vkSemaphore() const {\n        if (!fIsInitialized || kVulkan_GrBackend != fBackend) {\n            return VK_NULL_HANDLE;\n        }\n        return fVkSemaphore;\n    }\n#endif\n\nprivate:\n    GrBackend fBackend;\n    union {\n        GrGLsync    fGLSync;\n#ifdef SK_VULKAN\n        VkSemaphore fVkSemaphore;\n#endif\n    };\n    bool fIsInitialized;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrBackendSurface.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrBackendSurface_DEFINED\n#define GrBackendSurface_DEFINED\n\n#include \"GrTypes.h\"\n#include \"gl/GrGLTypes.h\"\n#include \"mock/GrMockTypes.h\"\n\n#ifdef SK_VULKAN\n#include \"vk/GrVkTypes.h\"\n#include \"../private/GrVkTypesPriv.h\"\n\nclass GrVkImageLayout;\n#endif\n\n#if !SK_SUPPORT_GPU\n\n// SkSurface and SkImage rely on a minimal version of these always being available\nclass SK_API GrBackendTexture {\npublic:\n    GrBackendTexture() {}\n\n    bool isValid() const { return false; }\n};\n\nclass SK_API GrBackendRenderTarget {\npublic:\n    GrBackendRenderTarget() {}\n\n    bool isValid() const { return false; }\n};\n#else\n\nclass SK_API GrBackendFormat {\npublic:\n    // Creates an invalid backend format.\n    GrBackendFormat() : fValid(false) {}\n\n    static GrBackendFormat MakeGL(GrGLenum format, GrGLenum target) {\n        return GrBackendFormat(format, target);\n    }\n\n#ifdef SK_VULKAN\n    static GrBackendFormat MakeVk(VkFormat format) {\n        return GrBackendFormat(format);\n    }\n#endif\n\n    static GrBackendFormat MakeMock(GrPixelConfig config) {\n        return GrBackendFormat(config);\n    }\n\n    GrBackend backend() const {return fBackend; }\n\n    // If the backend API is GL, these return a pointer to the format and target. Otherwise\n    // it returns nullptr.\n    const GrGLenum* getGLFormat() const;\n    const GrGLenum* getGLTarget() const;\n\n#ifdef SK_VULKAN\n    // If the backend API is Vulkan, this returns a pointer to a VkFormat. Otherwise\n    // it returns nullptr\n    const VkFormat* getVkFormat() const;\n#endif\n\n    // If the backend API is Mock, this returns a pointer to a GrPixelConfig. Otherwise\n    // it returns nullptr.\n    const GrPixelConfig* getMockFormat() const;\n\n    // Returns true if the backend format has been initialized.\n    bool isValid() const { return fValid; }\n\nprivate:\n    GrBackendFormat(GrGLenum format, GrGLenum target);\n\n#ifdef SK_VULKAN\n    GrBackendFormat(const VkFormat vkFormat);\n#endif\n\n    GrBackendFormat(const GrPixelConfig config);\n\n    GrBackend fBackend;\n    bool      fValid;\n\n    union {\n        struct {\n            GrGLenum fTarget; // GL_TEXTURE_2D, GL_TEXTURE_EXTERNAL or GL_TEXTURE_RECTANGLE\n            GrGLenum fFormat; // the sized, internal format of the GL resource\n        } fGL;\n#ifdef SK_VULKAN\n        VkFormat      fVkFormat;\n#endif\n        GrPixelConfig fMockFormat;\n    };\n};\n\nclass SK_API GrBackendTexture {\npublic:\n    // Creates an invalid backend texture.\n    GrBackendTexture() : fIsValid(false) {}\n\n#if GR_TEST_UTILS\n    // GrGLTextureInfo::fFormat is ignored\n    // Deprecated: Should use version that does not take a GrPixelConfig instead\n    GrBackendTexture(int width,\n                     int height,\n                     GrPixelConfig config,\n                     const GrGLTextureInfo& glInfo);\n\n    // GrGLTextureInfo::fFormat is ignored\n    // Deprecated: Should use version that does not take a GrPixelConfig instead\n    GrBackendTexture(int width,\n                     int height,\n                     GrPixelConfig config,\n                     GrMipMapped,\n                     const GrGLTextureInfo& glInfo);\n#endif\n\n    // The GrGLTextureInfo must have a valid fFormat.\n    GrBackendTexture(int width,\n                     int height,\n                     GrMipMapped,\n                     const GrGLTextureInfo& glInfo);\n\n#ifdef SK_VULKAN\n    GrBackendTexture(int width,\n                     int height,\n                     const GrVkImageInfo& vkInfo);\n#endif\n\n    GrBackendTexture(int width,\n                     int height,\n                     GrMipMapped,\n                     const GrMockTextureInfo& mockInfo);\n\n    GrBackendTexture(const GrBackendTexture& that);\n\n    ~GrBackendTexture();\n\n    GrBackendTexture& operator=(const GrBackendTexture& that);\n\n    int width() const { return fWidth; }\n    int height() const { return fHeight; }\n    bool hasMipMaps() const { return GrMipMapped::kYes == fMipMapped; }\n    GrBackend backend() const {return fBackend; }\n\n    // If the backend API is GL, copies a snapshot of the GrGLTextureInfo struct into the passed in\n    // pointer and returns true. Otherwise returns false if the backend API is not GL.\n    bool getGLTextureInfo(GrGLTextureInfo*) const;\n\n#ifdef SK_VULKAN\n    // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed\n    // in pointer and returns true. This snapshot will set the fImageLayout to the current layout\n    // state. Otherwise returns false if the backend API is not Vulkan.\n    bool getVkImageInfo(GrVkImageInfo*) const;\n\n    // Anytime the client changes the VkImageLayout of the VkImage captured by this\n    // GrBackendTexture, they must call this function to notify Skia of the changed layout.\n    void setVkImageLayout(VkImageLayout);\n#endif\n\n    // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed\n    // in pointer and returns true. Otherwise returns false if the backend API is not Mock.\n    bool getMockTextureInfo(GrMockTextureInfo*) const;\n\n    // Returns true if the backend texture has been initialized.\n    bool isValid() const { return fIsValid; }\n\n    /**\n     * Create a GrBackendFormat object that matches this texture\n     */\n    GrBackendFormat format() const;\n\n#if GR_TEST_UTILS\n    GrPixelConfig testingOnly_getPixelConfig() const;\n    static bool TestingOnly_Equals(const GrBackendTexture& , const GrBackendTexture&);\n#endif\n\nprivate:\n    // Friending for access to the GrPixelConfig\n    friend class SkImage;\n    friend class SkImage_Gpu;\n    friend class SkSurface;\n    friend class GrBackendTextureImageGenerator;\n    friend class GrProxyProvider;\n    friend class GrGpu;\n    friend class GrGLGpu;\n    friend class GrVkGpu;\n    friend class PromiseImageHelper;\n\n    GrPixelConfig config() const { return fConfig; }\n\n#ifdef SK_VULKAN\n   // Requires friending of GrVkGpu (done above already)\n   sk_sp<GrVkImageLayout> getGrVkImageLayout() const;\n\n   friend class GrVkTexture;\n   GrBackendTexture(int width,\n                    int height,\n                    const GrVkImageInfo& vkInfo,\n                    sk_sp<GrVkImageLayout> layout);\n#endif\n\n    // Free and release and resources being held by the GrBackendTexture.\n    void cleanup();\n\n    bool fIsValid;\n    int fWidth;         //<! width in pixels\n    int fHeight;        //<! height in pixels\n    GrPixelConfig fConfig;\n    GrMipMapped fMipMapped;\n    GrBackend fBackend;\n\n    union {\n        GrGLTextureInfo fGLInfo;\n#ifdef SK_VULKAN\n        GrVkBackendSurfaceInfo fVkInfo;\n#endif\n        GrMockTextureInfo fMockInfo;\n    };\n};\n\nclass SK_API GrBackendRenderTarget {\npublic:\n    // Creates an invalid backend texture.\n    GrBackendRenderTarget() : fIsValid(false) {}\n\n#if GR_TEST_UTILS\n    // GrGLTextureInfo::fFormat is ignored\n    // Deprecated: Should use version that does not take a GrPixelConfig instead\n    GrBackendRenderTarget(int width,\n                          int height,\n                          int sampleCnt,\n                          int stencilBits,\n                          GrPixelConfig config,\n                          const GrGLFramebufferInfo& glInfo);\n#endif\n\n    // The GrGLTextureInfo must have a valid fFormat.\n    GrBackendRenderTarget(int width,\n                          int height,\n                          int sampleCnt,\n                          int stencilBits,\n                          const GrGLFramebufferInfo& glInfo);\n\n#ifdef SK_VULKAN\n    /** Deprecated, use version that does not take stencil bits. */\n    GrBackendRenderTarget(int width,\n                          int height,\n                          int sampleCnt,\n                          int stencilBits,\n                          const GrVkImageInfo& vkInfo);\n    GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo);\n#endif\n\n    GrBackendRenderTarget(int width,\n                          int height,\n                          int sampleCnt,\n                          int stencilBits,\n                          const GrMockRenderTargetInfo& mockInfo);\n\n    ~GrBackendRenderTarget();\n\n    GrBackendRenderTarget(const GrBackendRenderTarget& that);\n    GrBackendRenderTarget& operator=(const GrBackendRenderTarget&);\n\n    int width() const { return fWidth; }\n    int height() const { return fHeight; }\n    int sampleCnt() const { return fSampleCnt; }\n    int stencilBits() const { return fStencilBits; }\n    GrBackend backend() const {return fBackend; }\n\n    // If the backend API is GL, copies a snapshot of the GrGLFramebufferInfo struct into the passed\n    // in pointer and returns true. Otherwise returns false if the backend API is not GL.\n    bool getGLFramebufferInfo(GrGLFramebufferInfo*) const;\n\n#ifdef SK_VULKAN\n    // If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed\n    // in pointer and returns true. This snapshot will set the fImageLayout to the current layout\n    // state. Otherwise returns false if the backend API is not Vulkan.\n    bool getVkImageInfo(GrVkImageInfo*) const;\n\n    // Anytime the client changes the VkImageLayout of the VkImage captured by this\n    // GrBackendRenderTarget, they must call this function to notify Skia of the changed layout.\n    void setVkImageLayout(VkImageLayout);\n#endif\n\n    // If the backend API is Mock, copies a snapshot of the GrMockTextureInfo struct into the passed\n    // in pointer and returns true. Otherwise returns false if the backend API is not Mock.\n    bool getMockRenderTargetInfo(GrMockRenderTargetInfo*) const;\n\n    // Returns true if the backend texture has been initialized.\n    bool isValid() const { return fIsValid; }\n\n\n#if GR_TEST_UTILS\n    GrPixelConfig testingOnly_getPixelConfig() const;\n    static bool TestingOnly_Equals(const GrBackendRenderTarget&, const GrBackendRenderTarget&);\n#endif\n\nprivate:\n    // Friending for access to the GrPixelConfig\n    friend class SkSurface;\n    friend class SkSurface_Gpu;\n    friend class SkImage_Gpu;\n    friend class GrGpu;\n    friend class GrGLGpu;\n    friend class GrProxyProvider;\n    friend class GrVkGpu;\n    GrPixelConfig config() const { return fConfig; }\n\n#ifdef SK_VULKAN\n   // Requires friending of GrVkGpu (done above already)\n   sk_sp<GrVkImageLayout> getGrVkImageLayout() const;\n\n   friend class GrVkRenderTarget;\n   GrBackendRenderTarget(int width, int height, int sampleCnt, const GrVkImageInfo& vkInfo,\n                         sk_sp<GrVkImageLayout> layout);\n#endif\n\n    // Free and release and resources being held by the GrBackendTexture.\n    void cleanup();\n\n    bool fIsValid;\n    int fWidth;         //<! width in pixels\n    int fHeight;        //<! height in pixels\n\n    int fSampleCnt;\n    int fStencilBits;\n    GrPixelConfig fConfig;\n\n    GrBackend fBackend;\n\n    union {\n        GrGLFramebufferInfo fGLInfo;\n#ifdef SK_VULKAN\n        GrVkBackendSurfaceInfo fVkInfo;\n#endif\n        GrMockRenderTargetInfo fMockInfo;\n    };\n};\n\n#endif\n\n#endif\n\n"
  },
  {
    "path": "include/gpu/GrBlend.h",
    "content": "\n/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrBlend_DEFINED\n#define GrBlend_DEFINED\n\n#include \"GrTypes.h\"\n#include \"../private/SkTLogic.h\"\n\n/**\n * Equations for alpha-blending.\n */\nenum GrBlendEquation {\n    // Basic blend equations.\n    kAdd_GrBlendEquation,             //<! Cs*S + Cd*D\n    kSubtract_GrBlendEquation,        //<! Cs*S - Cd*D\n    kReverseSubtract_GrBlendEquation, //<! Cd*D - Cs*S\n\n    // Advanced blend equations. These are described in the SVG and PDF specs.\n    kScreen_GrBlendEquation,\n    kOverlay_GrBlendEquation,\n    kDarken_GrBlendEquation,\n    kLighten_GrBlendEquation,\n    kColorDodge_GrBlendEquation,\n    kColorBurn_GrBlendEquation,\n    kHardLight_GrBlendEquation,\n    kSoftLight_GrBlendEquation,\n    kDifference_GrBlendEquation,\n    kExclusion_GrBlendEquation,\n    kMultiply_GrBlendEquation,\n    kHSLHue_GrBlendEquation,\n    kHSLSaturation_GrBlendEquation,\n    kHSLColor_GrBlendEquation,\n    kHSLLuminosity_GrBlendEquation,\n\n    kFirstAdvancedGrBlendEquation = kScreen_GrBlendEquation,\n    kLast_GrBlendEquation = kHSLLuminosity_GrBlendEquation\n};\n\nstatic const int kGrBlendEquationCnt = kLast_GrBlendEquation + 1;\n\n\n/**\n * Coefficients for alpha-blending.\n */\nenum GrBlendCoeff {\n    kZero_GrBlendCoeff,    //<! 0\n    kOne_GrBlendCoeff,     //<! 1\n    kSC_GrBlendCoeff,      //<! src color\n    kISC_GrBlendCoeff,     //<! one minus src color\n    kDC_GrBlendCoeff,      //<! dst color\n    kIDC_GrBlendCoeff,     //<! one minus dst color\n    kSA_GrBlendCoeff,      //<! src alpha\n    kISA_GrBlendCoeff,     //<! one minus src alpha\n    kDA_GrBlendCoeff,      //<! dst alpha\n    kIDA_GrBlendCoeff,     //<! one minus dst alpha\n    kConstC_GrBlendCoeff,  //<! constant color\n    kIConstC_GrBlendCoeff, //<! one minus constant color\n    kConstA_GrBlendCoeff,  //<! constant color alpha\n    kIConstA_GrBlendCoeff, //<! one minus constant color alpha\n    kS2C_GrBlendCoeff,\n    kIS2C_GrBlendCoeff,\n    kS2A_GrBlendCoeff,\n    kIS2A_GrBlendCoeff,\n\n    kLast_GrBlendCoeff = kIS2A_GrBlendCoeff\n};\n\nstatic const int kGrBlendCoeffCnt = kLast_GrBlendCoeff + 1;\n\nstatic constexpr bool GrBlendCoeffRefsSrc(const GrBlendCoeff coeff) {\n    return kSC_GrBlendCoeff == coeff || kISC_GrBlendCoeff == coeff || kSA_GrBlendCoeff == coeff ||\n           kISA_GrBlendCoeff == coeff;\n}\n\nstatic constexpr bool GrBlendCoeffRefsDst(const GrBlendCoeff coeff) {\n    return kDC_GrBlendCoeff == coeff || kIDC_GrBlendCoeff == coeff || kDA_GrBlendCoeff == coeff ||\n           kIDA_GrBlendCoeff == coeff;\n}\n\nstatic constexpr bool GrBlendCoeffRefsSrc2(const GrBlendCoeff coeff) {\n    return kS2C_GrBlendCoeff == coeff || kIS2C_GrBlendCoeff == coeff ||\n           kS2A_GrBlendCoeff == coeff || kIS2A_GrBlendCoeff == coeff;\n}\n\nstatic constexpr bool GrBlendCoeffsUseSrcColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {\n    return kZero_GrBlendCoeff != srcCoeff || GrBlendCoeffRefsSrc(dstCoeff);\n}\n\nstatic constexpr bool GrBlendCoeffsUseDstColor(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {\n    return GrBlendCoeffRefsDst(srcCoeff) || kZero_GrBlendCoeff != dstCoeff;\n}\n\nstatic constexpr bool GrBlendEquationIsAdvanced(GrBlendEquation equation) {\n    return equation >= kFirstAdvancedGrBlendEquation;\n}\n\nstatic constexpr bool GrBlendModifiesDst(GrBlendEquation equation, GrBlendCoeff srcCoeff,\n                                         GrBlendCoeff dstCoeff) {\n    return (kAdd_GrBlendEquation != equation && kReverseSubtract_GrBlendEquation != equation) ||\n           kZero_GrBlendCoeff != srcCoeff || kOne_GrBlendCoeff != dstCoeff;\n}\n\n/**\n * Advanced blend equations can always tweak alpha for coverage. (See GrCustomXfermode.cpp)\n *\n * For \"add\" and \"reverse subtract\" the blend equation with f=coverage is:\n *\n *   D' = f * (S * srcCoeff + D * dstCoeff) + (1-f) * D\n *      = f * S * srcCoeff + D * (f * dstCoeff + (1 - f))\n *\n * (Let srcCoeff be negative for reverse subtract.) We can tweak alpha for coverage when the\n * following relationship holds:\n *\n *   (f*S) * srcCoeff' + D * dstCoeff' == f * S * srcCoeff + D * (f * dstCoeff + (1 - f))\n *\n * (Where srcCoeff' and dstCoeff' have any reference to S pre-multiplied by f.)\n *\n * It's easy to see this works for the src term as long as srcCoeff' == srcCoeff (meaning srcCoeff\n * does not reference S). For the dst term, this will work as long as the following is true:\n *|\n *   dstCoeff' == f * dstCoeff + (1 - f)\n *   dstCoeff' == 1 - f * (1 - dstCoeff)\n *\n * By inspection we can see this will work as long as dstCoeff has a 1, and any other term in\n * dstCoeff references S.\n *\n * Moreover, if the blend doesn't modify the dst at all then it is ok to arbitrarily modify the src\n * color so folding in coverage is allowed.\n */\nstatic constexpr bool GrBlendAllowsCoverageAsAlpha(GrBlendEquation equation,\n                                                   GrBlendCoeff srcCoeff,\n                                                   GrBlendCoeff dstCoeff) {\n    return GrBlendEquationIsAdvanced(equation) ||\n           !GrBlendModifiesDst(equation, srcCoeff, dstCoeff) ||\n           ((kAdd_GrBlendEquation == equation || kReverseSubtract_GrBlendEquation == equation) &&\n            !GrBlendCoeffRefsSrc(srcCoeff) &&\n            (kOne_GrBlendCoeff == dstCoeff || kISC_GrBlendCoeff == dstCoeff ||\n             kISA_GrBlendCoeff == dstCoeff));\n}\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrConfig.h",
    "content": "\n/*\n * Copyright 2010 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n\n#ifndef GrConfig_DEFINED\n#define GrConfig_DEFINED\n\n#include \"SkTypes.h\"\n\n///////////////////////////////////////////////////////////////////////////////\n// preconfig section:\n//\n// All the work before including GrUserConfig.h should center around guessing\n// what platform we're on, and defining low-level symbols based on that.\n//\n// A build environment may have already defined symbols, so we first check\n// for that\n//\n\n// hack to ensure we know what sort of Apple platform we're on\n#if defined(__APPLE_CPP__) || defined(__APPLE_CC__)\n    #include <TargetConditionals.h>\n#endif\n\n/**\n *  Gr defines are set to 0 or 1, rather than being undefined or defined\n */\n\n#if !defined(GR_CACHE_STATS)\n  #if defined(SK_DEBUG) || defined(SK_DUMP_STATS)\n      #define GR_CACHE_STATS  1\n  #else\n      #define GR_CACHE_STATS  0\n  #endif\n#endif\n\n#if !defined(GR_GPU_STATS)\n  #if defined(SK_DEBUG) || defined(SK_DUMP_STATS)\n      #define GR_GPU_STATS    1\n  #else\n      #define GR_GPU_STATS    0\n  #endif\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n\n#if defined(SK_BUILD_FOR_WIN)\n// VC8 doesn't support stdint.h, so we define those types here.\ntypedef signed char int8_t;\ntypedef unsigned char uint8_t;\ntypedef short int16_t;\ntypedef unsigned short uint16_t;\ntypedef int int32_t;\ntypedef unsigned uint32_t;\ntypedef __int64 int64_t;\ntypedef unsigned __int64 uint64_t;\n#else\n/*\n *  Include stdint.h with defines that trigger declaration of C99 limit/const\n *  macros here before anyone else has a chance to include stdint.h without\n *  these.\n */\n#ifndef __STDC_LIMIT_MACROS\n#define __STDC_LIMIT_MACROS\n#endif\n#ifndef __STDC_CONSTANT_MACROS\n#define __STDC_CONSTANT_MACROS\n#endif\n#include <stdint.h>\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n///////////////////////////////////////////////////////////////////////////////\n// postconfig section:\n//\n\n/**\n *  GR_STRING makes a string of X where X is expanded before conversion to a string\n *  if X itself contains macros.\n */\n#define GR_STRING(X) GR_STRING_IMPL(X)\n#define GR_STRING_IMPL(X) #X\n\n/**\n *  GR_CONCAT concatenates X and Y  where each is expanded before\n *  contanenation if either contains macros.\n */\n#define GR_CONCAT(X,Y) GR_CONCAT_IMPL(X,Y)\n#define GR_CONCAT_IMPL(X,Y) X##Y\n\n/**\n *  Creates a string of the form \"<filename>(<linenumber>) : \"\n */\n#define GR_FILE_AND_LINE_STR __FILE__ \"(\" GR_STRING(__LINE__) \") : \"\n\n/**\n *  Compilers have different ways of issuing warnings. This macro\n *  attempts to abstract them, but may need to be specialized for your\n *  particular compiler.\n *  To insert compiler warnings use \"#pragma message GR_WARN(<string>)\"\n */\n#if defined(_MSC_VER)\n    #define GR_WARN(MSG) (GR_FILE_AND_LINE_STR \"WARNING: \" MSG)\n#else//__GNUC__ - may need other defines for different compilers\n    #define GR_WARN(MSG) (\"WARNING: \" MSG)\n#endif\n\n/**\n *  GR_ALWAYSBREAK is an unconditional break in all builds.\n */\n#if !defined(GR_ALWAYSBREAK)\n    #if     defined(SK_BUILD_FOR_WIN)\n        #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); __debugbreak()\n    #else\n        // TODO: do other platforms really not have continuable breakpoints?\n        // sign extend for 64bit architectures to be sure this is\n        // in the high address range\n        #define GR_ALWAYSBREAK SkNO_RETURN_HINT(); *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;\n    #endif\n#endif\n\n/**\n *  GR_DEBUGBREAK is an unconditional break in debug builds.\n */\n#if !defined(GR_DEBUGBREAK)\n    #ifdef SK_DEBUG\n        #define GR_DEBUGBREAK GR_ALWAYSBREAK\n    #else\n        #define GR_DEBUGBREAK\n    #endif\n#endif\n\n/**\n *  GR_ALWAYSASSERT is an assertion in all builds.\n */\n#if !defined(GR_ALWAYSASSERT)\n    #define GR_ALWAYSASSERT(COND)                                        \\\n        do {                                                             \\\n            if (!(COND)) {                                               \\\n                SkDebugf(\"%s %s failed\\n\", GR_FILE_AND_LINE_STR, #COND); \\\n                GR_ALWAYSBREAK;                                          \\\n            }                                                            \\\n        } while (false)\n#endif\n\n/**\n *  GR_DEBUGASSERT is an assertion in debug builds only.\n */\n#if !defined(GR_DEBUGASSERT)\n    #ifdef SK_DEBUG\n        #define GR_DEBUGASSERT(COND) GR_ALWAYSASSERT(COND)\n    #else\n        #define GR_DEBUGASSERT(COND)\n    #endif\n#endif\n\n/**\n *  Prettier forms of the above macros.\n */\n#define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND)\n\n/**\n *  GR_STATIC_ASSERT is a compile time assertion. Depending on the platform\n *  it may print the message in the compiler log. Obviously, the condition must\n *  be evaluatable at compile time.\n */\n#define GR_STATIC_ASSERT(CONDITION) static_assert(CONDITION, \"bug\")\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrContext.h",
    "content": "/*\n * Copyright 2010 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrContext_DEFINED\n#define GrContext_DEFINED\n\n#include \"SkMatrix.h\"\n#include \"SkPathEffect.h\"\n#include \"SkTypes.h\"\n#include \"../private/GrAuditTrail.h\"\n#include \"../private/GrSingleOwner.h\"\n#include \"GrContextOptions.h\"\n\n// We shouldn't need this but currently Android is relying on this being include transitively.\n#include \"SkUnPreMultiply.h\"\n\nclass GrAtlasManager;\nclass GrBackendFormat;\nclass GrBackendSemaphore;\nclass GrCaps;\nclass GrContextPriv;\nclass GrContextThreadSafeProxy;\nclass GrContextThreadSafeProxyPriv;\nclass GrDrawingManager;\nstruct GrDrawOpAtlasConfig;\nclass GrFragmentProcessor;\nstruct GrGLInterface;\nclass GrGlyphCache;\nclass GrGpu;\nclass GrIndexBuffer;\nstruct GrMockOptions;\nclass GrOvalRenderer;\nclass GrPath;\nclass GrProxyProvider;\nclass GrRenderTargetContext;\nclass GrResourceEntry;\nclass GrResourceCache;\nclass GrResourceProvider;\nclass GrSamplerState;\nclass GrSurfaceProxy;\nclass GrSwizzle;\nclass GrTextBlobCache;\nclass GrTextContext;\nclass GrTextureProxy;\nclass GrTextureStripAtlasManager;\nclass GrVertexBuffer;\nstruct GrVkBackendContext;\n\nclass SkImage;\nclass SkSurfaceCharacterization;\nclass SkSurfaceProps;\nclass SkTaskGroup;\nclass SkTraceMemoryDump;\n\nclass SK_API GrContext : public SkRefCnt {\npublic:\n    /**\n     * Creates a GrContext for a backend context. If no GrGLInterface is provided then the result of\n     * GrGLMakeNativeInterface() is used if it succeeds.\n     */\n    static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>, const GrContextOptions&);\n    static sk_sp<GrContext> MakeGL(sk_sp<const GrGLInterface>);\n    static sk_sp<GrContext> MakeGL(const GrContextOptions&);\n    static sk_sp<GrContext> MakeGL();\n\n#ifdef SK_VULKAN\n    static sk_sp<GrContext> MakeVulkan(sk_sp<const GrVkBackendContext>, const GrContextOptions&);\n    static sk_sp<GrContext> MakeVulkan(sk_sp<const GrVkBackendContext>);\n#endif\n\n#ifdef SK_METAL\n    /**\n     * Makes a GrContext which uses Metal as the backend. The device parameter is an MTLDevice\n     * and queue is an MTLCommandQueue which should be used by the backend. These objects must\n     * have a ref on them which can be transferred to Ganesh which will release the ref when the\n     * GrContext is destroyed.\n     */\n    static sk_sp<GrContext> MakeMetal(void* device, void* queue, const GrContextOptions& options);\n    static sk_sp<GrContext> MakeMetal(void* device, void* queue);\n#endif\n\n    static sk_sp<GrContext> MakeMock(const GrMockOptions*, const GrContextOptions&);\n    static sk_sp<GrContext> MakeMock(const GrMockOptions*);\n\n    virtual ~GrContext();\n\n    sk_sp<GrContextThreadSafeProxy> threadSafeProxy();\n\n    /**\n     * The GrContext normally assumes that no outsider is setting state\n     * within the underlying 3D API's context/device/whatever. This call informs\n     * the context that the state was modified and it should resend. Shouldn't\n     * be called frequently for good performance.\n     * The flag bits, state, is dpendent on which backend is used by the\n     * context, either GL or D3D (possible in future).\n     */\n    void resetContext(uint32_t state = kAll_GrBackendState);\n\n    /**\n     * Abandons all GPU resources and assumes the underlying backend 3D API context is no longer\n     * usable. Call this if you have lost the associated GPU context, and thus internal texture,\n     * buffer, etc. references/IDs are now invalid. Calling this ensures that the destructors of the\n     * GrContext and any of its created resource objects will not make backend 3D API calls. Content\n     * rendered but not previously flushed may be lost. After this function is called all subsequent\n     * calls on the GrContext will fail or be no-ops.\n     *\n     * The typical use case for this function is that the underlying 3D context was lost and further\n     * API calls may crash.\n     */\n    virtual void abandonContext();\n\n    /**\n     * This is similar to abandonContext() however the underlying 3D context is not yet lost and\n     * the GrContext will cleanup all allocated resources before returning. After returning it will\n     * assume that the underlying context may no longer be valid.\n     *\n     * The typical use case for this function is that the client is going to destroy the 3D context\n     * but can't guarantee that GrContext will be destroyed first (perhaps because it may be ref'ed\n     * elsewhere by either the client or Skia objects).\n     */\n    virtual void releaseResourcesAndAbandonContext();\n\n    ///////////////////////////////////////////////////////////////////////////\n    // Resource Cache\n\n    /**\n     *  Return the current GPU resource cache limits.\n     *\n     *  @param maxResources If non-null, returns maximum number of resources that\n     *                      can be held in the cache.\n     *  @param maxResourceBytes If non-null, returns maximum number of bytes of\n     *                          video memory that can be held in the cache.\n     */\n    void getResourceCacheLimits(int* maxResources, size_t* maxResourceBytes) const;\n\n    /**\n     *  Gets the current GPU resource cache usage.\n     *\n     *  @param resourceCount If non-null, returns the number of resources that are held in the\n     *                       cache.\n     *  @param maxResourceBytes If non-null, returns the total number of bytes of video memory held\n     *                          in the cache.\n     */\n    void getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const;\n\n    /**\n     *  Gets the number of bytes in the cache consumed by purgeable (e.g. unlocked) resources.\n     */\n    size_t getResourceCachePurgeableBytes() const;\n\n    /**\n     *  Specify the GPU resource cache limits. If the current cache exceeds either\n     *  of these, it will be purged (LRU) to keep the cache within these limits.\n     *\n     *  @param maxResources The maximum number of resources that can be held in\n     *                      the cache.\n     *  @param maxResourceBytes The maximum number of bytes of video memory\n     *                          that can be held in the cache.\n     */\n    void setResourceCacheLimits(int maxResources, size_t maxResourceBytes);\n\n    /**\n     * Frees GPU created by the context. Can be called to reduce GPU memory\n     * pressure.\n     */\n    virtual void freeGpuResources();\n\n    /**\n     * Purge GPU resources that haven't been used in the past 'msNotUsed' milliseconds or are\n     * otherwise marked for deletion, regardless of whether the context is under budget.\n     */\n    void performDeferredCleanup(std::chrono::milliseconds msNotUsed);\n\n    // Temporary compatibility API for Android.\n    void purgeResourcesNotUsedInMs(std::chrono::milliseconds msNotUsed) {\n        this->performDeferredCleanup(msNotUsed);\n    }\n\n    /**\n     * Purge unlocked resources from the cache until the the provided byte count has been reached\n     * or we have purged all unlocked resources. The default policy is to purge in LRU order, but\n     * can be overridden to prefer purging scratch resources (in LRU order) prior to purging other\n     * resource types.\n     *\n     * @param maxBytesToPurge the desired number of bytes to be purged.\n     * @param preferScratchResources If true scratch resources will be purged prior to other\n     *                               resource types.\n     */\n    void purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources);\n\n    /**\n     * This entry point is intended for instances where an app has been backgrounded or\n     * suspended.\n     * If 'scratchResourcesOnly' is true all unlocked scratch resources will be purged but the\n     * unlocked resources with persistent data will remain. If 'scratchResourcesOnly' is false\n     * then all unlocked resources will be purged.\n     * In either case, after the unlocked resources are purged a separate pass will be made to\n     * ensure that resource usage is under budget (i.e., even if 'scratchResourcesOnly' is true\n     * some resources with persistent data may be purged to be under budget).\n     *\n     * @param scratchResourcesOnly   If true only unlocked scratch resources will be purged prior\n     *                               enforcing the budget requirements.\n     */\n    void purgeUnlockedResources(bool scratchResourcesOnly);\n\n    /**\n     * Gets the maximum supported texture size.\n     */\n    int maxTextureSize() const;\n\n    /**\n     * Gets the maximum supported render target size.\n     */\n    int maxRenderTargetSize() const;\n\n    /**\n     * Can a SkImage be created with the given color type.\n     */\n    bool colorTypeSupportedAsImage(SkColorType) const;\n\n    /**\n     * Can a SkSurface be created with the given color type. To check whether MSAA is supported\n     * use maxSurfaceSampleCountForColorType().\n     */\n    bool colorTypeSupportedAsSurface(SkColorType colorType) const {\n        return this->maxSurfaceSampleCountForColorType(colorType) > 0;\n    }\n\n    /**\n     * Gets the maximum supported sample count for a color type. 1 is returned if only non-MSAA\n     * rendering is supported for the color type. 0 is returned if rendering to this color type\n     * is not supported at all.\n     */\n    int maxSurfaceSampleCountForColorType(SkColorType) const;\n\n    ///////////////////////////////////////////////////////////////////////////\n    // Misc.\n\n    /**\n     * Call to ensure all drawing to the context has been issued to the underlying 3D API.\n     */\n    void flush();\n\n    /**\n     * Call to ensure all drawing to the context has been issued to the underlying 3D API. After\n     * issuing all commands, numSemaphore semaphores will be signaled by the gpu. The client passes\n     * in an array of numSemaphores GrBackendSemaphores. In general these GrBackendSemaphore's can\n     * be either initialized or not. If they are initialized, the backend uses the passed in\n     * semaphore. If it is not initialized, a new semaphore is created and the GrBackendSemaphore\n     * object is initialized with that semaphore.\n     *\n     * The client will own and be responsible for deleting the underlying semaphores that are stored\n     * and returned in initialized GrBackendSemaphore objects. The GrBackendSemaphore objects\n     * themselves can be deleted as soon as this function returns.\n     *\n     * If the backend API is OpenGL only uninitialized GrBackendSemaphores are supported.\n     * If the backend API is Vulkan either initialized or unitialized semaphores are supported.\n     * If unitialized, the semaphores which are created will be valid for use only with the VkDevice\n     * with which they were created.\n     *\n     * If this call returns GrSemaphoresSubmited::kNo, the GPU backend will not have created or\n     * added any semaphores to signal on the GPU. Thus the client should not have the GPU wait on\n     * any of the semaphores. However, any pending commands to the context will still be flushed.\n     */\n    GrSemaphoresSubmitted flushAndSignalSemaphores(int numSemaphores,\n                                                   GrBackendSemaphore signalSemaphores[]);\n\n    /**\n     * An ID associated with this context, guaranteed to be unique.\n     */\n    uint32_t uniqueID() { return fUniqueID; }\n\n    // Provides access to functions that aren't part of the public API.\n    GrContextPriv contextPriv();\n    const GrContextPriv contextPriv() const;\n\n    /** Enumerates all cached GPU resources and dumps their memory to traceMemoryDump. */\n    // Chrome is using this!\n    void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;\n\n    bool supportsDistanceFieldText() const;\n\nprotected:\n    GrContext(GrBackend, int32_t id = SK_InvalidGenID);\n\n    bool initCommon(const GrContextOptions&);\n    virtual bool init(const GrContextOptions&) = 0; // must be called after the ctor!\n\n    virtual GrAtlasManager* onGetAtlasManager() = 0;\n\n    const GrBackend                         fBackend;\n    sk_sp<const GrCaps>                     fCaps;\n    sk_sp<GrContextThreadSafeProxy>         fThreadSafeProxy;\n\nprivate:\n    sk_sp<GrGpu>                            fGpu;\n    GrResourceCache*                        fResourceCache;\n    GrResourceProvider*                     fResourceProvider;\n    GrProxyProvider*                        fProxyProvider;\n    std::unique_ptr<GrTextureStripAtlasManager> fTextureStripAtlasManager;\n\n\n    GrGlyphCache*                           fGlyphCache;\n    std::unique_ptr<GrTextBlobCache>        fTextBlobCache;\n\n    bool                                    fDisableGpuYUVConversion;\n    bool                                    fSharpenMipmappedTextures;\n    bool                                    fDidTestPMConversions;\n    // true if the PM/UPM conversion succeeded; false otherwise\n    bool                                    fPMUPMConversionsRoundTrip;\n\n    // In debug builds we guard against improper thread handling\n    // This guard is passed to the GrDrawingManager and, from there to all the\n    // GrRenderTargetContexts.  It is also passed to the GrResourceProvider and SkGpuDevice.\n    mutable GrSingleOwner                   fSingleOwner;\n\n    std::unique_ptr<SkTaskGroup>            fTaskGroup;\n\n    const uint32_t                          fUniqueID;\n\n    std::unique_ptr<GrDrawingManager>       fDrawingManager;\n\n    GrAuditTrail                            fAuditTrail;\n\n    GrContextOptions::PersistentCache*      fPersistentCache;\n\n    // TODO: have the GrClipStackClip use renderTargetContexts and rm this friending\n    friend class GrContextPriv;\n\n    /**\n     * These functions create premul <-> unpremul effects. If the second argument is 'true', they\n     * use the specialized round-trip effects from GrConfigConversionEffect, otherwise they\n     * create effects that do naive multiply or divide.\n     */\n    std::unique_ptr<GrFragmentProcessor> createPMToUPMEffect(std::unique_ptr<GrFragmentProcessor>,\n                                                             bool useConfigConversionEffect);\n    std::unique_ptr<GrFragmentProcessor> createUPMToPMEffect(std::unique_ptr<GrFragmentProcessor>,\n                                                             bool useConfigConversionEffect);\n\n    /**\n     * Returns true if createPMtoUPMEffect and createUPMToPMEffect will succeed for non-sRGB 8888\n     * configs. In other words, did we find a pair of round-trip preserving conversion effects?\n     */\n    bool validPMUPMConversionExists();\n\n    /**\n     * A callback similar to the above for use by the TextBlobCache\n     * TODO move textblob draw calls below context so we can use the call above.\n     */\n    static void TextBlobCacheOverBudgetCB(void* data);\n\n    typedef SkRefCnt INHERITED;\n};\n\n/**\n * Can be used to perform actions related to the generating GrContext in a thread safe manner. The\n * proxy does not access the 3D API (e.g. OpenGL) that backs the generating GrContext.\n */\nclass SK_API GrContextThreadSafeProxy : public SkRefCnt {\npublic:\n    ~GrContextThreadSafeProxy();\n\n    bool matches(GrContext* context) const { return context->uniqueID() == fContextUniqueID; }\n\n    /**\n     *  Create a surface characterization for a DDL that will be replayed into the GrContext\n     *  that created this proxy. On failure the resulting characterization will be invalid (i.e.,\n     *  \"!c.isValid()\").\n     *\n     *  @param cacheMaxResourceBytes The max resource bytes limit that will be in effect when the\n     *                               DDL created with this characterization is replayed.\n     *                               Note: the contract here is that the DDL will be created as\n     *                               if it had a full 'cacheMaxResourceBytes' to use. If replayed\n     *                               into a GrContext that already has locked GPU memory, the\n     *                               replay can exceed the budget. To rephrase, all resource\n     *                               allocation decisions are made at record time and at playback\n     *                               time the budget limits will be ignored.\n     *  @param ii                    The image info specifying properties of the SkSurface that\n     *                               the DDL created with this characterization will be replayed\n     *                               into.\n     *                               Note: Ganesh doesn't make use of the SkImageInfo's alphaType\n     *  @param backendFormat         Information about the format of the GPU surface that will\n     *                               back the SkSurface upon replay\n     *  @param sampleCount           The sample count of the SkSurface that the DDL created with\n     *                               this characterization will be replayed into\n     *  @param origin                The origin of the SkSurface that the DDL created with this\n     *                               characterization will be replayed into\n     *  @param surfaceProps          The surface properties of the SkSurface that the DDL created\n     *                               with this characterization will be replayed into\n     *  @param isMipMapped           Will the surface the DDL will be replayed into have space\n     *                               allocated for mipmaps?\n     *  @param willUseGLFBO0         Will the surface the DDL will be replayed into be backed by GL\n     *                               FBO 0. This flag is only valid if using an GL backend.\n     */\n    SkSurfaceCharacterization createCharacterization(\n                                  size_t cacheMaxResourceBytes,\n                                  const SkImageInfo& ii, const GrBackendFormat& backendFormat,\n                                  int sampleCount, GrSurfaceOrigin origin,\n                                  const SkSurfaceProps& surfaceProps,\n                                  bool isMipMapped, bool willUseGLFBO0 = false);\n\n    bool operator==(const GrContextThreadSafeProxy& that) const {\n        // Each GrContext should only ever have a single thread-safe proxy.\n        SkASSERT((this == &that) == (fContextUniqueID == that.fContextUniqueID));\n        return this == &that;\n    }\n\n    bool operator!=(const GrContextThreadSafeProxy& that) const { return !(*this == that); }\n\n    // Provides access to functions that aren't part of the public API.\n    GrContextThreadSafeProxyPriv priv();\n    const GrContextThreadSafeProxyPriv priv() const;\n\nprivate:\n    // DDL TODO: need to add unit tests for backend & maybe options\n    GrContextThreadSafeProxy(sk_sp<const GrCaps> caps,\n                             uint32_t uniqueID,\n                             GrBackend backend,\n                             const GrContextOptions& options);\n\n    sk_sp<const GrCaps>    fCaps;\n    const uint32_t         fContextUniqueID;\n    const GrBackend        fBackend;\n    const GrContextOptions fOptions;\n\n    friend class GrDirectContext; // To construct this object\n    friend class GrContextThreadSafeProxyPriv;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrContextOptions.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrContextOptions_DEFINED\n#define GrContextOptions_DEFINED\n\n#include \"SkData.h\"\n#include \"SkTypes.h\"\n#include \"GrTypes.h\"\n#include \"../private/GrTypesPriv.h\"\n#include \"GrDriverBugWorkarounds.h\"\n\n#include <vector>\n\nclass SkExecutor;\n\n#if SK_SUPPORT_GPU\nstruct GrContextOptions {\n    enum class Enable {\n        /** Forces an option to be disabled. */\n        kNo,\n        /** Forces an option to be enabled. */\n        kYes,\n        /**\n         * Uses Skia's default behavior, which may use runtime properties (e.g. driver version).\n         */\n        kDefault\n    };\n\n    /**\n     * Abstract class which stores Skia data in a cache that persists between sessions. Currently,\n     * Skia stores compiled shader binaries (only when glProgramBinary / glGetProgramBinary are\n     * supported) when provided a persistent cache, but this may extend to other data in the future.\n     */\n    class PersistentCache {\n    public:\n        virtual ~PersistentCache() {}\n\n        /**\n         * Returns the data for the key if it exists in the cache, otherwise returns null.\n         */\n        virtual sk_sp<SkData> load(const SkData& key) = 0;\n\n        virtual void store(const SkData& key, const SkData& data) = 0;\n    };\n\n    GrContextOptions() {}\n\n    // Suppress prints for the GrContext.\n    bool fSuppressPrints = false;\n\n    /** Overrides: These options override feature detection using backend API queries. These\n        overrides can only reduce the feature set or limits, never increase them beyond the\n        detected values. */\n\n    int  fMaxTextureSizeOverride = SK_MaxS32;\n\n    /** the threshold in bytes above which we will use a buffer mapping API to map vertex and index\n        buffers to CPU memory in order to update them.  A value of -1 means the GrContext should\n        deduce the optimal value for this platform. */\n    int  fBufferMapThreshold = -1;\n\n    /**\n     * Executor to handle threaded work within Ganesh. If this is nullptr, then all work will be\n     * done serially on the main thread. To have worker threads assist with various tasks, set this\n     * to a valid SkExecutor instance. Currently, used for software path rendering, but may be used\n     * for other tasks.\n     */\n    SkExecutor* fExecutor = nullptr;\n\n    /** Construct mipmaps manually, via repeated downsampling draw-calls. This is used when\n        the driver's implementation (glGenerateMipmap) contains bugs. This requires mipmap\n        level and LOD control (ie desktop or ES3). */\n    bool fDoManualMipmapping = false;\n\n    /**\n     * Disables distance field rendering for paths. Distance field computation can be expensive,\n     * and yields no benefit if a path is not rendered multiple times with different transforms.\n     */\n    bool fDisableDistanceFieldPaths = false;\n\n    /**\n     * If true this allows path mask textures to be cached. This is only really useful if paths\n     * are commonly rendered at the same scale and fractional translation.\n     */\n    bool fAllowPathMaskCaching = true;\n\n    /**\n     * If true, the GPU will not be used to perform YUV -> RGB conversion when generating\n     * textures from codec-backed images.\n     */\n    bool fDisableGpuYUVConversion = false;\n\n    /**\n     * The maximum size of cache textures used for Skia's Glyph cache.\n     */\n    float fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4;\n\n    /**\n     * Below this threshold size in device space distance field fonts won't be used. Distance field\n     * fonts don't support hinting which is more important at smaller sizes. A negative value means\n     * use the default threshold.\n     */\n    float fMinDistanceFieldFontSize = -1.f;\n\n    /**\n     * Above this threshold size in device space glyphs are drawn as individual paths. A negative\n     * value means use the default threshold.\n     */\n    float fGlyphsAsPathsFontSize = -1.f;\n\n    /**\n     * Can the glyph atlas use multiple textures. If allowed, the each texture's size is bound by\n     * fGlypheCacheTextureMaximumBytes.\n     */\n    Enable fAllowMultipleGlyphCacheTextures = Enable::kDefault;\n\n    /**\n     * Bugs on certain drivers cause stencil buffers to leak. This flag causes Skia to avoid\n     * allocating stencil buffers and use alternate rasterization paths, avoiding the leak.\n     */\n    bool fAvoidStencilBuffers = false;\n\n    /**\n     * When specifing new data for a vertex/index buffer that replaces old data Ganesh can give\n     * a hint to the driver that the previous data will not be used in future draws like this:\n     *  glBufferData(GL_..._BUFFER, size, NULL, usage);       //<--hint, NULL means\n     *  glBufferSubData(GL_..._BUFFER, 0, lessThanSize, data) //   old data can't be\n     *                                                        //   used again.\n     * However, this can be an unoptimization on some platforms, esp. Chrome.\n     * Chrome's cmd buffer will create a new allocation and memset the whole thing\n     * to zero (for security reasons).\n     * Defaults to the value of GR_GL_USE_BUFFER_DATA_NULL_HINT #define (which is, by default, 1).\n     */\n    Enable fUseGLBufferDataNullHint = Enable::kDefault;\n\n    /**\n     * If true, texture fetches from mip-mapped textures will be biased to read larger MIP levels.\n     * This has the effect of sharpening those textures, at the cost of some aliasing, and possible\n     * performance impact.\n     */\n    bool fSharpenMipmappedTextures = false;\n\n    /**\n     * Enables driver workaround to use draws instead of glClear. This only applies to\n     * kOpenGL_GrBackend.\n     */\n    Enable fUseDrawInsteadOfGLClear = Enable::kDefault;\n\n    /**\n     * Allow Ganesh to explicitly allocate resources at flush time rather than incrementally while\n     * drawing. This will eventually just be the way it is but, for now, it is optional.\n     */\n    Enable fExplicitlyAllocateGPUResources = Enable::kDefault;\n\n    /**\n     * Allow Ganesh to sort the opLists prior to allocating resources. This is an optional\n     * behavior that is only relevant when 'fExplicitlyAllocateGPUResources' is enabled.\n     * Eventually this will just be what is done and will not be optional.\n     */\n    Enable fSortRenderTargets = Enable::kDefault;\n\n    /**\n     * Some ES3 contexts report the ES2 external image extension, but not the ES3 version.\n     * If support for external images is critical, enabling this option will cause Ganesh to limit\n     * shaders to the ES2 shading language in that situation.\n     */\n    bool fPreferExternalImagesOverES3 = false;\n\n    /**\n     * Disables correctness workarounds that are enabled for particular GPUs, OSes, or drivers.\n     * This does not affect code path choices that are made for perfomance reasons nor does it\n     * override other GrContextOption settings.\n     */\n    bool fDisableDriverCorrectnessWorkarounds = false;\n\n    /**\n     * Cache in which to store compiled shader binaries between runs.\n     */\n    PersistentCache* fPersistentCache = nullptr;\n\n#if GR_TEST_UTILS\n    /**\n     * Private options that are only meant for testing within Skia's tools.\n     */\n\n    /**\n     * If non-zero, overrides the maximum size of a tile for sw-backed images and bitmaps rendered\n     * by SkGpuDevice.\n     */\n    int  fMaxTileSizeOverride = 0;\n\n    /**\n     * Prevents use of dual source blending, to test that all xfer modes work correctly without it.\n     */\n    bool fSuppressDualSourceBlending = false;\n\n    /**\n     * If true, the caps will never report driver support for path rendering.\n     */\n    bool fSuppressPathRendering = false;\n\n    /**\n     * If true, the caps will never support geometry shaders.\n     */\n    bool fSuppressGeometryShaders = false;\n\n    /**\n     * Render everything in wireframe\n     */\n    bool fWireframeMode = false;\n\n    /**\n     * Include or exclude specific GPU path renderers.\n     */\n    GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kDefault;\n\n    /**\n     * Disables using multiple texture units to batch multiple images into a single draw on\n     * supported GPUs.\n     */\n    bool fDisableImageMultitexturing = false;\n#endif\n\n#if SK_SUPPORT_ATLAS_TEXT\n    /**\n     * Controls whether distance field glyph vertices always have 3 components even when the view\n     * matrix does not have perspective.\n     */\n    Enable fDistanceFieldGlyphVerticesAlwaysHaveW = Enable::kDefault;\n#endif\n\n    GrDriverBugWorkarounds fDriverBugWorkarounds;\n};\n#else\nstruct GrContextOptions {\n    struct PersistentCache {};\n};\n#endif\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrDriverBugWorkarounds.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrDriverBugWorkarounds_DEFINED\n#define GrDriverBugWorkarounds_DEFINED\n\n// External embedders of Skia can override this to use their own list\n// of workaround names.\n#ifdef SK_GPU_WORKAROUNDS_HEADER\n#include SK_GPU_WORKAROUNDS_HEADER\n#else\n// To regenerate this file, set gn arg \"skia_generate_workarounds = true\".\n// This is not rebuilt by default to avoid embedders having to have extra\n// build steps.\n#include \"GrDriverBugWorkaroundsAutogen.h\"\n#endif\n\n#include \"SkTypes.h\"\n\n#include <stdint.h>\n#include <vector>\n\nenum GrDriverBugWorkaroundType {\n#define GPU_OP(type, name) type,\n  GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)\n#undef GPU_OP\n  NUMBER_OF_GPU_DRIVER_BUG_WORKAROUND_TYPES\n};\n\nclass SK_API GrDriverBugWorkarounds {\n public:\n  GrDriverBugWorkarounds();\n  explicit GrDriverBugWorkarounds(const std::vector<int32_t>& workarounds);\n\n  GrDriverBugWorkarounds& operator=(const GrDriverBugWorkarounds&) = default;\n\n  // Turn on any workarounds listed in |workarounds| (but don't turn any off).\n  void applyOverrides(const GrDriverBugWorkarounds& workarounds);\n\n  ~GrDriverBugWorkarounds();\n\n#define GPU_OP(type, name) bool name = false;\n  GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)\n#undef GPU_OP\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrDriverBugWorkaroundsAutogen.h",
    "content": "// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// This file is auto-generated from build_workaround_header.py\n// DO NOT EDIT!\n\n#define GPU_DRIVER_BUG_WORKAROUNDS(GPU_OP)              \\\n  GPU_OP(DISABLE_BLEND_EQUATION_ADVANCED,               \\\n         disable_blend_equation_advanced)               \\\n  GPU_OP(DISABLE_DISCARD_FRAMEBUFFER,                   \\\n         disable_discard_framebuffer)                   \\\n  GPU_OP(DISALLOW_LARGE_INSTANCED_DRAW,                 \\\n         disallow_large_instanced_draw)                 \\\n  GPU_OP(GL_CLEAR_BROKEN,                               \\\n         gl_clear_broken)                               \\\n  GPU_OP(MAX_MSAA_SAMPLE_COUNT_4,                       \\\n         max_msaa_sample_count_4)                       \\\n  GPU_OP(MAX_TEXTURE_SIZE_LIMIT_4096,                   \\\n         max_texture_size_limit_4096)                   \\\n  GPU_OP(PACK_PARAMETERS_WORKAROUND_WITH_PACK_BUFFER,   \\\n         pack_parameters_workaround_with_pack_buffer)   \\\n  GPU_OP(RESTORE_SCISSOR_ON_FBO_CHANGE,                 \\\n         restore_scissor_on_fbo_change)                 \\\n  GPU_OP(UNBIND_ATTACHMENTS_ON_BOUND_RENDER_FBO_DELETE, \\\n         unbind_attachments_on_bound_render_fbo_delete) \\\n// The End\n"
  },
  {
    "path": "include/gpu/GrGpuResource.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGpuResource_DEFINED\n#define GrGpuResource_DEFINED\n\n#include \"../private/GrTypesPriv.h\"\n#include \"GrResourceKey.h\"\n\nclass GrContext;\nclass GrGpu;\nclass GrResourceCache;\nclass SkTraceMemoryDump;\n\n/**\n * Base class for GrGpuResource. Handles the various types of refs we need. Separated out as a base\n * class to isolate the ref-cnting behavior and provide friendship without exposing all of\n * GrGpuResource.\n *\n * Gpu resources can have three types of refs:\n *   1) Normal ref (+ by ref(), - by unref()): These are used by code that is issuing draw calls\n *      that read and write the resource via GrOpList and by any object that must own a\n *      GrGpuResource and is itself owned (directly or indirectly) by Skia-client code.\n *   2) Pending read (+ by addPendingRead(), - by completedRead()): GrContext has scheduled a read\n *      of the resource by the GPU as a result of a skia API call but hasn't executed it yet.\n *   3) Pending write (+ by addPendingWrite(), - by completedWrite()): GrContext has scheduled a\n *      write to the resource by the GPU as a result of a skia API call but hasn't executed it yet.\n *\n * The latter two ref types are private and intended only for Gr core code.\n *\n * When all the ref/io counts reach zero DERIVED::notifyAllCntsAreZero() will be called (static poly\n * morphism using CRTP). Similarly when the ref (but not necessarily pending read/write) count\n * reaches 0 DERIVED::notifyRefCountIsZero() will be called. In the case when an unref() causes both\n * the ref cnt to reach zero and the other counts are zero, notifyRefCountIsZero() will be called\n * before notifyIsPurgeable(). Moreover, if notifyRefCountIsZero() returns false then\n * notifyAllRefCntsAreZero() won't be called at all. notifyRefCountIsZero() must return false if the\n * object may be deleted after notifyRefCntIsZero() returns.\n *\n * GrIORef and GrGpuResource are separate classes for organizational reasons and to be\n * able to give access via friendship to only the functions related to pending IO operations.\n */\ntemplate <typename DERIVED> class GrIORef : public SkNoncopyable {\npublic:\n    // Some of the signatures are written to mirror SkRefCnt so that GrGpuResource can work with\n    // templated helper classes (e.g. sk_sp). However, we have different categories of\n    // refs (e.g. pending reads). We also don't require thread safety as GrCacheable objects are\n    // not intended to cross thread boundaries.\n    void ref() const {\n        this->validate();\n        ++fRefCnt;\n    }\n\n    void unref() const {\n        this->validate();\n\n        if (!(--fRefCnt)) {\n            if (!static_cast<const DERIVED*>(this)->notifyRefCountIsZero()) {\n                return;\n            }\n        }\n\n        this->didRemoveRefOrPendingIO(kRef_CntType);\n    }\n\n    void validate() const {\n#ifdef SK_DEBUG\n        SkASSERT(fRefCnt >= 0);\n        SkASSERT(fPendingReads >= 0);\n        SkASSERT(fPendingWrites >= 0);\n        SkASSERT(fRefCnt + fPendingReads + fPendingWrites >= 0);\n#endif\n    }\n\nprotected:\n    GrIORef() : fRefCnt(1), fPendingReads(0), fPendingWrites(0) { }\n\n    enum CntType {\n        kRef_CntType,\n        kPendingRead_CntType,\n        kPendingWrite_CntType,\n    };\n\n    bool isPurgeable() const { return !this->internalHasRef() && !this->internalHasPendingIO(); }\n\n    bool internalHasPendingRead() const { return SkToBool(fPendingReads); }\n    bool internalHasPendingWrite() const { return SkToBool(fPendingWrites); }\n    bool internalHasPendingIO() const { return SkToBool(fPendingWrites | fPendingReads); }\n\n    bool internalHasRef() const { return SkToBool(fRefCnt); }\n    bool internalHasUniqueRef() const { return fRefCnt == 1; }\n\nprivate:\n    friend class GrIORefProxy; // needs to forward on wrapped IO calls\n    // This is for a unit test.\n    template <typename T>\n    friend void testingOnly_getIORefCnts(const T*, int* refCnt, int* readCnt, int* writeCnt);\n\n    void addPendingRead() const {\n        this->validate();\n        ++fPendingReads;\n    }\n\n    void completedRead() const {\n        this->validate();\n        --fPendingReads;\n        this->didRemoveRefOrPendingIO(kPendingRead_CntType);\n    }\n\n    void addPendingWrite() const {\n        this->validate();\n        ++fPendingWrites;\n    }\n\n    void completedWrite() const {\n        this->validate();\n        --fPendingWrites;\n        this->didRemoveRefOrPendingIO(kPendingWrite_CntType);\n    }\n\nprivate:\n    void didRemoveRefOrPendingIO(CntType cntTypeRemoved) const {\n        if (0 == fPendingReads && 0 == fPendingWrites && 0 == fRefCnt) {\n            static_cast<const DERIVED*>(this)->notifyAllCntsAreZero(cntTypeRemoved);\n        }\n    }\n\n    mutable int32_t fRefCnt;\n    mutable int32_t fPendingReads;\n    mutable int32_t fPendingWrites;\n\n    // This class is used to manage conversion of refs to pending reads/writes.\n    friend class GrGpuResourceRef;\n    friend class GrResourceCache; // to check IO ref counts.\n\n    template <typename, GrIOType> friend class GrPendingIOResource;\n};\n\n/**\n * Base class for objects that can be kept in the GrResourceCache.\n */\nclass SK_API GrGpuResource : public GrIORef<GrGpuResource> {\npublic:\n\n    /**\n     * Tests whether a object has been abandoned or released. All objects will\n     * be in this state after their creating GrContext is destroyed or has\n     * contextLost called. It's up to the client to test wasDestroyed() before\n     * attempting to use an object if it holds refs on objects across\n     * ~GrContext, freeResources with the force flag, or contextLost.\n     *\n     * @return true if the object has been released or abandoned,\n     *         false otherwise.\n     */\n    bool wasDestroyed() const { return nullptr == fGpu; }\n\n    /**\n     * Retrieves the context that owns the object. Note that it is possible for\n     * this to return NULL. When objects have been release()ed or abandon()ed\n     * they no longer have an owning context. Destroying a GrContext\n     * automatically releases all its resources.\n     */\n    const GrContext* getContext() const;\n    GrContext* getContext();\n\n    /**\n     * Retrieves the amount of GPU memory used by this resource in bytes. It is\n     * approximate since we aren't aware of additional padding or copies made\n     * by the driver.\n     *\n     * @return the amount of GPU memory used in bytes\n     */\n    size_t gpuMemorySize() const {\n        if (kInvalidGpuMemorySize == fGpuMemorySize) {\n            fGpuMemorySize = this->onGpuMemorySize();\n            SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);\n        }\n        return fGpuMemorySize;\n    }\n\n    class UniqueID {\n    public:\n        static UniqueID InvalidID() {\n            return UniqueID(uint32_t(SK_InvalidUniqueID));\n        }\n\n        UniqueID() {}\n\n        explicit UniqueID(uint32_t id) : fID(id) {}\n\n        uint32_t asUInt() const { return fID; }\n\n        bool operator==(const UniqueID& other) const {\n            return fID == other.fID;\n        }\n        bool operator!=(const UniqueID& other) const {\n            return !(*this == other);\n        }\n\n        void makeInvalid() { fID = SK_InvalidUniqueID; }\n        bool isInvalid() const { return SK_InvalidUniqueID == fID; }\n\n    protected:\n        uint32_t fID;\n    };\n\n    /**\n     * Gets an id that is unique for this GrGpuResource object. It is static in that it does\n     * not change when the content of the GrGpuResource object changes. This will never return\n     * 0.\n     */\n    UniqueID uniqueID() const { return fUniqueID; }\n\n    /** Returns the current unique key for the resource. It will be invalid if the resource has no\n        associated unique key. */\n    const GrUniqueKey& getUniqueKey() const { return fUniqueKey; }\n\n    /**\n     * Internal-only helper class used for manipulations of the resource by the cache.\n     */\n    class CacheAccess;\n    inline CacheAccess cacheAccess();\n    inline const CacheAccess cacheAccess() const;\n\n    /**\n     * Internal-only helper class used for manipulations of the resource by internal code.\n     */\n    class ResourcePriv;\n    inline ResourcePriv resourcePriv();\n    inline const ResourcePriv resourcePriv() const;\n\n    /**\n     * Removes references to objects in the underlying 3D API without freeing them.\n     * Called by CacheAccess.\n     * In general this method should not be called outside of skia. It was\n     * made by public for a special case where it needs to be called in Blink\n     * when a texture becomes unsafe to use after having been shared through\n     * a texture mailbox.\n     */\n    void abandon();\n\n    /**\n     * Dumps memory usage information for this GrGpuResource to traceMemoryDump.\n     * Typically, subclasses should not need to override this, and should only\n     * need to override setMemoryBacking.\n     **/\n    virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;\n\n    /**\n     * Describes the type of gpu resource that is represented by the implementing\n     * class (e.g. texture, buffer object, stencil).  This data is used for diagnostic\n     * purposes by dumpMemoryStatistics().\n     *\n     * The value returned is expected to be long lived and will not be copied by the caller.\n     */\n    virtual const char* getResourceType() const = 0;\n\n    static uint32_t CreateUniqueID();\n\nprotected:\n    // This must be called by every non-wrapped GrGpuObject. It should be called once the object is\n    // fully initialized (i.e. only from the constructors of the final class).\n    void registerWithCache(SkBudgeted);\n\n    // This must be called by every GrGpuObject that references any wrapped backend objects. It\n    // should be called once the object is fully initialized (i.e. only from the constructors of the\n    // final class).\n    void registerWithCacheWrapped();\n\n    GrGpuResource(GrGpu*);\n    virtual ~GrGpuResource();\n\n    GrGpu* getGpu() const { return fGpu; }\n\n    /** Overridden to free GPU resources in the backend API. */\n    virtual void onRelease() { }\n    /** Overridden to abandon any internal handles, ptrs, etc to backend API resources.\n        This may be called when the underlying 3D context is no longer valid and so no\n        backend API calls should be made. */\n    virtual void onAbandon() { }\n\n    /**\n     * This entry point should be called whenever gpuMemorySize() should report a different size.\n     * The cache will call gpuMemorySize() to update the current size of the resource.\n     */\n    void didChangeGpuMemorySize() const;\n\n    /**\n     * Allows subclasses to add additional backing information to the SkTraceMemoryDump.\n     **/\n    virtual void setMemoryBacking(SkTraceMemoryDump*, const SkString&) const {}\n\n    /**\n     * Returns a string that uniquely identifies this resource.\n     */\n    SkString getResourceName() const;\n\n    /**\n     * A helper for subclasses that override dumpMemoryStatistics(). This method using a format\n     * consistent with the default implementation of dumpMemoryStatistics() but allows the caller\n     * to customize various inputs.\n     */\n    void dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump, const SkString& resourceName,\n                                  const char* type, size_t size) const;\n\n\nprivate:\n    /**\n     * Called by the registerWithCache if the resource is available to be used as scratch.\n     * Resource subclasses should override this if the instances should be recycled as scratch\n     * resources and populate the scratchKey with the key.\n     * By default resources are not recycled as scratch.\n     **/\n    virtual void computeScratchKey(GrScratchKey*) const { }\n\n    /**\n     * Frees the object in the underlying 3D API. Called by CacheAccess.\n     */\n    void release();\n\n    virtual size_t onGpuMemorySize() const = 0;\n\n    // See comments in CacheAccess and ResourcePriv.\n    void setUniqueKey(const GrUniqueKey&);\n    void removeUniqueKey();\n    void notifyAllCntsAreZero(CntType) const;\n    bool notifyRefCountIsZero() const;\n    void removeScratchKey();\n    void makeBudgeted();\n    void makeUnbudgeted();\n\n#ifdef SK_DEBUG\n    friend class GrGpu;  // for assert in GrGpu to access getGpu\n#endif\n\n    // An index into a heap when this resource is purgeable or an array when not. This is maintained\n    // by the cache.\n    int fCacheArrayIndex;\n    // This value reflects how recently this resource was accessed in the cache. This is maintained\n    // by the cache.\n    uint32_t fTimestamp;\n    uint32_t fExternalFlushCntWhenBecamePurgeable;\n    GrStdSteadyClock::time_point fTimeWhenBecamePurgeable;\n\n    static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);\n    GrScratchKey fScratchKey;\n    GrUniqueKey fUniqueKey;\n\n    // This is not ref'ed but abandon() or release() will be called before the GrGpu object\n    // is destroyed. Those calls set will this to NULL.\n    GrGpu* fGpu;\n    mutable size_t fGpuMemorySize;\n\n    SkBudgeted fBudgeted;\n    bool fRefsWrappedObjects;\n    const UniqueID fUniqueID;\n\n    typedef GrIORef<GrGpuResource> INHERITED;\n    friend class GrIORef<GrGpuResource>; // to access notifyAllCntsAreZero and notifyRefCntIsZero.\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrRenderTarget.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrRenderTarget_DEFINED\n#define GrRenderTarget_DEFINED\n\n#include \"GrSurface.h\"\n#include \"SkRect.h\"\n\nclass GrCaps;\nclass GrRenderTargetOpList;\nclass GrRenderTargetPriv;\nclass GrStencilAttachment;\nclass GrBackendRenderTarget;\n\n/**\n * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.\n * A context's render target is set by setRenderTarget(). Render targets are\n * created by a createTexture with the kRenderTarget_SurfaceFlag flag.\n * Additionally, GrContext provides methods for creating GrRenderTargets\n * that wrap externally created render targets.\n */\nclass GrRenderTarget : virtual public GrSurface {\npublic:\n    virtual bool alwaysClearStencil() const { return false; }\n\n    // GrSurface overrides\n    GrRenderTarget* asRenderTarget() override { return this; }\n    const GrRenderTarget* asRenderTarget() const  override { return this; }\n\n    // GrRenderTarget\n    bool isStencilBufferMultisampled() const { return fSampleCnt > 1; }\n\n    GrFSAAType fsaaType() const {\n        SkASSERT(fSampleCnt >= 1);\n        if (fSampleCnt <= 1) {\n            SkASSERT(!this->hasMixedSamples());\n            return GrFSAAType::kNone;\n        }\n        return this->hasMixedSamples() ? GrFSAAType::kMixedSamples : GrFSAAType::kUnifiedMSAA;\n    }\n\n    /**\n     * Returns the number of samples/pixel in the stencil buffer (One if non-MSAA).\n     */\n    int numStencilSamples() const { return fSampleCnt; }\n\n    /**\n     * Returns the number of samples/pixel in the color buffer (One if non-MSAA or mixed sampled).\n     */\n    int numColorSamples() const {\n        return GrFSAAType::kMixedSamples == this->fsaaType() ? 1 : fSampleCnt;\n    }\n\n    /**\n     * Call to indicate the multisample contents were modified such that the\n     * render target needs to be resolved before it can be used as texture. Gr\n     * tracks this for its own drawing and thus this only needs to be called\n     * when the render target has been modified outside of Gr. This has no\n     * effect on wrapped backend render targets.\n     *\n     * @param rect  a rect bounding the area needing resolve. NULL indicates\n     *              the whole RT needs resolving.\n     */\n    void flagAsNeedingResolve(const SkIRect* rect = nullptr);\n\n    /**\n     * Call to override the region that needs to be resolved.\n     */\n    void overrideResolveRect(const SkIRect rect);\n\n    /**\n     * Call to indicate that GrRenderTarget was externally resolved. This may\n     * allow Gr to skip a redundant resolve step.\n     */\n    void flagAsResolved();\n\n    /**\n     * @return true if the GrRenderTarget requires MSAA resolving\n     */\n    bool needsResolve() const { return !fResolveRect.isEmpty(); }\n\n    /**\n     * Returns a rect bounding the region needing resolving.\n     */\n    const SkIRect& getResolveRect() const { return fResolveRect; }\n\n    // a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO\n    // 0 in GL), or be unresolvable because the client didn't give us the\n    // resolve destination.\n    enum ResolveType {\n        kCanResolve_ResolveType,\n        kAutoResolves_ResolveType,\n        kCantResolve_ResolveType,\n    };\n    virtual ResolveType getResolveType() const = 0;\n\n    virtual GrBackendRenderTarget getBackendRenderTarget() const = 0;\n\n    // Checked when this object is asked to attach a stencil buffer.\n    virtual bool canAttemptStencilAttachment() const = 0;\n\n    // Provides access to functions that aren't part of the public API.\n    GrRenderTargetPriv renderTargetPriv();\n    const GrRenderTargetPriv renderTargetPriv() const;\n\nprotected:\n    GrRenderTarget(GrGpu*, const GrSurfaceDesc&, GrStencilAttachment* = nullptr);\n\n    // override of GrResource\n    void onAbandon() override;\n    void onRelease() override;\n\nprivate:\n    // Allows the backends to perform any additional work that is required for attaching a\n    // GrStencilAttachment. When this is called, the GrStencilAttachment has already been put onto\n    // the GrRenderTarget. This function must return false if any failures occur when completing the\n    // stencil attachment.\n    virtual bool completeStencilAttachment() = 0;\n\n    friend class GrRenderTargetPriv;\n\n    int                  fSampleCnt;\n    GrStencilAttachment* fStencilAttachment;\n\n    SkIRect              fResolveRect;\n\n    typedef GrSurface INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrResourceKey.h",
    "content": "\n/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrResourceKey_DEFINED\n#define GrResourceKey_DEFINED\n\n#include \"../private/SkOnce.h\"\n#include \"../private/SkTemplates.h\"\n#include \"GrTypes.h\"\n#include \"SkData.h\"\n#include \"SkString.h\"\n\nuint32_t GrResourceKeyHash(const uint32_t* data, size_t size);\n\n/**\n * Base class for all GrGpuResource cache keys. There are two types of cache keys. Refer to the\n * comments for each key type below.\n */\nclass GrResourceKey {\npublic:\n    uint32_t hash() const {\n        this->validate();\n        return fKey[kHash_MetaDataIdx];\n    }\n\n    size_t size() const {\n        this->validate();\n        SkASSERT(this->isValid());\n        return this->internalSize();\n    }\n\nprotected:\n    static const uint32_t kInvalidDomain = 0;\n\n    GrResourceKey() { this->reset(); }\n\n    /** Reset to an invalid key. */\n    void reset() {\n        GR_STATIC_ASSERT((uint16_t)kInvalidDomain == kInvalidDomain);\n        fKey.reset(kMetaDataCnt);\n        fKey[kHash_MetaDataIdx] = 0;\n        fKey[kDomainAndSize_MetaDataIdx] = kInvalidDomain;\n    }\n\n    bool operator==(const GrResourceKey& that) const {\n        return this->hash() == that.hash() &&\n                0 == memcmp(&fKey[kHash_MetaDataIdx + 1],\n                            &that.fKey[kHash_MetaDataIdx + 1],\n                            this->internalSize() - sizeof(uint32_t));\n    }\n\n    GrResourceKey& operator=(const GrResourceKey& that) {\n        SkASSERT(that.isValid());\n        if (this != &that) {\n            size_t bytes = that.size();\n            SkASSERT(SkIsAlign4(bytes));\n            fKey.reset(SkToInt(bytes / sizeof(uint32_t)));\n            memcpy(fKey.get(), that.fKey.get(), bytes);\n            this->validate();\n        }\n        return *this;\n    }\n\n    bool isValid() const { return kInvalidDomain != this->domain(); }\n\n    uint32_t domain() const { return fKey[kDomainAndSize_MetaDataIdx] & 0xffff; }\n\n    /** size of the key data, excluding meta-data (hash, domain, etc).  */\n    size_t dataSize() const { return this->size() - 4 * kMetaDataCnt; }\n\n    /** ptr to the key data, excluding meta-data (hash, domain, etc).  */\n    const uint32_t* data() const {\n        this->validate();\n        return &fKey[kMetaDataCnt];\n    }\n\n    /** Used to initialize a key. */\n    class Builder {\n    public:\n        Builder(GrResourceKey* key, uint32_t domain, int data32Count) : fKey(key) {\n            SkASSERT(data32Count >= 0);\n            SkASSERT(domain != kInvalidDomain);\n            key->fKey.reset(kMetaDataCnt + data32Count);\n            int size = (data32Count + kMetaDataCnt) * sizeof(uint32_t);\n            SkASSERT(SkToU16(size) == size);\n            SkASSERT(SkToU16(domain) == domain);\n            key->fKey[kDomainAndSize_MetaDataIdx] = domain | (size << 16);\n        }\n\n        ~Builder() { this->finish(); }\n\n        void finish() {\n            if (nullptr == fKey) {\n                return;\n            }\n            GR_STATIC_ASSERT(0 == kHash_MetaDataIdx);\n            uint32_t* hash = &fKey->fKey[kHash_MetaDataIdx];\n            *hash = GrResourceKeyHash(hash + 1, fKey->internalSize() - sizeof(uint32_t));\n            fKey->validate();\n            fKey = nullptr;\n        }\n\n        uint32_t& operator[](int dataIdx) {\n            SkASSERT(fKey);\n            SkDEBUGCODE(size_t dataCount = fKey->internalSize() / sizeof(uint32_t) - kMetaDataCnt;)\n            SkASSERT(SkToU32(dataIdx) < dataCount);\n            return fKey->fKey[kMetaDataCnt + dataIdx];\n        }\n\n    private:\n        GrResourceKey* fKey;\n    };\n\nprivate:\n    enum MetaDataIdx {\n        kHash_MetaDataIdx,\n        // The key domain and size are packed into a single uint32_t.\n        kDomainAndSize_MetaDataIdx,\n\n        kLastMetaDataIdx = kDomainAndSize_MetaDataIdx\n    };\n    static const uint32_t kMetaDataCnt = kLastMetaDataIdx + 1;\n\n    size_t internalSize() const {\n        return fKey[kDomainAndSize_MetaDataIdx] >> 16;\n    }\n\n    void validate() const {\n        SkASSERT(fKey[kHash_MetaDataIdx] ==\n                 GrResourceKeyHash(&fKey[kHash_MetaDataIdx] + 1,\n                                   this->internalSize() - sizeof(uint32_t)));\n        SkASSERT(SkIsAlign4(this->internalSize()));\n    }\n\n    friend class TestResource; // For unit test to access kMetaDataCnt.\n\n    // bmp textures require 7 uint32_t values (5 for the base key, and two more for image\n    // cacherator's decode format.\n    SkAutoSTMalloc<kMetaDataCnt + 7, uint32_t> fKey;\n};\n\n/**\n * A key used for scratch resources. There are three important rules about scratch keys:\n *        * Multiple resources can share the same scratch key. Therefore resources assigned the same\n *          scratch key should be interchangeable with respect to the code that uses them.\n *        * A resource can have at most one scratch key and it is set at resource creation by the\n *          resource itself.\n *        * When a scratch resource is ref'ed it will not be returned from the\n *          cache for a subsequent cache request until all refs are released. This facilitates using\n *          a scratch key for multiple render-to-texture scenarios. An example is a separable blur:\n *\n *  GrTexture* texture[2];\n *  texture[0] = get_scratch_texture(scratchKey);\n *  texture[1] = get_scratch_texture(scratchKey); // texture[0] is already owned so we will get a\n *                                                // different one for texture[1]\n *  draw_mask(texture[0], path);        // draws path mask to texture[0]\n *  blur_x(texture[0], texture[1]);     // blurs texture[0] in y and stores result in texture[1]\n *  blur_y(texture[1], texture[0]);     // blurs texture[1] in y and stores result in texture[0]\n *  texture[1]->unref();  // texture 1 can now be recycled for the next request with scratchKey\n *  consume_blur(texture[0]);\n *  texture[0]->unref();  // texture 0 can now be recycled for the next request with scratchKey\n */\nclass GrScratchKey : public GrResourceKey {\nprivate:\n    typedef GrResourceKey INHERITED;\n\npublic:\n    /** Uniquely identifies the type of resource that is cached as scratch. */\n    typedef uint32_t ResourceType;\n\n    /** Generate a unique ResourceType. */\n    static ResourceType GenerateResourceType();\n\n    /** Creates an invalid scratch key. It must be initialized using a Builder object before use. */\n    GrScratchKey() {}\n\n    GrScratchKey(const GrScratchKey& that) { *this = that; }\n\n    /** reset() returns the key to the invalid state. */\n    using INHERITED::reset;\n\n    using INHERITED::isValid;\n\n    ResourceType resourceType() const { return this->domain(); }\n\n    GrScratchKey& operator=(const GrScratchKey& that) {\n        this->INHERITED::operator=(that);\n        return *this;\n    }\n\n    bool operator==(const GrScratchKey& that) const {\n        return this->INHERITED::operator==(that);\n    }\n    bool operator!=(const GrScratchKey& that) const { return !(*this == that); }\n\n    class Builder : public INHERITED::Builder {\n    public:\n        Builder(GrScratchKey* key, ResourceType type, int data32Count)\n            : INHERITED::Builder(key, type, data32Count) {}\n    };\n};\n\n/**\n * A key that allows for exclusive use of a resource for a use case (AKA \"domain\"). There are three\n * rules governing the use of unique keys:\n *        * Only one resource can have a given unique key at a time. Hence, \"unique\".\n *        * A resource can have at most one unique key at a time.\n *        * Unlike scratch keys, multiple requests for a unique key will return the same\n *          resource even if the resource already has refs.\n * This key type allows a code path to create cached resources for which it is the exclusive user.\n * The code path creates a domain which it sets on its keys. This guarantees that there are no\n * cross-domain collisions.\n *\n * Unique keys preempt scratch keys. While a resource has a unique key it is inaccessible via its\n * scratch key. It can become scratch again if the unique key is removed.\n */\nclass GrUniqueKey : public GrResourceKey {\nprivate:\n    typedef GrResourceKey INHERITED;\n\npublic:\n    typedef uint32_t Domain;\n    /** Generate a Domain for unique keys. */\n    static Domain GenerateDomain();\n\n    /** Creates an invalid unique key. It must be initialized using a Builder object before use. */\n    GrUniqueKey() {}\n\n    GrUniqueKey(const GrUniqueKey& that) { *this = that; }\n\n    /** reset() returns the key to the invalid state. */\n    using INHERITED::reset;\n\n    using INHERITED::isValid;\n\n    GrUniqueKey& operator=(const GrUniqueKey& that) {\n        this->INHERITED::operator=(that);\n        this->setCustomData(sk_ref_sp(that.getCustomData()));\n        fTag = that.fTag;\n        return *this;\n    }\n\n    bool operator==(const GrUniqueKey& that) const {\n        return this->INHERITED::operator==(that);\n    }\n    bool operator!=(const GrUniqueKey& that) const { return !(*this == that); }\n\n    void setCustomData(sk_sp<SkData> data) {\n        fData = std::move(data);\n    }\n    SkData* getCustomData() const {\n        return fData.get();\n    }\n\n    const char* tag() const { return fTag; }\n\n    class Builder : public INHERITED::Builder {\n    public:\n        Builder(GrUniqueKey* key, Domain type, int data32Count, const char* tag = nullptr)\n                : INHERITED::Builder(key, type, data32Count) {\n            key->fTag = tag;\n        }\n\n        /** Used to build a key that wraps another key and adds additional data. */\n        Builder(GrUniqueKey* key, const GrUniqueKey& innerKey, Domain domain, int extraData32Cnt,\n                const char* tag = nullptr)\n                : INHERITED::Builder(key, domain, Data32CntForInnerKey(innerKey) + extraData32Cnt) {\n            SkASSERT(&innerKey != key);\n            // add the inner key to the end of the key so that op[] can be indexed normally.\n            uint32_t* innerKeyData = &this->operator[](extraData32Cnt);\n            const uint32_t* srcData = innerKey.data();\n            (*innerKeyData++) = innerKey.domain();\n            memcpy(innerKeyData, srcData, innerKey.dataSize());\n            key->fTag = tag;\n        }\n\n    private:\n        static int Data32CntForInnerKey(const GrUniqueKey& innerKey) {\n            // key data + domain\n            return SkToInt((innerKey.dataSize() >> 2) + 1);\n        }\n    };\n\nprivate:\n    sk_sp<SkData> fData;\n    const char* fTag;\n};\n\n/**\n * It is common to need a frequently reused GrUniqueKey where the only requirement is that the key\n * is unique. These macros create such a key in a thread safe manner so the key can be truly global\n * and only constructed once.\n */\n\n/** Place outside of function/class definitions. */\n#define GR_DECLARE_STATIC_UNIQUE_KEY(name) static SkOnce name##_once\n\n/** Place inside function where the key is used. */\n#define GR_DEFINE_STATIC_UNIQUE_KEY(name)                                                       \\\n    static SkAlignedSTStorage<1, GrUniqueKey> name##_storage;                                   \\\n    name##_once(gr_init_static_unique_key_once, &name##_storage);                               \\\n    static const GrUniqueKey& name = *reinterpret_cast<GrUniqueKey*>(name##_storage.get());\n\nstatic inline void gr_init_static_unique_key_once(SkAlignedSTStorage<1,GrUniqueKey>* keyStorage) {\n    GrUniqueKey* key = new (keyStorage->get()) GrUniqueKey;\n    GrUniqueKey::Builder builder(key, GrUniqueKey::GenerateDomain(), 0);\n}\n\n// The cache listens for these messages to purge junk resources proactively.\nclass GrUniqueKeyInvalidatedMessage {\npublic:\n    explicit GrUniqueKeyInvalidatedMessage(const GrUniqueKey& key) : fKey(key) {}\n\n    GrUniqueKeyInvalidatedMessage(const GrUniqueKeyInvalidatedMessage& that) : fKey(that.fKey) {}\n\n    GrUniqueKeyInvalidatedMessage& operator=(const GrUniqueKeyInvalidatedMessage& that) {\n        fKey = that.fKey;\n        return *this;\n    }\n\n    const GrUniqueKey& key() const { return fKey; }\n\nprivate:\n    GrUniqueKey fKey;\n};\n#endif\n"
  },
  {
    "path": "include/gpu/GrSamplerState.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSamplerState_DEFINED\n#define GrSamplerState_DEFINED\n\n#include \"GrTypes.h\"\n\n/**\n * Represents the filtering and tile modes used to access a texture.\n */\nclass GrSamplerState {\npublic:\n    enum class Filter : uint8_t { kNearest, kBilerp, kMipMap };\n    enum class WrapMode : uint8_t { kClamp, kRepeat, kMirrorRepeat };\n\n    static constexpr GrSamplerState ClampNearest() { return GrSamplerState(); }\n    static constexpr GrSamplerState ClampBilerp() {\n        return GrSamplerState(WrapMode::kClamp, Filter::kBilerp);\n    }\n\n    constexpr GrSamplerState() : GrSamplerState(WrapMode::kClamp, Filter::kNearest) {}\n\n    constexpr GrSamplerState(WrapMode wrapXAndY, Filter filter)\n            : fWrapModes{wrapXAndY, wrapXAndY}, fFilter(filter) {}\n\n    constexpr GrSamplerState(const WrapMode wrapModes[2], Filter filter)\n            : fWrapModes{wrapModes[0], wrapModes[1]}, fFilter(filter) {}\n\n    constexpr GrSamplerState(const GrSamplerState&) = default;\n\n    GrSamplerState& operator=(const GrSamplerState& that) {\n        fWrapModes[0] = that.fWrapModes[0];\n        fWrapModes[1] = that.fWrapModes[1];\n        fFilter = that.fFilter;\n        return *this;\n    }\n\n    Filter filter() const { return fFilter; }\n\n    void setFilterMode(Filter filterMode) { fFilter = filterMode; }\n\n    void setWrapModeX(const WrapMode wrap) { fWrapModes[0] = wrap; }\n    void setWrapModeY(const WrapMode wrap) { fWrapModes[1] = wrap; }\n\n    WrapMode wrapModeX() const { return fWrapModes[0]; }\n    WrapMode wrapModeY() const { return fWrapModes[1]; }\n\n    bool isRepeated() const {\n        return WrapMode::kClamp != fWrapModes[0] || WrapMode::kClamp != fWrapModes[1];\n    }\n\n    bool operator==(const GrSamplerState& that) const {\n        return fWrapModes[0] == that.fWrapModes[0] && fWrapModes[1] == that.fWrapModes[1] &&\n               fFilter == that.fFilter;\n    }\n\n    bool operator!=(const GrSamplerState& that) const { return !(*this == that); }\n\nprivate:\n    WrapMode fWrapModes[2];\n    Filter fFilter;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrSurface.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSurface_DEFINED\n#define GrSurface_DEFINED\n\n#include \"GrTypes.h\"\n#include \"GrGpuResource.h\"\n#include \"SkImageInfo.h\"\n#include \"SkRect.h\"\n\nclass GrRenderTarget;\nclass GrSurfacePriv;\nclass GrTexture;\n\nclass SK_API GrSurface : public GrGpuResource {\npublic:\n    /**\n     * Retrieves the width of the surface.\n     */\n    int width() const { return fWidth; }\n\n    /**\n     * Retrieves the height of the surface.\n     */\n    int height() const { return fHeight; }\n\n    /**\n     * Helper that gets the width and height of the surface as a bounding rectangle.\n     */\n    SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }\n\n    /**\n     * Retrieves the pixel config specified when the surface was created.\n     * For render targets this can be kUnknown_GrPixelConfig\n     * if client asked us to render to a target that has a pixel\n     * config that isn't equivalent with one of our configs.\n     */\n    GrPixelConfig config() const { return fConfig; }\n\n    /**\n     * @return the texture associated with the surface, may be null.\n     */\n    virtual GrTexture* asTexture() { return nullptr; }\n    virtual const GrTexture* asTexture() const { return nullptr; }\n\n    /**\n     * @return the render target underlying this surface, may be null.\n     */\n    virtual GrRenderTarget* asRenderTarget() { return nullptr; }\n    virtual const GrRenderTarget* asRenderTarget() const { return nullptr; }\n\n    /** Access methods that are only to be used within Skia code. */\n    inline GrSurfacePriv surfacePriv();\n    inline const GrSurfacePriv surfacePriv() const;\n\n    static size_t WorstCaseSize(const GrSurfaceDesc& desc, bool useNextPow2 = false);\n    static size_t ComputeSize(GrPixelConfig config, int width, int height, int colorSamplesPerPixel,\n                              GrMipMapped, bool useNextPow2 = false);\n\nprotected:\n    void setDoesNotSupportMipMaps() {\n        SkASSERT(this->asTexture());\n        fSurfaceFlags |= GrInternalSurfaceFlags::kDoesNotSupportMipMaps;\n    }\n    bool doesNotSupportMipMaps() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kDoesNotSupportMipMaps;\n    }\n\n    void setIsGLTextureRectangleOrExternal() {\n        SkASSERT(this->asTexture());\n        fSurfaceFlags |= GrInternalSurfaceFlags::kIsGLTextureRectangleOrExternal;\n        // If we are a GL rectangle or external texture, it also means that we do not support\n        // generating mip maps.\n        this->setDoesNotSupportMipMaps();\n    }\n    bool isGLTextureRectangleOrExternal() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kIsGLTextureRectangleOrExternal;\n    }\n\n    void setHasMixedSamples() {\n        SkASSERT(this->asRenderTarget());\n        fSurfaceFlags |= GrInternalSurfaceFlags::kMixedSampled;\n    }\n    bool hasMixedSamples() const { return fSurfaceFlags & GrInternalSurfaceFlags::kMixedSampled; }\n\n    void setSupportsWindowRects() {\n        SkASSERT(this->asRenderTarget());\n        fSurfaceFlags |= GrInternalSurfaceFlags::kWindowRectsSupport;\n    }\n    bool supportsWindowRects() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kWindowRectsSupport;\n    }\n\n    void setGLRTFBOIDIs0() {\n        SkASSERT(this->asRenderTarget());\n        fSurfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;\n    }\n    bool glRTFBOIDis0() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0;\n    }\n\n    // Methods made available via GrSurfacePriv\n    bool hasPendingRead() const;\n    bool hasPendingWrite() const;\n    bool hasPendingIO() const;\n\n    // Provides access to methods that should be public within Skia code.\n    friend class GrSurfacePriv;\n\n    GrSurface(GrGpu* gpu, const GrSurfaceDesc& desc)\n            : INHERITED(gpu)\n            , fConfig(desc.fConfig)\n            , fWidth(desc.fWidth)\n            , fHeight(desc.fHeight)\n            , fSurfaceFlags(GrInternalSurfaceFlags::kNone) {\n    }\n\n    ~GrSurface() override {}\n\n\n    void onRelease() override;\n    void onAbandon() override;\n\nprivate:\n    const char* getResourceType() const override { return \"Surface\"; }\n\n    GrPixelConfig          fConfig;\n    int                    fWidth;\n    int                    fHeight;\n    GrInternalSurfaceFlags fSurfaceFlags;\n\n    typedef GrGpuResource INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrTexture.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrTexture_DEFINED\n#define GrTexture_DEFINED\n\n#include \"GrBackendSurface.h\"\n#include \"GrSamplerState.h\"\n#include \"GrSurface.h\"\n#include \"SkImage.h\"\n#include \"SkPoint.h\"\n#include \"SkRefCnt.h\"\n#include \"../private/GrTypesPriv.h\"\n\nclass GrTexturePriv;\n\nclass GrTexture : virtual public GrSurface {\npublic:\n    GrTexture* asTexture() override { return this; }\n    const GrTexture* asTexture() const override { return this; }\n\n    virtual GrBackendTexture getBackendTexture() const = 0;\n\n    /**\n     * This function indicates that the texture parameters (wrap mode, filtering, ...) have been\n     * changed externally to Skia.\n     */\n    virtual void textureParamsModified() = 0;\n\n    /**\n     * This function steals the backend texture from a uniquely owned GrTexture with no pending\n     * IO, passing it out to the caller. The GrTexture is deleted in the process.\n     *\n     * Note that if the GrTexture is not uniquely owned (no other refs), or has pending IO, this\n     * function will fail.\n     */\n    static bool StealBackendTexture(sk_sp<GrTexture>&&,\n                                    GrBackendTexture*,\n                                    SkImage::BackendTextureReleaseProc*);\n\n#ifdef SK_DEBUG\n    void validate() const {\n        this->INHERITED::validate();\n    }\n#endif\n\n    virtual void setRelease(sk_sp<GrReleaseProcHelper> releaseHelper) = 0;\n\n    // These match the definitions in SkImage, from whence they came.\n    // TODO: Either move Chrome over to new api or remove their need to call this on GrTexture\n    typedef void* ReleaseCtx;\n    typedef void (*ReleaseProc)(ReleaseCtx);\n    void setRelease(ReleaseProc proc, ReleaseCtx ctx) {\n        sk_sp<GrReleaseProcHelper> helper(new GrReleaseProcHelper(proc, ctx));\n        this->setRelease(std::move(helper));\n    }\n\n    /** Access methods that are only to be used within Skia code. */\n    inline GrTexturePriv texturePriv();\n    inline const GrTexturePriv texturePriv() const;\n\nprotected:\n    GrTexture(GrGpu*, const GrSurfaceDesc&, GrSLType samplerType,\n              GrSamplerState::Filter highestFilterMode, GrMipMapsStatus);\n\n    virtual bool onStealBackendTexture(GrBackendTexture*, SkImage::BackendTextureReleaseProc*) = 0;\n\nprivate:\n    void computeScratchKey(GrScratchKey*) const override;\n    size_t onGpuMemorySize() const override;\n    void markMipMapsDirty();\n    void markMipMapsClean();\n\n    GrSLType                      fSamplerType;\n    GrSamplerState::Filter        fHighestFilterMode;\n    GrMipMapsStatus               fMipMapsStatus;\n    int                           fMaxMipMapLevel;\n    friend class GrTexturePriv;\n\n    typedef GrSurface INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/GrTypes.h",
    "content": "/*\n * Copyright 2010 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrTypes_DEFINED\n#define GrTypes_DEFINED\n\n#include \"SkMath.h\"\n#include \"SkTypes.h\"\n#include \"GrConfig.h\"\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * Defines overloaded bitwise operators to make it easier to use an enum as a\n * bitfield.\n */\n#define GR_MAKE_BITFIELD_OPS(X) \\\n    inline X operator |(X a, X b) { \\\n        return (X) (+a | +b); \\\n    } \\\n    inline X& operator |=(X& a, X b) { \\\n        return (a = a | b); \\\n    } \\\n    inline X operator &(X a, X b) { \\\n        return (X) (+a & +b); \\\n    } \\\n    inline X& operator &=(X& a, X b) { \\\n        return (a = a & b); \\\n    } \\\n    template <typename T> \\\n    inline X operator &(T a, X b) { \\\n        return (X) (+a & +b); \\\n    } \\\n    template <typename T> \\\n    inline X operator &(X a, T b) { \\\n        return (X) (+a & +b); \\\n    } \\\n\n#define GR_DECL_BITFIELD_OPS_FRIENDS(X) \\\n    friend X operator |(X a, X b); \\\n    friend X& operator |=(X& a, X b); \\\n    \\\n    friend X operator &(X a, X b); \\\n    friend X& operator &=(X& a, X b); \\\n    \\\n    template <typename T> \\\n    friend X operator &(T a, X b); \\\n    \\\n    template <typename T> \\\n    friend X operator &(X a, T b); \\\n\n/**\n * Wraps a C++11 enum that we use as a bitfield, and enables a limited amount of\n * masking with type safety. Instantiated with the ~ operator.\n */\ntemplate<typename TFlags> class GrTFlagsMask {\npublic:\n    constexpr explicit GrTFlagsMask(TFlags value) : GrTFlagsMask(static_cast<int>(value)) {}\n    constexpr explicit GrTFlagsMask(int value) : fValue(value) {}\n    constexpr int value() const { return fValue; }\nprivate:\n    const int fValue;\n};\n\n// Or-ing a mask always returns another mask.\ntemplate<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,\n                                                                   GrTFlagsMask<TFlags> b) {\n    return GrTFlagsMask<TFlags>(a.value() | b.value());\n}\ntemplate<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,\n                                                                   TFlags b) {\n    return GrTFlagsMask<TFlags>(a.value() | static_cast<int>(b));\n}\ntemplate<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(TFlags a,\n                                                                   GrTFlagsMask<TFlags> b) {\n    return GrTFlagsMask<TFlags>(static_cast<int>(a) | b.value());\n}\ntemplate<typename TFlags> inline GrTFlagsMask<TFlags>& operator|=(GrTFlagsMask<TFlags>& a,\n                                                                  GrTFlagsMask<TFlags> b) {\n    return (a = a | b);\n}\n\n// And-ing two masks returns another mask; and-ing one with regular flags returns flags.\ntemplate<typename TFlags> constexpr GrTFlagsMask<TFlags> operator&(GrTFlagsMask<TFlags> a,\n                                                                   GrTFlagsMask<TFlags> b) {\n    return GrTFlagsMask<TFlags>(a.value() & b.value());\n}\ntemplate<typename TFlags> constexpr TFlags operator&(GrTFlagsMask<TFlags> a, TFlags b) {\n    return static_cast<TFlags>(a.value() & static_cast<int>(b));\n}\ntemplate<typename TFlags> constexpr TFlags operator&(TFlags a, GrTFlagsMask<TFlags> b) {\n    return static_cast<TFlags>(static_cast<int>(a) & b.value());\n}\ntemplate<typename TFlags> inline TFlags& operator&=(TFlags& a, GrTFlagsMask<TFlags> b) {\n    return (a = a & b);\n}\n\n/**\n * Defines bitwise operators that make it possible to use an enum class as a\n * basic bitfield.\n */\n#define GR_MAKE_BITFIELD_CLASS_OPS(X) \\\n    constexpr GrTFlagsMask<X> operator~(X a) { \\\n        return GrTFlagsMask<X>(~static_cast<int>(a)); \\\n    } \\\n    constexpr X operator|(X a, X b) { \\\n        return static_cast<X>(static_cast<int>(a) | static_cast<int>(b)); \\\n    } \\\n    inline X& operator|=(X& a, X b) { \\\n        return (a = a | b); \\\n    } \\\n    constexpr bool operator&(X a, X b) { \\\n        return SkToBool(static_cast<int>(a) & static_cast<int>(b)); \\\n    } \\\n\n#define GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(X) \\\n    friend constexpr GrTFlagsMask<X> operator ~(X); \\\n    friend constexpr X operator |(X, X); \\\n    friend X& operator |=(X&, X); \\\n    friend constexpr bool operator &(X, X);\n\n////////////////////////////////////////////////////////////////////////////////\n\n// compile time versions of min/max\n#define GR_CT_MAX(a, b) (((b) < (a)) ? (a) : (b))\n#define GR_CT_MIN(a, b) (((b) < (a)) ? (b) : (a))\n\n/**\n *  divide, rounding up\n */\nstatic inline int32_t GrIDivRoundUp(int x, int y) {\n    SkASSERT(y > 0);\n    return (x + (y-1)) / y;\n}\nstatic inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) {\n    return (x + (y-1)) / y;\n}\nstatic inline size_t GrSizeDivRoundUp(size_t x, size_t y) {\n    return (x + (y-1)) / y;\n}\n\n// compile time, evaluates Y multiple times\n#define GR_CT_DIV_ROUND_UP(X, Y) (((X) + ((Y)-1)) / (Y))\n\n/**\n *  align up\n */\nstatic inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) {\n    return GrUIDivRoundUp(x, alignment) * alignment;\n}\nstatic inline size_t GrSizeAlignUp(size_t x, size_t alignment) {\n    return GrSizeDivRoundUp(x, alignment) * alignment;\n}\n\n// compile time, evaluates A multiple times\n#define GR_CT_ALIGN_UP(X, A) (GR_CT_DIV_ROUND_UP((X),(A)) * (A))\n\n/**\n * amount of pad needed to align up\n */\nstatic inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) {\n    return (alignment - x % alignment) % alignment;\n}\nstatic inline size_t GrSizeAlignUpPad(size_t x, size_t alignment) {\n    return (alignment - x % alignment) % alignment;\n}\n\n/**\n *  align down\n */\nstatic inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) {\n    return (x / alignment) * alignment;\n}\nstatic inline size_t GrSizeAlignDown(size_t x, uint32_t alignment) {\n    return (x / alignment) * alignment;\n}\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Possible 3D APIs that may be used by Ganesh.\n */\nenum GrBackend {\n    kMetal_GrBackend,\n    kOpenGL_GrBackend,\n    kVulkan_GrBackend,\n    /**\n     * Mock is a backend that does not draw anything. It is used for unit tests\n     * and to measure CPU overhead.\n     */\n    kMock_GrBackend,\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Used to say whether a texture has mip levels allocated or not.\n */\nenum class GrMipMapped : bool {\n    kNo = false,\n    kYes = true\n};\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * GPU SkImage and SkSurfaces can be stored such that (0, 0) in texture space may correspond to\n * either the top-left or bottom-left content pixel.\n */\nenum GrSurfaceOrigin {\n    kTopLeft_GrSurfaceOrigin,\n    kBottomLeft_GrSurfaceOrigin,\n};\n\n/**\n * A GrContext's cache of backend context state can be partially invalidated.\n * These enums are specific to the GL backend and we'd add a new set for an alternative backend.\n */\nenum GrGLBackendState {\n    kRenderTarget_GrGLBackendState     = 1 << 0,\n    kTextureBinding_GrGLBackendState   = 1 << 1,\n    // View state stands for scissor and viewport\n    kView_GrGLBackendState             = 1 << 2,\n    kBlend_GrGLBackendState            = 1 << 3,\n    kMSAAEnable_GrGLBackendState       = 1 << 4,\n    kVertex_GrGLBackendState           = 1 << 5,\n    kStencil_GrGLBackendState          = 1 << 6,\n    kPixelStore_GrGLBackendState       = 1 << 7,\n    kProgram_GrGLBackendState          = 1 << 8,\n    kFixedFunction_GrGLBackendState    = 1 << 9,\n    kMisc_GrGLBackendState             = 1 << 10,\n    kPathRendering_GrGLBackendState    = 1 << 11,\n    kALL_GrGLBackendState              = 0xffff\n};\n\n/**\n * This value translates to reseting all the context state for any backend.\n */\nstatic const uint32_t kAll_GrBackendState = 0xffffffff;\n\n/**\n * Enum used as return value when flush with semaphores so the client knows whether the semaphores\n * were submitted to GPU or not.\n */\nenum class GrSemaphoresSubmitted : bool {\n    kNo = false,\n    kYes = true\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLAssembleInterface.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#include \"gl/GrGLInterface.h\"\n\ntypedef GrGLFuncPtr (*GrGLGetProc)(void* ctx, const char name[]);\n\n/**\n * Generic function for creating a GrGLInterface for an either OpenGL or GLES. It calls\n * get() to get each function address. ctx is a generic ptr passed to and interpreted by get().\n */\nSK_API sk_sp<const GrGLInterface> GrGLMakeAssembledInterface(void *ctx, GrGLGetProc get);\n\n/**\n * Generic function for creating a GrGLInterface for an OpenGL (but not GLES) context. It calls\n * get() to get each function address. ctx is a generic ptr passed to and interpreted by get().\n */\nSK_API sk_sp<const GrGLInterface> GrGLMakeAssembledGLInterface(void *ctx, GrGLGetProc get);\n\n/**\n * Generic function for creating a GrGLInterface for an OpenGL ES (but not Open GL) context. It\n * calls get() to get each function address. ctx is a generic ptr passed to and interpreted by\n * get().\n */\nSK_API sk_sp<const GrGLInterface> GrGLMakeAssembledGLESInterface(void *ctx, GrGLGetProc get);\n\n/** Deprecated version of GrGLMakeAssembledInterface() that returns a bare pointer. */\nSK_API const GrGLInterface* GrGLAssembleInterface(void *ctx, GrGLGetProc get);\n"
  },
  {
    "path": "include/gpu/gl/GrGLConfig.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n\n#ifndef GrGLConfig_DEFINED\n#define GrGLConfig_DEFINED\n\n#include \"GrTypes.h\"\n\n/**\n * Optional GL config file.\n */\n#ifdef GR_GL_CUSTOM_SETUP_HEADER\n    #include GR_GL_CUSTOM_SETUP_HEADER\n#endif\n\n#if !defined(GR_GL_FUNCTION_TYPE)\n    #if defined(SK_BUILD_FOR_WIN)\n        #define GR_GL_FUNCTION_TYPE __stdcall\n    #else\n        #define GR_GL_FUNCTION_TYPE\n    #endif\n#endif\n\n/**\n * The following are optional defines that can be enabled at the compiler\n * command line, in a IDE project, in a GrUserConfig.h file, or in a GL custom\n * file (if one is in use). If a GR_GL_CUSTOM_SETUP_HEADER is used they can\n * also be placed there.\n *\n * GR_GL_LOG_CALLS: if 1 Gr can print every GL call using SkDebugf. Defaults to\n * 0. Logging can be enabled and disabled at runtime using a debugger via to\n * global gLogCallsGL. The initial value of gLogCallsGL is controlled by\n * GR_GL_LOG_CALLS_START.\n *\n * GR_GL_LOG_CALLS_START: controls the initial value of gLogCallsGL when\n * GR_GL_LOG_CALLS is 1. Defaults to 0.\n *\n * GR_GL_CHECK_ERROR: if enabled Gr can do a glGetError() after every GL call.\n * Defaults to 1 if SK_DEBUG is set, otherwise 0. When GR_GL_CHECK_ERROR is 1\n * this can be toggled in a debugger using the gCheckErrorGL global. The initial\n * value of gCheckErrorGL is controlled by by GR_GL_CHECK_ERROR_START.\n *\n * GR_GL_CHECK_ERROR_START: controls the initial value of gCheckErrorGL\n * when GR_GL_CHECK_ERROR is 1.  Defaults to 1.\n *\n * GR_GL_USE_BUFFER_DATA_NULL_HINT: When specifing new data for a vertex/index\n * buffer that replaces old data Ganesh can give a hint to the driver that the\n * previous data will not be used in future draws like this:\n *  glBufferData(GL_..._BUFFER, size, NULL, usage);       //<--hint, NULL means\n *  glBufferSubData(GL_..._BUFFER, 0, lessThanSize, data) //   old data can't be\n *                                                        //   used again.\n * However, this can be an unoptimization on some platforms, esp. Chrome.\n * Chrome's cmd buffer will create a new allocation and memset the whole thing\n * to zero (for security reasons). Defaults to 1 (enabled).\n *\n * GR_GL_CHECK_ALLOC_WITH_GET_ERROR: If set to 1 this will then glTexImage,\n * glBufferData, glRenderbufferStorage, etc will be checked for errors. This\n * amounts to ensuring the error is GL_NO_ERROR, calling the allocating\n * function, and then checking that the error is still GL_NO_ERROR. When the\n * value is 0 we will assume no error was generated without checking.\n *\n * GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT: We will normally check the FBO status\n * every time we bind a texture or renderbuffer to an FBO. However, in some\n * environments CheckFrameBufferStatus is very expensive. If this is set we will\n * check the first time we use a color format or a combination of color /\n * stencil formats as attachments. If the FBO is complete we will assume\n * subsequent attachments with the same formats are complete as well.\n *\n * GR_GL_MUST_USE_VBO: Indicates that all vertices and indices must be rendered\n * from VBOs. Chromium's command buffer doesn't allow glVertexAttribArray with\n * ARARY_BUFFER 0 bound or glDrawElements with ELEMENT_ARRAY_BUFFER 0 bound.\n *\n * GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE is for compatibility with the new version\n * of the OpenGLES2.0 headers from Khronos.  glShaderSource now takes a const char * const *,\n * instead of a const char\n */\n\n#if !defined(GR_GL_LOG_CALLS)\n    #ifdef SK_DEBUG\n        #define GR_GL_LOG_CALLS 1\n    #else\n        #define GR_GL_LOG_CALLS 0\n    #endif\n#endif\n\n#if !defined(GR_GL_LOG_CALLS_START)\n    #define GR_GL_LOG_CALLS_START                       0\n#endif\n\n#if !defined(GR_GL_CHECK_ERROR)\n    #ifdef SK_DEBUG\n        #define GR_GL_CHECK_ERROR 1\n    #else\n        #define GR_GL_CHECK_ERROR 0\n    #endif\n#endif\n\n#if !defined(GR_GL_CHECK_ERROR_START)\n    #define GR_GL_CHECK_ERROR_START                     1\n#endif\n\n#if !defined(GR_GL_USE_BUFFER_DATA_NULL_HINT)\n    #define GR_GL_USE_BUFFER_DATA_NULL_HINT             1\n#endif\n\n#if !defined(GR_GL_CHECK_ALLOC_WITH_GET_ERROR)\n    #define GR_GL_CHECK_ALLOC_WITH_GET_ERROR            1\n#endif\n\n#if !defined(GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT)\n    #define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT      0\n#endif\n\n#if !defined(GR_GL_MUST_USE_VBO)\n    #define GR_GL_MUST_USE_VBO                          0\n#endif\n\n#if !defined(GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE)\n    #define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE       0\n#endif\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLConfig_chrome.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef GrGLConfig_chrome_DEFINED\n#define GrGLConfig_chrome_DEFINED\n\n// glGetError() forces a sync with gpu process on chrome\n#define GR_GL_CHECK_ERROR_START                     0\n\n// cmd buffer allocates memory and memsets it to zero when it sees glBufferData\n// with NULL.\n#define GR_GL_USE_BUFFER_DATA_NULL_HINT             0\n\n// Check error is even more expensive in chrome (cmd buffer flush). The\n// compositor also doesn't check its allocations.\n#define GR_GL_CHECK_ALLOC_WITH_GET_ERROR            0\n\n// CheckFramebufferStatus in chrome synchronizes the gpu and renderer processes.\n#define GR_GL_CHECK_FBO_STATUS_ONCE_PER_FORMAT      1\n\n// Non-VBO vertices and indices are not allowed in Chromium.\n#define GR_GL_MUST_USE_VBO                          1\n\n// Use updated Khronos signature for glShaderSource\n// (const char* const instead of char**).\n#define GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE       1\n\n#if !defined(GR_GL_IGNORE_ES3_MSAA)\n    #define GR_GL_IGNORE_ES3_MSAA 1\n#endif\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLExtensions.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGLExtensions_DEFINED\n#define GrGLExtensions_DEFINED\n\n#include \"../../private/SkTArray.h\"\n#include \"GrGLFunctions.h\"\n#include \"SkString.h\"\n\nstruct GrGLInterface;\nclass SkJSONWriter;\n\n/**\n * This helper queries the current GL context for its extensions, remembers them, and can be\n * queried. It supports both glGetString- and glGetStringi-style extension string APIs and will\n * use the latter if it is available. It also will query for EGL extensions if a eglQueryString\n * implementation is provided.\n */\nclass SK_API GrGLExtensions {\npublic:\n    GrGLExtensions() {}\n\n    GrGLExtensions(const GrGLExtensions&);\n\n    GrGLExtensions& operator=(const GrGLExtensions&);\n\n    void swap(GrGLExtensions* that) {\n        fStrings.swap(&that->fStrings);\n        SkTSwap(fInitialized, that->fInitialized);\n    }\n\n    /**\n     * We sometimes need to use this class without having yet created a GrGLInterface. This version\n     * of init expects that getString is always non-NULL while getIntegerv and getStringi are non-\n     * NULL if on desktop GL with version 3.0 or higher. Otherwise it will fail.\n     */\n    bool init(GrGLStandard standard,\n              GrGLFunction<GrGLGetStringProc> getString,\n              GrGLFunction<GrGLGetStringiProc> getStringi,\n              GrGLFunction<GrGLGetIntegervProc> getIntegerv,\n              GrGLFunction<GrEGLQueryStringProc> queryString = nullptr,\n              GrEGLDisplay eglDisplay = nullptr);\n\n    bool isInitialized() const { return fInitialized; }\n\n    /**\n     * Queries whether an extension is present. This will fail if init() has not been called.\n     */\n    bool has(const char[]) const;\n\n    /**\n     * Removes an extension if present. Returns true if the extension was present before the call.\n     */\n    bool remove(const char[]);\n\n    /**\n     * Adds an extension to list\n     */\n    void add(const char[]);\n\n    void reset() { fStrings.reset(); }\n\n    void dumpJSON(SkJSONWriter*) const;\n\nprivate:\n    bool fInitialized = false;\n    SkTArray<SkString> fStrings;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLFunctions.h",
    "content": "\n/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGLFunctions_DEFINED\n#define GrGLFunctions_DEFINED\n\n#include \"GrGLTypes.h\"\n#include \"../private/SkTLogic.h\"\n\nextern \"C\" {\n\n///////////////////////////////////////////////////////////////////////////////\n\ntypedef GrGLvoid (* GrGLActiveTextureProc)(GrGLenum texture);\ntypedef GrGLvoid (* GrGLAttachShaderProc)(GrGLuint program, GrGLuint shader);\ntypedef GrGLvoid (* GrGLBeginQueryProc)(GrGLenum target, GrGLuint id);\ntypedef GrGLvoid (* GrGLBindAttribLocationProc)(GrGLuint program, GrGLuint index, const char* name);\ntypedef GrGLvoid (* GrGLBindBufferProc)(GrGLenum target, GrGLuint buffer);\ntypedef GrGLvoid (* GrGLBindFramebufferProc)(GrGLenum target, GrGLuint framebuffer);\ntypedef GrGLvoid (* GrGLBindRenderbufferProc)(GrGLenum target, GrGLuint renderbuffer);\ntypedef GrGLvoid (* GrGLBindTextureProc)(GrGLenum target, GrGLuint texture);\ntypedef GrGLvoid (* GrGLBindFragDataLocationProc)(GrGLuint program, GrGLuint colorNumber, const GrGLchar* name);\ntypedef GrGLvoid (* GrGLBindFragDataLocationIndexedProc)(GrGLuint program, GrGLuint colorNumber, GrGLuint index, const GrGLchar * name);\ntypedef GrGLvoid (* GrGLBindVertexArrayProc)(GrGLuint array);\ntypedef GrGLvoid (* GrGLBlendBarrierProc)();\ntypedef GrGLvoid (* GrGLBlendColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha);\ntypedef GrGLvoid (* GrGLBlendEquationProc)(GrGLenum mode);\ntypedef GrGLvoid (* GrGLBlendFuncProc)(GrGLenum sfactor, GrGLenum dfactor);\ntypedef GrGLvoid (* GrGLBlitFramebufferProc)(GrGLint srcX0, GrGLint srcY0, GrGLint srcX1, GrGLint srcY1, GrGLint dstX0, GrGLint dstY0, GrGLint dstX1, GrGLint dstY1, GrGLbitfield mask, GrGLenum filter);\ntypedef GrGLvoid (* GrGLBufferDataProc)(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage);\ntypedef GrGLvoid (* GrGLBufferSubDataProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr size, const GrGLvoid* data);\ntypedef GrGLenum (* GrGLCheckFramebufferStatusProc)(GrGLenum target);\ntypedef GrGLvoid (* GrGLClearProc)(GrGLbitfield mask);\ntypedef GrGLvoid (* GrGLClearColorProc)(GrGLclampf red, GrGLclampf green, GrGLclampf blue, GrGLclampf alpha);\ntypedef GrGLvoid (* GrGLClearStencilProc)(GrGLint s);\ntypedef GrGLvoid (* GrGLClearTexImageProc)(GrGLuint texture, GrGLint level, GrGLenum format, GrGLenum type,const GrGLvoid * data);\ntypedef GrGLvoid (* GrGLClearTexSubImageProc)(GrGLuint texture, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLsizei width, GrGLsizei height, GrGLsizei depth, GrGLenum format, GrGLenum type,const GrGLvoid * data);\ntypedef GrGLvoid (* GrGLColorMaskProc)(GrGLboolean red, GrGLboolean green, GrGLboolean blue, GrGLboolean alpha);\ntypedef GrGLvoid (* GrGLCompileShaderProc)(GrGLuint shader);\ntypedef GrGLvoid (* GrGLCompressedTexImage2DProc)(GrGLenum target, GrGLint level, GrGLenum internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLsizei imageSize, const GrGLvoid* data);\ntypedef GrGLvoid (* GrGLCompressedTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLsizei imageSize, const GrGLvoid* data);\ntypedef GrGLvoid (* GrGLCopyTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);\ntypedef GrGLuint (* GrGLCreateProgramProc)();\ntypedef GrGLuint (* GrGLCreateShaderProc)(GrGLenum type);\ntypedef GrGLvoid (* GrGLCullFaceProc)(GrGLenum mode);\ntypedef GrGLvoid (* GrGLDeleteBuffersProc)(GrGLsizei n, const GrGLuint* buffers);\ntypedef GrGLvoid (* GrGLDeleteFramebuffersProc)(GrGLsizei n, const GrGLuint *framebuffers);\ntypedef GrGLvoid (* GrGLDeleteProgramProc)(GrGLuint program);\ntypedef GrGLvoid (* GrGLDeleteQueriesProc)(GrGLsizei n, const GrGLuint *ids);\ntypedef GrGLvoid (* GrGLDeleteRenderbuffersProc)(GrGLsizei n, const GrGLuint *renderbuffers);\ntypedef GrGLvoid (* GrGLDeleteShaderProc)(GrGLuint shader);\ntypedef GrGLvoid (* GrGLDeleteTexturesProc)(GrGLsizei n, const GrGLuint* textures);\ntypedef GrGLvoid (* GrGLDeleteVertexArraysProc)(GrGLsizei n, const GrGLuint *arrays);\ntypedef GrGLvoid (* GrGLDepthMaskProc)(GrGLboolean flag);\ntypedef GrGLvoid (* GrGLDisableProc)(GrGLenum cap);\ntypedef GrGLvoid (* GrGLDisableVertexAttribArrayProc)(GrGLuint index);\ntypedef GrGLvoid (* GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count);\ntypedef GrGLvoid (* GrGLDrawArraysInstancedProc)(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount);\ntypedef GrGLvoid (* GrGLDrawArraysIndirectProc)(GrGLenum mode, const GrGLvoid* indirect);\ntypedef GrGLvoid (* GrGLDrawBufferProc)(GrGLenum mode);\ntypedef GrGLvoid (* GrGLDrawBuffersProc)(GrGLsizei n, const GrGLenum* bufs);\ntypedef GrGLvoid (* GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);\ntypedef GrGLvoid (* GrGLDrawElementsInstancedProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount);\ntypedef GrGLvoid (* GrGLDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, const GrGLvoid* indirect);\ntypedef GrGLvoid (* GrGLDrawRangeElementsProc)(GrGLenum mode, GrGLuint start, GrGLuint end, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);\ntypedef GrGLvoid (* GrGLEnableProc)(GrGLenum cap);\ntypedef GrGLvoid (* GrGLEnableVertexAttribArrayProc)(GrGLuint index);\ntypedef GrGLvoid (* GrGLEndQueryProc)(GrGLenum target);\ntypedef GrGLvoid (* GrGLFinishProc)();\ntypedef GrGLvoid (* GrGLFlushProc)();\ntypedef GrGLvoid (* GrGLFlushMappedBufferRangeProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length);\ntypedef GrGLvoid (* GrGLFramebufferRenderbufferProc)(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer);\ntypedef GrGLvoid (* GrGLFramebufferTexture2DProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level);\ntypedef GrGLvoid (* GrGLFramebufferTexture2DMultisampleProc)(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level, GrGLsizei samples);\ntypedef GrGLvoid (* GrGLFrontFaceProc)(GrGLenum mode);\ntypedef GrGLvoid (* GrGLGenBuffersProc)(GrGLsizei n, GrGLuint* buffers);\ntypedef GrGLvoid (* GrGLGenFramebuffersProc)(GrGLsizei n, GrGLuint *framebuffers);\ntypedef GrGLvoid (* GrGLGenerateMipmapProc)(GrGLenum target);\ntypedef GrGLvoid (* GrGLGenQueriesProc)(GrGLsizei n, GrGLuint *ids);\ntypedef GrGLvoid (* GrGLGenRenderbuffersProc)(GrGLsizei n, GrGLuint *renderbuffers);\ntypedef GrGLvoid (* GrGLGenTexturesProc)(GrGLsizei n, GrGLuint* textures);\ntypedef GrGLvoid (* GrGLGenVertexArraysProc)(GrGLsizei n, GrGLuint *arrays);\ntypedef GrGLvoid (* GrGLGetBufferParameterivProc)(GrGLenum target, GrGLenum pname, GrGLint* params);\ntypedef GrGLenum (* GrGLGetErrorProc)();\ntypedef GrGLvoid (* GrGLGetFramebufferAttachmentParameterivProc)(GrGLenum target, GrGLenum attachment, GrGLenum pname, GrGLint* params);\ntypedef GrGLvoid (* GrGLGetIntegervProc)(GrGLenum pname, GrGLint* params);\ntypedef GrGLvoid (* GrGLGetMultisamplefvProc)(GrGLenum pname, GrGLuint index, GrGLfloat* val);\ntypedef GrGLvoid (* GrGLGetProgramBinaryProc)(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, GrGLenum *binaryFormat, void *binary);\ntypedef GrGLvoid (* GrGLGetProgramInfoLogProc)(GrGLuint program, GrGLsizei bufsize, GrGLsizei* length, char* infolog);\ntypedef GrGLvoid (* GrGLGetProgramivProc)(GrGLuint program, GrGLenum pname, GrGLint* params);\ntypedef GrGLvoid (* GrGLGetQueryivProc)(GrGLenum GLtarget, GrGLenum pname, GrGLint *params);\ntypedef GrGLvoid (* GrGLGetQueryObjecti64vProc)(GrGLuint id, GrGLenum pname, GrGLint64 *params);\ntypedef GrGLvoid (* GrGLGetQueryObjectivProc)(GrGLuint id, GrGLenum pname, GrGLint *params);\ntypedef GrGLvoid (* GrGLGetQueryObjectui64vProc)(GrGLuint id, GrGLenum pname, GrGLuint64 *params);\ntypedef GrGLvoid (* GrGLGetQueryObjectuivProc)(GrGLuint id, GrGLenum pname, GrGLuint *params);\ntypedef GrGLvoid (* GrGLGetRenderbufferParameterivProc)(GrGLenum target, GrGLenum pname, GrGLint* params);\ntypedef GrGLvoid (* GrGLGetShaderInfoLogProc)(GrGLuint shader, GrGLsizei bufsize, GrGLsizei* length, char* infolog);\ntypedef GrGLvoid (* GrGLGetShaderivProc)(GrGLuint shader, GrGLenum pname, GrGLint* params);\ntypedef GrGLvoid (* GrGLGetShaderPrecisionFormatProc)(GrGLenum shadertype, GrGLenum precisiontype, GrGLint *range, GrGLint *precision);\ntypedef const GrGLubyte* (* GrGLGetStringProc)(GrGLenum name);\ntypedef const GrGLubyte* (* GrGLGetStringiProc)(GrGLenum name, GrGLuint index);\ntypedef GrGLvoid (* GrGLGetTexLevelParameterivProc)(GrGLenum target, GrGLint level, GrGLenum pname, GrGLint* params);\ntypedef GrGLint (* GrGLGetUniformLocationProc)(GrGLuint program, const char* name);\ntypedef GrGLvoid (* GrGLInsertEventMarkerProc)(GrGLsizei length, const char* marker);\ntypedef GrGLvoid (* GrGLInvalidateBufferDataProc)(GrGLuint buffer);\ntypedef GrGLvoid (* GrGLInvalidateBufferSubDataProc)(GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr length);\ntypedef GrGLvoid (* GrGLInvalidateFramebufferProc)(GrGLenum target, GrGLsizei numAttachments,  const GrGLenum *attachments);\ntypedef GrGLvoid (* GrGLInvalidateSubFramebufferProc)(GrGLenum target, GrGLsizei numAttachments, const GrGLenum *attachments, GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);\ntypedef GrGLvoid (* GrGLInvalidateTexImageProc)(GrGLuint texture, GrGLint level);\ntypedef GrGLvoid (* GrGLInvalidateTexSubImageProc)(GrGLuint texture, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLint zoffset, GrGLsizei width, GrGLsizei height, GrGLsizei depth);\ntypedef GrGLboolean (* GrGLIsTextureProc)(GrGLuint texture);\ntypedef GrGLvoid (* GrGLLineWidthProc)(GrGLfloat width);\ntypedef GrGLvoid (* GrGLLinkProgramProc)(GrGLuint program);\ntypedef GrGLvoid* (* GrGLMapBufferProc)(GrGLenum target, GrGLenum access);\ntypedef GrGLvoid* (* GrGLMapBufferRangeProc)(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access);\ntypedef GrGLvoid* (* GrGLMapBufferSubDataProc)(GrGLuint target, GrGLintptr offset, GrGLsizeiptr size, GrGLenum access);\ntypedef GrGLvoid* (* GrGLMapTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLenum access);\ntypedef GrGLvoid (* GrGLPixelStoreiProc)(GrGLenum pname, GrGLint param);\ntypedef GrGLvoid (* GrGLPolygonModeProc)(GrGLenum face, GrGLenum mode);\ntypedef GrGLvoid (* GrGLPopGroupMarkerProc)();\ntypedef GrGLvoid (* GrGLProgramBinaryProc)(GrGLuint program, GrGLenum binaryFormat, void *binary, GrGLsizei length);\ntypedef GrGLvoid (* GrGLProgramParameteriProc)(GrGLuint program, GrGLenum pname, GrGLint value);\ntypedef GrGLvoid (* GrGLPushGroupMarkerProc)(GrGLsizei length, const char* marker);\ntypedef GrGLvoid (* GrGLQueryCounterProc)(GrGLuint id, GrGLenum target);\ntypedef GrGLvoid (* GrGLRasterSamplesProc)(GrGLuint samples, GrGLboolean fixedsamplelocations);\ntypedef GrGLvoid (* GrGLReadBufferProc)(GrGLenum src);\ntypedef GrGLvoid (* GrGLReadPixelsProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLvoid* pixels);\ntypedef GrGLvoid (* GrGLRenderbufferStorageProc)(GrGLenum target, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);\ntypedef GrGLvoid (* GrGLRenderbufferStorageMultisampleProc)(GrGLenum target, GrGLsizei samples, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);\ntypedef GrGLvoid (* GrGLResolveMultisampleFramebufferProc)();\ntypedef GrGLvoid (* GrGLScissorProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);\n// GL_CHROMIUM_bind_uniform_location\ntypedef GrGLvoid (* GrGLBindUniformLocationProc)(GrGLuint program, GrGLint location, const char* name);\n\n#if GR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE\ntypedef GrGLvoid (* GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char* const * str, const GrGLint* length);\n#else\ntypedef GrGLvoid (* GrGLShaderSourceProc)(GrGLuint shader, GrGLsizei count, const char** str, const GrGLint* length);\n#endif\ntypedef GrGLvoid (* GrGLStencilFuncProc)(GrGLenum func, GrGLint ref, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilFuncSeparateProc)(GrGLenum face, GrGLenum func, GrGLint ref, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilMaskProc)(GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilMaskSeparateProc)(GrGLenum face, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilOpProc)(GrGLenum fail, GrGLenum zfail, GrGLenum zpass);\ntypedef GrGLvoid (* GrGLStencilOpSeparateProc)(GrGLenum face, GrGLenum fail, GrGLenum zfail, GrGLenum zpass);\ntypedef GrGLvoid (* GrGLTexBufferProc)(GrGLenum target, GrGLenum internalformat, GrGLuint buffer);\ntypedef GrGLvoid (* GrGLTexBufferRangeProc)(GrGLenum target, GrGLenum internalformat, GrGLuint buffer, GrGLintptr offset, GrGLsizeiptr size);\ntypedef GrGLvoid (* GrGLTexImage2DProc)(GrGLenum target, GrGLint level, GrGLint internalformat, GrGLsizei width, GrGLsizei height, GrGLint border, GrGLenum format, GrGLenum type, const GrGLvoid* pixels);\ntypedef GrGLvoid (* GrGLTexParameteriProc)(GrGLenum target, GrGLenum pname, GrGLint param);\ntypedef GrGLvoid (* GrGLTexParameterivProc)(GrGLenum target, GrGLenum pname, const GrGLint* params);\ntypedef GrGLvoid (* GrGLTexStorage2DProc)(GrGLenum target, GrGLsizei levels, GrGLenum internalformat, GrGLsizei width, GrGLsizei height);\ntypedef GrGLvoid (* GrGLDiscardFramebufferProc)(GrGLenum target, GrGLsizei numAttachments, const GrGLenum* attachments);\ntypedef GrGLvoid (* GrGLTexSubImage2DProc)(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, const GrGLvoid* pixels);\ntypedef GrGLvoid (* GrGLTextureBarrierProc)();\ntypedef GrGLvoid (* GrGLUniform1fProc)(GrGLint location, GrGLfloat v0);\ntypedef GrGLvoid (* GrGLUniform1iProc)(GrGLint location, GrGLint v0);\ntypedef GrGLvoid (* GrGLUniform1fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);\ntypedef GrGLvoid (* GrGLUniform1ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);\ntypedef GrGLvoid (* GrGLUniform2fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1);\ntypedef GrGLvoid (* GrGLUniform2iProc)(GrGLint location, GrGLint v0, GrGLint v1);\ntypedef GrGLvoid (* GrGLUniform2fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);\ntypedef GrGLvoid (* GrGLUniform2ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);\ntypedef GrGLvoid (* GrGLUniform3fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2);\ntypedef GrGLvoid (* GrGLUniform3iProc)(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2);\ntypedef GrGLvoid (* GrGLUniform3fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);\ntypedef GrGLvoid (* GrGLUniform3ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);\ntypedef GrGLvoid (* GrGLUniform4fProc)(GrGLint location, GrGLfloat v0, GrGLfloat v1, GrGLfloat v2, GrGLfloat v3);\ntypedef GrGLvoid (* GrGLUniform4iProc)(GrGLint location, GrGLint v0, GrGLint v1, GrGLint v2, GrGLint v3);\ntypedef GrGLvoid (* GrGLUniform4fvProc)(GrGLint location, GrGLsizei count, const GrGLfloat* v);\ntypedef GrGLvoid (* GrGLUniform4ivProc)(GrGLint location, GrGLsizei count, const GrGLint* v);\ntypedef GrGLvoid (* GrGLUniformMatrix2fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);\ntypedef GrGLvoid (* GrGLUniformMatrix3fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);\ntypedef GrGLvoid (* GrGLUniformMatrix4fvProc)(GrGLint location, GrGLsizei count, GrGLboolean transpose, const GrGLfloat* value);\ntypedef GrGLboolean (* GrGLUnmapBufferProc)(GrGLenum target);\ntypedef GrGLvoid (* GrGLUnmapBufferSubDataProc)(const GrGLvoid* mem);\ntypedef GrGLvoid (* GrGLUnmapTexSubImage2DProc)(const GrGLvoid* mem);\ntypedef GrGLvoid (* GrGLUseProgramProc)(GrGLuint program);\ntypedef GrGLvoid (* GrGLVertexAttrib1fProc)(GrGLuint indx, const GrGLfloat value);\ntypedef GrGLvoid (* GrGLVertexAttrib2fvProc)(GrGLuint indx, const GrGLfloat* values);\ntypedef GrGLvoid (* GrGLVertexAttrib3fvProc)(GrGLuint indx, const GrGLfloat* values);\ntypedef GrGLvoid (* GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values);\ntypedef GrGLvoid (* GrGLVertexAttribDivisorProc)(GrGLuint index, GrGLuint divisor);\ntypedef GrGLvoid (* GrGLVertexAttribIPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLsizei stride, const GrGLvoid* ptr);\ntypedef GrGLvoid (* GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr);\ntypedef GrGLvoid (* GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);\n\n/* GL_NV_path_rendering */\ntypedef GrGLvoid (* GrGLMatrixLoadfProc)(GrGLenum matrixMode, const GrGLfloat* m);\ntypedef GrGLvoid (* GrGLMatrixLoadIdentityProc)(GrGLenum);\ntypedef GrGLvoid (* GrGLPathCommandsProc)(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);\ntypedef GrGLvoid (* GrGLPathParameteriProc)(GrGLuint path, GrGLenum pname, GrGLint value);\ntypedef GrGLvoid (* GrGLPathParameterfProc)(GrGLuint path, GrGLenum pname, GrGLfloat value);\ntypedef GrGLuint (* GrGLGenPathsProc)(GrGLsizei range);\ntypedef GrGLvoid (* GrGLDeletePathsProc)(GrGLuint path, GrGLsizei range);\ntypedef GrGLboolean (* GrGLIsPathProc)(GrGLuint path);\ntypedef GrGLvoid (* GrGLPathStencilFuncProc)(GrGLenum func, GrGLint ref, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilFillPathProc)(GrGLuint path, GrGLenum fillMode, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilStrokePathProc)(GrGLuint path, GrGLint reference, GrGLuint mask);\ntypedef GrGLvoid (* GrGLStencilFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);\ntypedef GrGLvoid (* GrGLStencilStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);\ntypedef GrGLvoid (* GrGLCoverFillPathProc)(GrGLuint path, GrGLenum coverMode);\ntypedef GrGLvoid (* GrGLCoverStrokePathProc)(GrGLuint name, GrGLenum coverMode);\ntypedef GrGLvoid (* GrGLCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);\ntypedef GrGLvoid (* GrGLCoverStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues);\n// NV_path_rendering v1.2\ntypedef GrGLvoid (* GrGLStencilThenCoverFillPathProc)(GrGLuint path, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode);\ntypedef GrGLvoid (* GrGLStencilThenCoverStrokePathProc)(GrGLuint path, GrGLint reference, GrGLuint mask, GrGLenum coverMode);\ntypedef GrGLvoid (* GrGLStencilThenCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);\ntypedef GrGLvoid (* GrGLStencilThenCoverStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);\n// NV_path_rendering v1.3\ntypedef GrGLvoid (* GrGLProgramPathFragmentInputGenProc)(GrGLuint program, GrGLint location, GrGLenum genMode, GrGLint components,const GrGLfloat *coeffs);\n// CHROMIUM_path_rendering\ntypedef GrGLvoid (* GrGLBindFragmentInputLocationProc)(GrGLuint program, GrGLint location, const GrGLchar* name);\n\n/* ARB_program_interface_query */\ntypedef GrGLint (* GrGLGetProgramResourceLocationProc)(GrGLuint program, GrGLenum programInterface, const GrGLchar *name);\n\n/* GL_NV_framebuffer_mixed_samples */\ntypedef GrGLvoid (* GrGLCoverageModulationProc)(GrGLenum components);\n\n/* EXT_multi_draw_indirect */\ntypedef GrGLvoid (* GrGLMultiDrawArraysIndirectProc)(GrGLenum mode, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);\ntypedef GrGLvoid (* GrGLMultiDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);\n\n/* ARB_sample_shading */\ntypedef GrGLvoid (* GrGLMinSampleShadingProc)(GrGLfloat value);\n\n/* ARB_sync */\ntypedef GrGLsync (* GrGLFenceSyncProc)(GrGLenum condition, GrGLbitfield flags);\ntypedef GrGLboolean (* GrGLIsSyncProc)(GrGLsync sync);\ntypedef GrGLenum (* GrGLClientWaitSyncProc)(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout);\ntypedef GrGLvoid (* GrGLWaitSyncProc)(GrGLsync sync, GrGLbitfield flags, GrGLuint64 timeout);\ntypedef GrGLvoid (* GrGLDeleteSyncProc)(GrGLsync sync);\n\n/* ARB_internalformat_query */\ntypedef GrGLvoid (* GrGLGetInternalformativProc)(GrGLenum target, GrGLenum internalformat, GrGLenum pname, GrGLsizei bufSize, GrGLint *params);\n\n/* KHR_debug */\ntypedef GrGLvoid (* GrGLDebugMessageControlProc)(GrGLenum source, GrGLenum type, GrGLenum severity, GrGLsizei count, const GrGLuint* ids, GrGLboolean enabled);\ntypedef GrGLvoid (* GrGLDebugMessageInsertProc)(GrGLenum source, GrGLenum type, GrGLuint id, GrGLenum severity, GrGLsizei length,  const GrGLchar* buf);\ntypedef GrGLvoid (* GrGLDebugMessageCallbackProc)(GRGLDEBUGPROC callback, const GrGLvoid* userParam);\ntypedef GrGLuint (* GrGLGetDebugMessageLogProc)(GrGLuint count, GrGLsizei bufSize, GrGLenum* sources, GrGLenum* types, GrGLuint* ids, GrGLenum* severities, GrGLsizei* lengths,  GrGLchar* messageLog);\ntypedef GrGLvoid (* GrGLPushDebugGroupProc)(GrGLenum source, GrGLuint id, GrGLsizei length,  const GrGLchar * message);\ntypedef GrGLvoid (* GrGLPopDebugGroupProc)();\ntypedef GrGLvoid (* GrGLObjectLabelProc)(GrGLenum identifier, GrGLuint name, GrGLsizei length, const GrGLchar *label);\n\n/** EXT_window_rectangles */\ntypedef GrGLvoid (* GrGLWindowRectanglesProc)(GrGLenum mode, GrGLsizei count, const GrGLint box[]);\n\n/** EGL functions */\ntypedef const char* (* GrEGLQueryStringProc)(GrEGLDisplay dpy, GrEGLint name);\ntypedef GrEGLDisplay (* GrEGLGetCurrentDisplayProc)();\ntypedef GrEGLImage (* GrEGLCreateImageProc)(GrEGLDisplay dpy, GrEGLContext ctx, GrEGLenum target, GrEGLClientBuffer buffer, const GrEGLint *attrib_list);\ntypedef GrEGLBoolean (* GrEGLDestroyImageProc)(GrEGLDisplay dpy, GrEGLImage image);\n}  // extern \"C\"\n\n// This is a lighter-weight std::function, trying to reduce code size and compile time\n// by only supporting the exact use cases we require.\ntemplate <typename T> class GrGLFunction;\n\ntemplate <typename R, typename... Args>\nclass GrGLFunction<R(*)(Args...)>{\npublic:\n    // Construct empty.\n    GrGLFunction() : fCall(nullptr) {}\n    GrGLFunction(std::nullptr_t) : GrGLFunction() {}\n\n    // Construct from a simple function pointer.\n    GrGLFunction(R (GR_GL_FUNCTION_TYPE* fn_ptr)(Args...)) : GrGLFunction() {\n        if (fn_ptr) {\n            memcpy(fBuf, &fn_ptr, sizeof(fn_ptr));\n            fCall = [](const void* buf, Args... args) {\n                auto fn_ptr = *(R (GR_GL_FUNCTION_TYPE**)(Args...))buf;\n                return fn_ptr(args...);\n            };\n        }\n    }\n\n    // Construct from a small closure.\n    template <typename Closure>\n    GrGLFunction(Closure closure) : GrGLFunction() {\n        static_assert(sizeof(Closure) <= sizeof(fBuf), \"fBuf is too small\");\n    #if defined(__APPLE__)   // I am having serious trouble getting these to work with all STLs...\n        static_assert(std::is_trivially_copyable<Closure>::value, \"\");\n        static_assert(std::is_trivially_destructible<Closure>::value, \"\");\n    #endif\n\n        memcpy(fBuf, &closure, sizeof(closure));\n        fCall = [](const void* buf, Args... args) {\n            auto closure = (const Closure*)buf;\n            return (*closure)(args...);\n        };\n    }\n\n    R operator()(Args... args) const {\n        SkASSERT(fCall);\n        return fCall(fBuf, args...);\n    }\n\n    explicit operator bool() const {\n        return fCall != nullptr;\n    }\n\nprivate:\n    R (*fCall)(const void*, Args...);\n    size_t fBuf[4];\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLInterface.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGLInterface_DEFINED\n#define GrGLInterface_DEFINED\n\n#include \"GrGLFunctions.h\"\n#include \"GrGLExtensions.h\"\n#include \"SkRefCnt.h\"\n\n////////////////////////////////////////////////////////////////////////////////\n\ntypedef void(*GrGLFuncPtr)();\nstruct GrGLInterface;\n\n\n/**\n * Rather than depend on platform-specific GL headers and libraries, we require\n * the client to provide a struct of GL function pointers. This struct can be\n * specified per-GrContext as a parameter to GrContext::MakeGL. If no interface is\n * passed to MakeGL then a default GL interface is created using GrGLMakeNativeInterface().\n * If this returns nullptr then GrContext::MakeGL() will fail.\n *\n * The implementation of GrGLMakeNativeInterface is platform-specific. Several\n * implementations have been provided (for GLX, WGL, EGL, etc), along with an\n * implementation that simply returns nullptr. Clients should select the most\n * appropriate one to build.\n */\nSK_API sk_sp<const GrGLInterface> GrGLMakeNativeInterface();\n// Deprecated alternative to GrGLMakeNativeInterface().\nSK_API const GrGLInterface* GrGLCreateNativeInterface();\n\n/**\n * Creates a null GrGLInterface that doesn't draw anything. Used for measuring\n * CPU overhead. TODO: We would like to move this to tools/gpu/gl/null but currently\n * Chromium is using it in its unit tests.\n */\nconst SK_API GrGLInterface* GrGLCreateNullInterface(bool enableNVPR = false);\n\n/**\n * GrContext uses the following interface to make all calls into OpenGL. When a\n * GrContext is created it is given a GrGLInterface. The interface's function\n * pointers must be valid for the OpenGL context associated with the GrContext.\n * On some platforms, such as Windows, function pointers for OpenGL extensions\n * may vary between OpenGL contexts. So the caller must be careful to use a\n * GrGLInterface initialized for the correct context. All functions that should\n * be available based on the OpenGL's version and extension string must be\n * non-NULL or GrContext creation will fail. This can be tested with the\n * validate() method when the OpenGL context has been made current.\n */\nstruct SK_API GrGLInterface : public SkRefCnt {\nprivate:\n    typedef SkRefCnt INHERITED;\n\npublic:\n    GrGLInterface();\n\n    // Validates that the GrGLInterface supports its advertised standard. This means the necessary\n    // function pointers have been initialized for both the GL version and any advertised\n    // extensions.\n    bool validate() const;\n\n    // Indicates the type of GL implementation\n    union {\n        GrGLStandard fStandard;\n        GrGLStandard fBindingsExported; // Legacy name, will be remove when Chromium is updated.\n    };\n\n    GrGLExtensions fExtensions;\n\n    bool hasExtension(const char ext[]) const { return fExtensions.has(ext); }\n\n    /**\n     * The function pointers are in a struct so that we can have a compiler generated assignment\n     * operator.\n     */\n    struct Functions {\n        GrGLFunction<GrGLActiveTextureProc> fActiveTexture;\n        GrGLFunction<GrGLAttachShaderProc> fAttachShader;\n        GrGLFunction<GrGLBeginQueryProc> fBeginQuery;\n        GrGLFunction<GrGLBindAttribLocationProc> fBindAttribLocation;\n        GrGLFunction<GrGLBindBufferProc> fBindBuffer;\n        GrGLFunction<GrGLBindFragDataLocationProc> fBindFragDataLocation;\n        GrGLFunction<GrGLBindFragDataLocationIndexedProc> fBindFragDataLocationIndexed;\n        GrGLFunction<GrGLBindFramebufferProc> fBindFramebuffer;\n        GrGLFunction<GrGLBindRenderbufferProc> fBindRenderbuffer;\n        GrGLFunction<GrGLBindTextureProc> fBindTexture;\n        GrGLFunction<GrGLBindVertexArrayProc> fBindVertexArray;\n        GrGLFunction<GrGLBlendBarrierProc> fBlendBarrier;\n        GrGLFunction<GrGLBlendColorProc> fBlendColor;\n        GrGLFunction<GrGLBlendEquationProc> fBlendEquation;\n        GrGLFunction<GrGLBlendFuncProc> fBlendFunc;\n        GrGLFunction<GrGLBlitFramebufferProc> fBlitFramebuffer;\n        GrGLFunction<GrGLBufferDataProc> fBufferData;\n        GrGLFunction<GrGLBufferSubDataProc> fBufferSubData;\n        GrGLFunction<GrGLCheckFramebufferStatusProc> fCheckFramebufferStatus;\n        GrGLFunction<GrGLClearProc> fClear;\n        GrGLFunction<GrGLClearColorProc> fClearColor;\n        GrGLFunction<GrGLClearStencilProc> fClearStencil;\n        GrGLFunction<GrGLClearTexImageProc> fClearTexImage;\n        GrGLFunction<GrGLClearTexSubImageProc> fClearTexSubImage;\n        GrGLFunction<GrGLColorMaskProc> fColorMask;\n        GrGLFunction<GrGLCompileShaderProc> fCompileShader;\n        GrGLFunction<GrGLCompressedTexImage2DProc> fCompressedTexImage2D;\n        GrGLFunction<GrGLCompressedTexSubImage2DProc> fCompressedTexSubImage2D;\n        GrGLFunction<GrGLCopyTexSubImage2DProc> fCopyTexSubImage2D;\n        GrGLFunction<GrGLCreateProgramProc> fCreateProgram;\n        GrGLFunction<GrGLCreateShaderProc> fCreateShader;\n        GrGLFunction<GrGLCullFaceProc> fCullFace;\n        GrGLFunction<GrGLDeleteBuffersProc> fDeleteBuffers;\n        GrGLFunction<GrGLDeleteFramebuffersProc> fDeleteFramebuffers;\n        GrGLFunction<GrGLDeleteProgramProc> fDeleteProgram;\n        GrGLFunction<GrGLDeleteQueriesProc> fDeleteQueries;\n        GrGLFunction<GrGLDeleteRenderbuffersProc> fDeleteRenderbuffers;\n        GrGLFunction<GrGLDeleteShaderProc> fDeleteShader;\n        GrGLFunction<GrGLDeleteTexturesProc> fDeleteTextures;\n        GrGLFunction<GrGLDeleteVertexArraysProc> fDeleteVertexArrays;\n        GrGLFunction<GrGLDepthMaskProc> fDepthMask;\n        GrGLFunction<GrGLDisableProc> fDisable;\n        GrGLFunction<GrGLDisableVertexAttribArrayProc> fDisableVertexAttribArray;\n        GrGLFunction<GrGLDrawArraysProc> fDrawArrays;\n        GrGLFunction<GrGLDrawArraysIndirectProc> fDrawArraysIndirect;\n        GrGLFunction<GrGLDrawArraysInstancedProc> fDrawArraysInstanced;\n        GrGLFunction<GrGLDrawBufferProc> fDrawBuffer;\n        GrGLFunction<GrGLDrawBuffersProc> fDrawBuffers;\n        GrGLFunction<GrGLDrawElementsProc> fDrawElements;\n        GrGLFunction<GrGLDrawElementsIndirectProc> fDrawElementsIndirect;\n        GrGLFunction<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;\n        GrGLFunction<GrGLDrawRangeElementsProc> fDrawRangeElements;\n        GrGLFunction<GrGLEnableProc> fEnable;\n        GrGLFunction<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;\n        GrGLFunction<GrGLEndQueryProc> fEndQuery;\n        GrGLFunction<GrGLFinishProc> fFinish;\n        GrGLFunction<GrGLFlushProc> fFlush;\n        GrGLFunction<GrGLFlushMappedBufferRangeProc> fFlushMappedBufferRange;\n        GrGLFunction<GrGLFramebufferRenderbufferProc> fFramebufferRenderbuffer;\n        GrGLFunction<GrGLFramebufferTexture2DProc> fFramebufferTexture2D;\n        GrGLFunction<GrGLFramebufferTexture2DMultisampleProc> fFramebufferTexture2DMultisample;\n        GrGLFunction<GrGLFrontFaceProc> fFrontFace;\n        GrGLFunction<GrGLGenBuffersProc> fGenBuffers;\n        GrGLFunction<GrGLGenFramebuffersProc> fGenFramebuffers;\n        GrGLFunction<GrGLGenerateMipmapProc> fGenerateMipmap;\n        GrGLFunction<GrGLGenQueriesProc> fGenQueries;\n        GrGLFunction<GrGLGenRenderbuffersProc> fGenRenderbuffers;\n        GrGLFunction<GrGLGenTexturesProc> fGenTextures;\n        GrGLFunction<GrGLGenVertexArraysProc> fGenVertexArrays;\n        GrGLFunction<GrGLGetBufferParameterivProc> fGetBufferParameteriv;\n        GrGLFunction<GrGLGetErrorProc> fGetError;\n        GrGLFunction<GrGLGetFramebufferAttachmentParameterivProc> fGetFramebufferAttachmentParameteriv;\n        GrGLFunction<GrGLGetIntegervProc> fGetIntegerv;\n        GrGLFunction<GrGLGetMultisamplefvProc> fGetMultisamplefv;\n        GrGLFunction<GrGLGetProgramBinaryProc> fGetProgramBinary;\n        GrGLFunction<GrGLGetProgramInfoLogProc> fGetProgramInfoLog;\n        GrGLFunction<GrGLGetProgramivProc> fGetProgramiv;\n        GrGLFunction<GrGLGetQueryObjecti64vProc> fGetQueryObjecti64v;\n        GrGLFunction<GrGLGetQueryObjectivProc> fGetQueryObjectiv;\n        GrGLFunction<GrGLGetQueryObjectui64vProc> fGetQueryObjectui64v;\n        GrGLFunction<GrGLGetQueryObjectuivProc> fGetQueryObjectuiv;\n        GrGLFunction<GrGLGetQueryivProc> fGetQueryiv;\n        GrGLFunction<GrGLGetRenderbufferParameterivProc> fGetRenderbufferParameteriv;\n        GrGLFunction<GrGLGetShaderInfoLogProc> fGetShaderInfoLog;\n        GrGLFunction<GrGLGetShaderivProc> fGetShaderiv;\n        GrGLFunction<GrGLGetShaderPrecisionFormatProc> fGetShaderPrecisionFormat;\n        GrGLFunction<GrGLGetStringProc> fGetString;\n        GrGLFunction<GrGLGetStringiProc> fGetStringi;\n        GrGLFunction<GrGLGetTexLevelParameterivProc> fGetTexLevelParameteriv;\n        GrGLFunction<GrGLGetUniformLocationProc> fGetUniformLocation;\n        GrGLFunction<GrGLInsertEventMarkerProc> fInsertEventMarker;\n        GrGLFunction<GrGLInvalidateBufferDataProc> fInvalidateBufferData;\n        GrGLFunction<GrGLInvalidateBufferSubDataProc> fInvalidateBufferSubData;\n        GrGLFunction<GrGLInvalidateFramebufferProc> fInvalidateFramebuffer;\n        GrGLFunction<GrGLInvalidateSubFramebufferProc> fInvalidateSubFramebuffer;\n        GrGLFunction<GrGLInvalidateTexImageProc> fInvalidateTexImage;\n        GrGLFunction<GrGLInvalidateTexSubImageProc> fInvalidateTexSubImage;\n        GrGLFunction<GrGLIsTextureProc> fIsTexture;\n        GrGLFunction<GrGLLineWidthProc> fLineWidth;\n        GrGLFunction<GrGLLinkProgramProc> fLinkProgram;\n        GrGLFunction<GrGLProgramBinaryProc> fProgramBinary;\n        GrGLFunction<GrGLProgramParameteriProc> fProgramParameteri;\n        GrGLFunction<GrGLMapBufferProc> fMapBuffer;\n        GrGLFunction<GrGLMapBufferRangeProc> fMapBufferRange;\n        GrGLFunction<GrGLMapBufferSubDataProc> fMapBufferSubData;\n        GrGLFunction<GrGLMapTexSubImage2DProc> fMapTexSubImage2D;\n        GrGLFunction<GrGLMultiDrawArraysIndirectProc> fMultiDrawArraysIndirect;\n        GrGLFunction<GrGLMultiDrawElementsIndirectProc> fMultiDrawElementsIndirect;\n        GrGLFunction<GrGLPixelStoreiProc> fPixelStorei;\n        GrGLFunction<GrGLPolygonModeProc> fPolygonMode;\n        GrGLFunction<GrGLPopGroupMarkerProc> fPopGroupMarker;\n        GrGLFunction<GrGLPushGroupMarkerProc> fPushGroupMarker;\n        GrGLFunction<GrGLQueryCounterProc> fQueryCounter;\n        GrGLFunction<GrGLRasterSamplesProc> fRasterSamples;\n        GrGLFunction<GrGLReadBufferProc> fReadBuffer;\n        GrGLFunction<GrGLReadPixelsProc> fReadPixels;\n        GrGLFunction<GrGLRenderbufferStorageProc> fRenderbufferStorage;\n\n        //  On OpenGL ES there are multiple incompatible extensions that add support for MSAA\n        //  and ES3 adds MSAA support to the standard. On an ES3 driver we may still use the\n        //  older extensions for performance reasons or due to ES3 driver bugs. We want the function\n        //  that creates the GrGLInterface to provide all available functions and internally\n        //  we will select among them. They all have a method called glRenderbufferStorageMultisample*.\n        //  So we have separate function pointers for GL_IMG/EXT_multisampled_to_texture,\n        //  GL_CHROMIUM/ANGLE_framebuffer_multisample/ES3, and GL_APPLE_framebuffer_multisample\n        //  variations.\n        //\n        //  If a driver supports multiple GL_ARB_framebuffer_multisample-style extensions then we will\n        //  assume the function pointers for the standard (or equivalent GL_ARB) version have\n        //  been preferred over GL_EXT, GL_CHROMIUM, or GL_ANGLE variations that have reduced\n        //  functionality.\n\n        //  GL_EXT_multisampled_render_to_texture (preferred) or GL_IMG_multisampled_render_to_texture\n        GrGLFunction<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisampleES2EXT;\n        //  GL_APPLE_framebuffer_multisample\n        GrGLFunction<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisampleES2APPLE;\n\n        //  This is used to store the pointer for GL_ARB/EXT/ANGLE/CHROMIUM_framebuffer_multisample or\n        //  the standard function in ES3+ or GL 3.0+.\n        GrGLFunction<GrGLRenderbufferStorageMultisampleProc> fRenderbufferStorageMultisample;\n\n        // Pointer to BindUniformLocationCHROMIUM from the GL_CHROMIUM_bind_uniform_location extension.\n        GrGLFunction<GrGLBindUniformLocationProc> fBindUniformLocation;\n\n        GrGLFunction<GrGLResolveMultisampleFramebufferProc> fResolveMultisampleFramebuffer;\n        GrGLFunction<GrGLScissorProc> fScissor;\n        GrGLFunction<GrGLShaderSourceProc> fShaderSource;\n        GrGLFunction<GrGLStencilFuncProc> fStencilFunc;\n        GrGLFunction<GrGLStencilFuncSeparateProc> fStencilFuncSeparate;\n        GrGLFunction<GrGLStencilMaskProc> fStencilMask;\n        GrGLFunction<GrGLStencilMaskSeparateProc> fStencilMaskSeparate;\n        GrGLFunction<GrGLStencilOpProc> fStencilOp;\n        GrGLFunction<GrGLStencilOpSeparateProc> fStencilOpSeparate;\n        GrGLFunction<GrGLTexBufferProc> fTexBuffer;\n        GrGLFunction<GrGLTexBufferRangeProc> fTexBufferRange;\n        GrGLFunction<GrGLTexImage2DProc> fTexImage2D;\n        GrGLFunction<GrGLTexParameteriProc> fTexParameteri;\n        GrGLFunction<GrGLTexParameterivProc> fTexParameteriv;\n        GrGLFunction<GrGLTexSubImage2DProc> fTexSubImage2D;\n        GrGLFunction<GrGLTexStorage2DProc> fTexStorage2D;\n        GrGLFunction<GrGLTextureBarrierProc> fTextureBarrier;\n        GrGLFunction<GrGLDiscardFramebufferProc> fDiscardFramebuffer;\n        GrGLFunction<GrGLUniform1fProc> fUniform1f;\n        GrGLFunction<GrGLUniform1iProc> fUniform1i;\n        GrGLFunction<GrGLUniform1fvProc> fUniform1fv;\n        GrGLFunction<GrGLUniform1ivProc> fUniform1iv;\n        GrGLFunction<GrGLUniform2fProc> fUniform2f;\n        GrGLFunction<GrGLUniform2iProc> fUniform2i;\n        GrGLFunction<GrGLUniform2fvProc> fUniform2fv;\n        GrGLFunction<GrGLUniform2ivProc> fUniform2iv;\n        GrGLFunction<GrGLUniform3fProc> fUniform3f;\n        GrGLFunction<GrGLUniform3iProc> fUniform3i;\n        GrGLFunction<GrGLUniform3fvProc> fUniform3fv;\n        GrGLFunction<GrGLUniform3ivProc> fUniform3iv;\n        GrGLFunction<GrGLUniform4fProc> fUniform4f;\n        GrGLFunction<GrGLUniform4iProc> fUniform4i;\n        GrGLFunction<GrGLUniform4fvProc> fUniform4fv;\n        GrGLFunction<GrGLUniform4ivProc> fUniform4iv;\n        GrGLFunction<GrGLUniformMatrix2fvProc> fUniformMatrix2fv;\n        GrGLFunction<GrGLUniformMatrix3fvProc> fUniformMatrix3fv;\n        GrGLFunction<GrGLUniformMatrix4fvProc> fUniformMatrix4fv;\n        GrGLFunction<GrGLUnmapBufferProc> fUnmapBuffer;\n        GrGLFunction<GrGLUnmapBufferSubDataProc> fUnmapBufferSubData;\n        GrGLFunction<GrGLUnmapTexSubImage2DProc> fUnmapTexSubImage2D;\n        GrGLFunction<GrGLUseProgramProc> fUseProgram;\n        GrGLFunction<GrGLVertexAttrib1fProc> fVertexAttrib1f;\n        GrGLFunction<GrGLVertexAttrib2fvProc> fVertexAttrib2fv;\n        GrGLFunction<GrGLVertexAttrib3fvProc> fVertexAttrib3fv;\n        GrGLFunction<GrGLVertexAttrib4fvProc> fVertexAttrib4fv;\n        GrGLFunction<GrGLVertexAttribDivisorProc> fVertexAttribDivisor;\n        GrGLFunction<GrGLVertexAttribIPointerProc> fVertexAttribIPointer;\n        GrGLFunction<GrGLVertexAttribPointerProc> fVertexAttribPointer;\n        GrGLFunction<GrGLViewportProc> fViewport;\n\n        /* GL_NV_path_rendering */\n        GrGLFunction<GrGLMatrixLoadfProc> fMatrixLoadf;\n        GrGLFunction<GrGLMatrixLoadIdentityProc> fMatrixLoadIdentity;\n        GrGLFunction<GrGLGetProgramResourceLocationProc> fGetProgramResourceLocation;\n        GrGLFunction<GrGLPathCommandsProc> fPathCommands;\n        GrGLFunction<GrGLPathParameteriProc> fPathParameteri;\n        GrGLFunction<GrGLPathParameterfProc> fPathParameterf;\n        GrGLFunction<GrGLGenPathsProc> fGenPaths;\n        GrGLFunction<GrGLDeletePathsProc> fDeletePaths;\n        GrGLFunction<GrGLIsPathProc> fIsPath;\n        GrGLFunction<GrGLPathStencilFuncProc> fPathStencilFunc;\n        GrGLFunction<GrGLStencilFillPathProc> fStencilFillPath;\n        GrGLFunction<GrGLStencilStrokePathProc> fStencilStrokePath;\n        GrGLFunction<GrGLStencilFillPathInstancedProc> fStencilFillPathInstanced;\n        GrGLFunction<GrGLStencilStrokePathInstancedProc> fStencilStrokePathInstanced;\n        GrGLFunction<GrGLCoverFillPathProc> fCoverFillPath;\n        GrGLFunction<GrGLCoverStrokePathProc> fCoverStrokePath;\n        GrGLFunction<GrGLCoverFillPathInstancedProc> fCoverFillPathInstanced;\n        GrGLFunction<GrGLCoverStrokePathInstancedProc> fCoverStrokePathInstanced;\n        // NV_path_rendering v1.2\n        GrGLFunction<GrGLStencilThenCoverFillPathProc> fStencilThenCoverFillPath;\n        GrGLFunction<GrGLStencilThenCoverStrokePathProc> fStencilThenCoverStrokePath;\n        GrGLFunction<GrGLStencilThenCoverFillPathInstancedProc> fStencilThenCoverFillPathInstanced;\n        GrGLFunction<GrGLStencilThenCoverStrokePathInstancedProc> fStencilThenCoverStrokePathInstanced;\n        // NV_path_rendering v1.3\n        GrGLFunction<GrGLProgramPathFragmentInputGenProc> fProgramPathFragmentInputGen;\n        // CHROMIUM_path_rendering\n        GrGLFunction<GrGLBindFragmentInputLocationProc> fBindFragmentInputLocation;\n\n        /* NV_framebuffer_mixed_samples */\n        GrGLFunction<GrGLCoverageModulationProc> fCoverageModulation;\n\n        /* ARB_sample_shading */\n        GrGLFunction<GrGLMinSampleShadingProc> fMinSampleShading;\n\n        /* ARB_sync */\n        GrGLFunction<GrGLFenceSyncProc> fFenceSync;\n        GrGLFunction<GrGLIsSyncProc> fIsSync;\n        GrGLFunction<GrGLClientWaitSyncProc> fClientWaitSync;\n        GrGLFunction<GrGLWaitSyncProc> fWaitSync;\n        GrGLFunction<GrGLDeleteSyncProc> fDeleteSync;\n\n        /* ARB_internalforamt_query */\n        GrGLFunction<GrGLGetInternalformativProc> fGetInternalformativ;\n\n        /* KHR_debug */\n        GrGLFunction<GrGLDebugMessageControlProc> fDebugMessageControl;\n        GrGLFunction<GrGLDebugMessageInsertProc> fDebugMessageInsert;\n        GrGLFunction<GrGLDebugMessageCallbackProc> fDebugMessageCallback;\n        GrGLFunction<GrGLGetDebugMessageLogProc> fGetDebugMessageLog;\n        GrGLFunction<GrGLPushDebugGroupProc> fPushDebugGroup;\n        GrGLFunction<GrGLPopDebugGroupProc> fPopDebugGroup;\n        GrGLFunction<GrGLObjectLabelProc> fObjectLabel;\n\n        /* EXT_window_rectangles */\n        GrGLFunction<GrGLWindowRectanglesProc> fWindowRectangles;\n\n        /* EGL functions */\n        GrGLFunction<GrEGLCreateImageProc> fEGLCreateImage;\n        GrGLFunction<GrEGLDestroyImageProc> fEGLDestroyImage;\n    } fFunctions;\n\n    // This exists for internal testing.\n    virtual void abandon() const {}\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/gl/GrGLTypes.h",
    "content": "\n/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGLTypes_DEFINED\n#define GrGLTypes_DEFINED\n\n#include \"GrGLConfig.h\"\n#include \"SkRefCnt.h\"\n\n/**\n * Classifies GL contexts by which standard they implement (currently as OpenGL vs. OpenGL ES).\n */\nenum GrGLStandard {\n    kNone_GrGLStandard,\n    kGL_GrGLStandard,\n    kGLES_GrGLStandard,\n};\nstatic const int kGrGLStandardCnt = 3;\n\n///////////////////////////////////////////////////////////////////////////////\n\n/**\n * Declares typedefs for all the GL functions used in GrGLInterface\n */\n\ntypedef unsigned int GrGLenum;\ntypedef unsigned char GrGLboolean;\ntypedef unsigned int GrGLbitfield;\ntypedef signed char GrGLbyte;\ntypedef char GrGLchar;\ntypedef short GrGLshort;\ntypedef int GrGLint;\ntypedef int GrGLsizei;\ntypedef int64_t GrGLint64;\ntypedef unsigned char GrGLubyte;\ntypedef unsigned short GrGLushort;\ntypedef unsigned int GrGLuint;\ntypedef uint64_t GrGLuint64;\ntypedef float GrGLfloat;\ntypedef float GrGLclampf;\ntypedef double GrGLdouble;\ntypedef double GrGLclampd;\ntypedef void GrGLvoid;\n#ifndef SK_IGNORE_64BIT_OPENGL_CHANGES\n#ifdef _WIN64\ntypedef signed long long int GrGLintptr;\ntypedef signed long long int GrGLsizeiptr;\n#else\ntypedef signed long int GrGLintptr;\ntypedef signed long int GrGLsizeiptr;\n#endif\n#else\ntypedef signed long int GrGLintptr;\ntypedef signed long int GrGLsizeiptr;\n#endif\ntypedef void* GrGLeglImage;\ntypedef struct __GLsync* GrGLsync;\n\nstruct GrGLDrawArraysIndirectCommand {\n    GrGLuint fCount;\n    GrGLuint fInstanceCount;\n    GrGLuint fFirst;\n    GrGLuint fBaseInstance;  // Requires EXT_base_instance on ES.\n};\n\nGR_STATIC_ASSERT(16 == sizeof(GrGLDrawArraysIndirectCommand));\n\nstruct GrGLDrawElementsIndirectCommand {\n    GrGLuint fCount;\n    GrGLuint fInstanceCount;\n    GrGLuint fFirstIndex;\n    GrGLuint fBaseVertex;\n    GrGLuint fBaseInstance;  // Requires EXT_base_instance on ES.\n};\n\nGR_STATIC_ASSERT(20 == sizeof(GrGLDrawElementsIndirectCommand));\n\n/**\n * KHR_debug\n */\ntypedef void (GR_GL_FUNCTION_TYPE* GRGLDEBUGPROC)(GrGLenum source,\n                                                  GrGLenum type,\n                                                  GrGLuint id,\n                                                  GrGLenum severity,\n                                                  GrGLsizei length,\n                                                  const GrGLchar* message,\n                                                  const void* userParam);\n\n/**\n * EGL types.\n */\ntypedef void* GrEGLImage;\ntypedef void* GrEGLDisplay;\ntypedef void* GrEGLContext;\ntypedef void* GrEGLClientBuffer;\ntypedef unsigned int GrEGLenum;\ntypedef int32_t GrEGLint;\ntypedef unsigned int GrEGLBoolean;\n\n///////////////////////////////////////////////////////////////////////////////\n/**\n * Types for interacting with GL resources created externally to Skia. GrBackendObjects for GL\n * textures are really const GrGLTexture*. The fFormat here should be a sized, internal format\n * for the texture. We will try to use the sized format if the GL Context supports it, otherwise\n * we will internally fall back to using the base internal formats.\n */\nstruct GrGLTextureInfo {\n    GrGLenum fTarget;\n    GrGLuint fID;\n    GrGLenum fFormat = 0;\n\n    bool operator==(const GrGLTextureInfo& that) const {\n        return fTarget == that.fTarget && fID == that.fID && fFormat == that.fFormat;\n    }\n};\n\nstruct GrGLFramebufferInfo {\n    GrGLuint fFBOID;\n    GrGLenum fFormat = 0;\n\n    bool operator==(const GrGLFramebufferInfo& that) const {\n        return fFBOID == that.fFBOID && fFormat == that.fFormat;\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/mock/GrMockTypes.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrMockOptions_DEFINED\n#define GrMockOptions_DEFINED\n\n#include \"GrTypes.h\"\n#include \"../private/GrTypesPriv.h\"\n\nstruct GrMockTextureInfo {\n    GrPixelConfig fConfig;\n    int fID;\n\n    bool operator==(const GrMockTextureInfo& that) const {\n        return fConfig == that.fConfig && fID == that.fID;\n    }\n};\n\nstruct GrMockRenderTargetInfo {\n    GrPixelConfig fConfig;\n    int fID;\n\n    bool operator==(const GrMockRenderTargetInfo& that) const {\n        return fConfig == that.fConfig && fID == that.fID;\n    }\n};\n\n/**\n * A pointer to this type is used as the GrBackendContext when creating a Mock GrContext. It can be\n * used to specify capability options for the mock context. If nullptr is used a default constructed\n * GrMockOptions is used.\n */\nstruct GrMockOptions {\n    GrMockOptions() {\n        using Renderability = ConfigOptions::Renderability;\n        // By default RGBA_8888 is textureable and renderable and A8 and RGB565 are texturable.\n        fConfigOptions[kRGBA_8888_GrPixelConfig].fRenderability = Renderability::kNonMSAA;\n        fConfigOptions[kRGBA_8888_GrPixelConfig].fTexturable = true;\n        fConfigOptions[kAlpha_8_GrPixelConfig].fTexturable = true;\n        fConfigOptions[kAlpha_8_as_Alpha_GrPixelConfig].fTexturable = true;\n        fConfigOptions[kAlpha_8_as_Red_GrPixelConfig].fTexturable = true;\n        fConfigOptions[kRGB_565_GrPixelConfig].fTexturable = true;\n    }\n\n    struct ConfigOptions {\n        enum Renderability { kNo, kNonMSAA, kMSAA };\n        Renderability fRenderability;\n        bool fTexturable = false;\n    };\n\n    // GrCaps options.\n    bool fInstanceAttribSupport = false;\n    uint32_t fMapBufferFlags = 0;\n    int fMaxTextureSize = 2048;\n    int fMaxRenderTargetSize = 2048;\n    int fMaxVertexAttributes = 16;\n    ConfigOptions fConfigOptions[kGrPixelConfigCnt];\n\n    // GrShaderCaps options.\n    bool fGeometryShaderSupport = false;\n    bool fTexelBufferSupport = false;\n    bool fIntegerSupport = false;\n    bool fFlatInterpolationSupport = false;\n    int fMaxVertexSamplers = 0;\n    int fMaxFragmentSamplers = 8;\n    bool fShaderDerivativeSupport = true;\n\n    // GrMockGpu options.\n    bool fFailTextureAllocations = false;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/mtl/GrMtlTypes.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrMtlTypes_DEFINED\n#define GrMtlTypes_DEFINED\n\n#include \"GrTypes.h\"\n\n// This is a placeholder class until we fill it out. This is needed so we can have the mtl include\n// path in our BUILD.gn\n\n#endif\n"
  },
  {
    "path": "include/gpu/vk/GrVkBackendContext.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkBackendContext_DEFINED\n#define GrVkBackendContext_DEFINED\n\n#include \"SkRefCnt.h\"\n\n#include \"vk/GrVkDefines.h\"\n#include \"vk/GrVkInterface.h\"\n#include \"vk/GrVkMemoryAllocator.h\"\n\nenum GrVkExtensionFlags {\n    kEXT_debug_report_GrVkExtensionFlag    = 0x0001,\n    kNV_glsl_shader_GrVkExtensionFlag      = 0x0002,\n    kKHR_surface_GrVkExtensionFlag         = 0x0004,\n    kKHR_swapchain_GrVkExtensionFlag       = 0x0008,\n    kKHR_win32_surface_GrVkExtensionFlag   = 0x0010,\n    kKHR_android_surface_GrVkExtensionFlag = 0x0020,\n    kKHR_xcb_surface_GrVkExtensionFlag     = 0x0040,\n};\n\nenum GrVkFeatureFlags {\n    kGeometryShader_GrVkFeatureFlag    = 0x0001,\n    kDualSrcBlend_GrVkFeatureFlag      = 0x0002,\n    kSampleRateShading_GrVkFeatureFlag = 0x0004,\n};\n\n// The BackendContext contains all of the base Vulkan objects needed by the GrVkGpu. The assumption\n// is that the client will set these up and pass them to the GrVkGpu constructor. The VkDevice\n// created must support at least one graphics queue, which is passed in as well.\n// The QueueFamilyIndex must match the family of the given queue. It is needed for CommandPool\n// creation, and any GrBackendObjects handed to us (e.g., for wrapped textures) need to be created\n// in or transitioned to that family.\nstruct SK_API GrVkBackendContext : public SkRefCnt {\n    VkInstance                 fInstance;\n    VkPhysicalDevice           fPhysicalDevice;\n    VkDevice                   fDevice;\n    VkQueue                    fQueue;\n    uint32_t                   fGraphicsQueueIndex;\n    uint32_t                   fMinAPIVersion;\n    uint32_t                   fExtensions;\n    uint32_t                   fFeatures;\n    sk_sp<const GrVkInterface> fInterface;\n    sk_sp<GrVkMemoryAllocator> fMemoryAllocator;\n\n    /**\n     * Controls whether this object destroys the instance and device upon destruction. The default\n     * is temporarily 'true' to avoid breaking existing clients but will be changed to 'false'.\n     */\n    bool                       fOwnsInstanceAndDevice = true;\n\n    using CanPresentFn = std::function<bool(VkInstance, VkPhysicalDevice,\n                                            uint32_t queueFamilyIndex)>;\n\n    /**\n     * Helper function to create the Vulkan objects needed for a Vulkan-backed GrContext.\n     * Note that the version that uses the unified \"GetProc\" instead of separate \"GetInstanceProc\"\n     * and \"GetDeviceProc\" functions will be removed.\n     *\n     * If presentQueueIndex is non-NULL, will try to set up presentQueue as part of device\n     * creation using the platform-specific canPresent() function.\n     *\n     * This will set fOwnsInstanceAndDevice to 'true'. If it is subsequently set to 'false' then\n     * the client owns the lifetime of the created VkDevice and VkInstance.\n     */\n    static const GrVkBackendContext* Create(uint32_t* presentQueueIndex = nullptr,\n                                            CanPresentFn = CanPresentFn(),\n                                            GrVkInterface::GetProc getProc = nullptr);\n\n    static const GrVkBackendContext* Create(const GrVkInterface::GetInstanceProc& getInstanceProc,\n                                            const GrVkInterface::GetDeviceProc& getDeviceProc,\n                                            uint32_t* presentQueueIndex = nullptr,\n                                            CanPresentFn canPresent = CanPresentFn()) {\n        if (!getInstanceProc || !getDeviceProc) {\n            return nullptr;\n        }\n        auto getProc = [&getInstanceProc, &getDeviceProc](const char* proc_name,\n                                                          VkInstance instance, VkDevice device) {\n            if (device != VK_NULL_HANDLE) {\n                return getDeviceProc(device, proc_name);\n            }\n            return getInstanceProc(instance, proc_name);\n        };\n        return Create(presentQueueIndex, canPresent, getProc);\n    }\n\n    ~GrVkBackendContext() override;\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/vk/GrVkDefines.h",
    "content": "\n/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkDefines_DEFINED\n#define GrVkDefines_DEFINED\n\n#ifdef SK_VULKAN\n\n#ifdef SK_VULKAN_HEADER\n#include SK_VULKAN_HEADER // IWYU pragma: export\n#else\n// This is deprecated and all clients should define their own custum header shim that sets up\n// defines and includes the vulkan.h header. Then they should define SK_VULKAN_HEADER or set the\n// skia_vulkan_header in gn to point to their custom header.\n#  if defined(SK_BUILD_FOR_WIN)\n#     if !defined(VK_USE_PLATFORM_WIN32_KHR)\n#        define VK_USE_PLATFORM_WIN32_KHR\n#     endif\n#  elif defined(SK_BUILD_FOR_ANDROID)\n#     if !defined(VK_USE_PLATFORM_ANDROID_KHR)\n#        define VK_USE_PLATFORM_ANDROID_KHR\n#     endif\n#  elif defined(SK_BUILD_FOR_UNIX)\n#     if defined(__Fuchsia__)\n#       if !defined(VK_USE_PLATFORM_MAGMA_KHR)\n#         define VK_USE_PLATFORM_MAGMA_KHR\n#       endif\n#     else\n#       if !defined(VK_USE_PLATFORM_XCB_KHR)\n#          define VK_USE_PLATFORM_XCB_KHR\n#       endif\n#     endif\n#  endif\n\n// We create our own function table and never directly call any functions via vk*(). So no need to\n// include the prototype functions.\n#  if !defined(VK_NO_PROTOTYPES) && !defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)\n#    define VK_NO_PROTOTYPES\n#  endif\n\n#  include <vulkan/vulkan.h> // IWYU pragma: export\n#endif // SK_VULKAN_HEADER\n\n#define SKIA_REQUIRED_VULKAN_HEADER_VERSION 17\n#if VK_HEADER_VERSION < SKIA_REQUIRED_VULKAN_HEADER_VERSION\n#error \"Vulkan header version is too low\"\n#endif\n\n// The AMD VulkanMemoryAllocator needs the objects from this extension to be declared.\n#ifndef VK_KHR_get_memory_requirements2\n\n#define VK_KHR_get_memory_requirements2 1\n#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_SPEC_VERSION 1\n#define VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME \"VK_KHR_get_memory_requirements2\"\n\ntypedef struct VkBufferMemoryRequirementsInfo2KHR {\n    VkStructureType    sType;\n    const void*        pNext;\n    VkBuffer           buffer;\n} VkBufferMemoryRequirementsInfo2KHR;\n\ntypedef struct VkImageMemoryRequirementsInfo2KHR {\n    VkStructureType    sType;\n    const void*        pNext;\n    VkImage            image;\n} VkImageMemoryRequirementsInfo2KHR;\n\ntypedef struct VkImageSparseMemoryRequirementsInfo2KHR {\n    VkStructureType    sType;\n    const void*        pNext;\n    VkImage            image;\n} VkImageSparseMemoryRequirementsInfo2KHR;\n\ntypedef struct VkMemoryRequirements2KHR {\n    VkStructureType         sType;\n    void*                   pNext;\n    VkMemoryRequirements    memoryRequirements;\n} VkMemoryRequirements2KHR;\n\ntypedef struct VkSparseImageMemoryRequirements2KHR {\n    VkStructureType                    sType;\n    void*                              pNext;\n    VkSparseImageMemoryRequirements    memoryRequirements;\n} VkSparseImageMemoryRequirements2KHR;\n\n\ntypedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements2KHR)(VkDevice device, const VkImageMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);\ntypedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements2KHR)(VkDevice device, const VkBufferMemoryRequirementsInfo2KHR* pInfo, VkMemoryRequirements2KHR* pMemoryRequirements);\ntypedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements2KHR)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2KHR* pInfo, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements);\n\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = (VkStructureType) 1000146000;\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR = (VkStructureType) 1000146001;\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_IMAGE_SPARSE_MEMORY_REQUIREMENTS_INFO_2_KHR = (VkStructureType) 1000146002;\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR = (VkStructureType) 1000146003;\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_SPARSE_IMAGE_MEMORY_REQUIREMENTS_2_KHR = (VkStructureType) 1000146004;\n\n#endif // VK_KHR_get_memory_requirements2\n\n// Also needed for VulkanMemoryAllocator\n#ifndef VK_KHR_dedicated_allocation\n\n#define VK_KHR_dedicated_allocation 1\n#define VK_KHR_DEDICATED_ALLOCATION_SPEC_VERSION 3\n#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME \"VK_KHR_dedicated_allocation\"\n\ntypedef struct VkMemoryDedicatedRequirementsKHR {\n    VkStructureType    sType;\n    void*              pNext;\n    VkBool32           prefersDedicatedAllocation;\n    VkBool32           requiresDedicatedAllocation;\n} VkMemoryDedicatedRequirementsKHR;\n\ntypedef struct VkMemoryDedicatedAllocateInfoKHR {\n    VkStructureType    sType;\n    const void*        pNext;\n    VkImage            image;\n    VkBuffer           buffer;\n} VkMemoryDedicatedAllocateInfoKHR;\n\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = (VkStructureType) 1000127000;\nstatic constexpr VkStructureType VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = (VkStructureType) 1000127001;\n\n#endif // VK_KHR_dedicated_allocation\n\n#endif\n\n#endif\n"
  },
  {
    "path": "include/gpu/vk/GrVkInterface.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkInterface_DEFINED\n#define GrVkInterface_DEFINED\n\n#include \"SkRefCnt.h\"\n\n#include \"vk/GrVkDefines.h\"\n\n////////////////////////////////////////////////////////////////////////////////\n\n/**\n * GrContext uses the following interface to make all calls into Vulkan. When a\n * GrContext is created it is given a GrVkInterface. All functions that should be\n * available based on the Vulkan's version must be non-NULL or GrContext creation\n * will fail. This can be tested with the validate() method.\n */\nstruct SK_API GrVkInterface : public SkRefCnt {\nprivate:\n    // simple wrapper class that exists only to initialize a pointer to NULL\n    template <typename FNPTR_TYPE> class VkPtr {\n    public:\n        VkPtr() : fPtr(NULL) {}\n        VkPtr operator=(FNPTR_TYPE ptr) { fPtr = ptr; return *this; }\n        operator FNPTR_TYPE() const { return fPtr; }\n    private:\n        FNPTR_TYPE fPtr;\n    };\n\n    typedef SkRefCnt INHERITED;\n\npublic:\n    using GetProc = std::function<PFN_vkVoidFunction(\n        const char*, // function name\n        VkInstance,  // instance or VK_NULL_HANDLE\n        VkDevice     // device or VK_NULL_HANDLE\n        )>;\n\n    // This is typically vkGetInstanceProcAddr.\n    using GetInstanceProc = std::function<PFN_vkVoidFunction(VkInstance, const char*)>;\n\n    // This is typically vkGetDeviceProcAddr.\n    using GetDeviceProc = std::function<PFN_vkVoidFunction(VkDevice, const char*)>;\n\n    GrVkInterface(GetProc getProc,\n                  VkInstance instance,\n                  VkDevice device,\n                  uint32_t extensionFlags);\n\n    GrVkInterface(const GetInstanceProc&,\n                  const GetDeviceProc&,\n                  VkInstance instance,\n                  VkDevice device,\n                  uint32_t extensionFlags);\n\n    // Validates that the GrVkInterface supports its advertised standard. This means the necessary\n    // function pointers have been initialized for Vulkan version.\n    bool validate(uint32_t extensionFlags) const;\n\n    /**\n     * The function pointers are in a struct so that we can have a compiler generated assignment\n     * operator.\n     */\n    struct Functions {\n        VkPtr<PFN_vkCreateInstance> fCreateInstance;\n        VkPtr<PFN_vkDestroyInstance> fDestroyInstance;\n        VkPtr<PFN_vkEnumeratePhysicalDevices> fEnumeratePhysicalDevices;\n        VkPtr<PFN_vkGetPhysicalDeviceFeatures> fGetPhysicalDeviceFeatures;\n        VkPtr<PFN_vkGetPhysicalDeviceFormatProperties> fGetPhysicalDeviceFormatProperties;\n        VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties> fGetPhysicalDeviceImageFormatProperties;\n        VkPtr<PFN_vkGetPhysicalDeviceProperties> fGetPhysicalDeviceProperties;\n        VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> fGetPhysicalDeviceQueueFamilyProperties;\n        VkPtr<PFN_vkGetPhysicalDeviceMemoryProperties> fGetPhysicalDeviceMemoryProperties;\n        VkPtr<PFN_vkCreateDevice> fCreateDevice;\n        VkPtr<PFN_vkDestroyDevice> fDestroyDevice;\n        VkPtr<PFN_vkEnumerateInstanceExtensionProperties> fEnumerateInstanceExtensionProperties;\n        VkPtr<PFN_vkEnumerateDeviceExtensionProperties> fEnumerateDeviceExtensionProperties;\n        VkPtr<PFN_vkEnumerateInstanceLayerProperties> fEnumerateInstanceLayerProperties;\n        VkPtr<PFN_vkEnumerateDeviceLayerProperties> fEnumerateDeviceLayerProperties;\n        VkPtr<PFN_vkGetDeviceQueue> fGetDeviceQueue;\n        VkPtr<PFN_vkQueueSubmit> fQueueSubmit;\n        VkPtr<PFN_vkQueueWaitIdle> fQueueWaitIdle;\n        VkPtr<PFN_vkDeviceWaitIdle> fDeviceWaitIdle;\n        VkPtr<PFN_vkAllocateMemory> fAllocateMemory;\n        VkPtr<PFN_vkFreeMemory> fFreeMemory;\n        VkPtr<PFN_vkMapMemory> fMapMemory;\n        VkPtr<PFN_vkUnmapMemory> fUnmapMemory;\n        VkPtr<PFN_vkFlushMappedMemoryRanges> fFlushMappedMemoryRanges;\n        VkPtr<PFN_vkInvalidateMappedMemoryRanges> fInvalidateMappedMemoryRanges;\n        VkPtr<PFN_vkGetDeviceMemoryCommitment> fGetDeviceMemoryCommitment;\n        VkPtr<PFN_vkBindBufferMemory> fBindBufferMemory;\n        VkPtr<PFN_vkBindImageMemory> fBindImageMemory;\n        VkPtr<PFN_vkGetBufferMemoryRequirements> fGetBufferMemoryRequirements;\n        VkPtr<PFN_vkGetImageMemoryRequirements> fGetImageMemoryRequirements;\n        VkPtr<PFN_vkGetImageSparseMemoryRequirements> fGetImageSparseMemoryRequirements;\n        VkPtr<PFN_vkGetPhysicalDeviceSparseImageFormatProperties> fGetPhysicalDeviceSparseImageFormatProperties;\n        VkPtr<PFN_vkQueueBindSparse> fQueueBindSparse;\n        VkPtr<PFN_vkCreateFence> fCreateFence;\n        VkPtr<PFN_vkDestroyFence> fDestroyFence;\n        VkPtr<PFN_vkResetFences> fResetFences;\n        VkPtr<PFN_vkGetFenceStatus> fGetFenceStatus;\n        VkPtr<PFN_vkWaitForFences> fWaitForFences;\n        VkPtr<PFN_vkCreateSemaphore> fCreateSemaphore;\n        VkPtr<PFN_vkDestroySemaphore> fDestroySemaphore;\n        VkPtr<PFN_vkCreateEvent> fCreateEvent;\n        VkPtr<PFN_vkDestroyEvent> fDestroyEvent;\n        VkPtr<PFN_vkGetEventStatus> fGetEventStatus;\n        VkPtr<PFN_vkSetEvent> fSetEvent;\n        VkPtr<PFN_vkResetEvent> fResetEvent;\n        VkPtr<PFN_vkCreateQueryPool> fCreateQueryPool;\n        VkPtr<PFN_vkDestroyQueryPool> fDestroyQueryPool;\n        VkPtr<PFN_vkGetQueryPoolResults> fGetQueryPoolResults;\n        VkPtr<PFN_vkCreateBuffer> fCreateBuffer;\n        VkPtr<PFN_vkDestroyBuffer> fDestroyBuffer;\n        VkPtr<PFN_vkCreateBufferView> fCreateBufferView;\n        VkPtr<PFN_vkDestroyBufferView> fDestroyBufferView;\n        VkPtr<PFN_vkCreateImage> fCreateImage;\n        VkPtr<PFN_vkDestroyImage> fDestroyImage;\n        VkPtr<PFN_vkGetImageSubresourceLayout> fGetImageSubresourceLayout;\n        VkPtr<PFN_vkCreateImageView> fCreateImageView;\n        VkPtr<PFN_vkDestroyImageView> fDestroyImageView;\n        VkPtr<PFN_vkCreateShaderModule> fCreateShaderModule;\n        VkPtr<PFN_vkDestroyShaderModule> fDestroyShaderModule;\n        VkPtr<PFN_vkCreatePipelineCache> fCreatePipelineCache;\n        VkPtr<PFN_vkDestroyPipelineCache> fDestroyPipelineCache;\n        VkPtr<PFN_vkGetPipelineCacheData> fGetPipelineCacheData;\n        VkPtr<PFN_vkMergePipelineCaches> fMergePipelineCaches;\n        VkPtr<PFN_vkCreateGraphicsPipelines> fCreateGraphicsPipelines;\n        VkPtr<PFN_vkCreateComputePipelines> fCreateComputePipelines;\n        VkPtr<PFN_vkDestroyPipeline> fDestroyPipeline;\n        VkPtr<PFN_vkCreatePipelineLayout> fCreatePipelineLayout;\n        VkPtr<PFN_vkDestroyPipelineLayout> fDestroyPipelineLayout;\n        VkPtr<PFN_vkCreateSampler> fCreateSampler;\n        VkPtr<PFN_vkDestroySampler> fDestroySampler;\n        VkPtr<PFN_vkCreateDescriptorSetLayout> fCreateDescriptorSetLayout;\n        VkPtr<PFN_vkDestroyDescriptorSetLayout> fDestroyDescriptorSetLayout;\n        VkPtr<PFN_vkCreateDescriptorPool> fCreateDescriptorPool;\n        VkPtr<PFN_vkDestroyDescriptorPool> fDestroyDescriptorPool;\n        VkPtr<PFN_vkResetDescriptorPool> fResetDescriptorPool;\n        VkPtr<PFN_vkAllocateDescriptorSets> fAllocateDescriptorSets;\n        VkPtr<PFN_vkFreeDescriptorSets> fFreeDescriptorSets;\n        VkPtr<PFN_vkUpdateDescriptorSets> fUpdateDescriptorSets;\n        VkPtr<PFN_vkCreateFramebuffer> fCreateFramebuffer;\n        VkPtr<PFN_vkDestroyFramebuffer> fDestroyFramebuffer;\n        VkPtr<PFN_vkCreateRenderPass> fCreateRenderPass;\n        VkPtr<PFN_vkDestroyRenderPass> fDestroyRenderPass;\n        VkPtr<PFN_vkGetRenderAreaGranularity> fGetRenderAreaGranularity;\n        VkPtr<PFN_vkCreateCommandPool> fCreateCommandPool;\n        VkPtr<PFN_vkDestroyCommandPool> fDestroyCommandPool;\n        VkPtr<PFN_vkResetCommandPool> fResetCommandPool;\n        VkPtr<PFN_vkAllocateCommandBuffers> fAllocateCommandBuffers;\n        VkPtr<PFN_vkFreeCommandBuffers> fFreeCommandBuffers;\n        VkPtr<PFN_vkBeginCommandBuffer> fBeginCommandBuffer;\n        VkPtr<PFN_vkEndCommandBuffer> fEndCommandBuffer;\n        VkPtr<PFN_vkResetCommandBuffer> fResetCommandBuffer;\n        VkPtr<PFN_vkCmdBindPipeline> fCmdBindPipeline;\n        VkPtr<PFN_vkCmdSetViewport> fCmdSetViewport;\n        VkPtr<PFN_vkCmdSetScissor> fCmdSetScissor;\n        VkPtr<PFN_vkCmdSetLineWidth> fCmdSetLineWidth;\n        VkPtr<PFN_vkCmdSetDepthBias> fCmdSetDepthBias;\n        VkPtr<PFN_vkCmdSetBlendConstants> fCmdSetBlendConstants;\n        VkPtr<PFN_vkCmdSetDepthBounds> fCmdSetDepthBounds;\n        VkPtr<PFN_vkCmdSetStencilCompareMask> fCmdSetStencilCompareMask;\n        VkPtr<PFN_vkCmdSetStencilWriteMask> fCmdSetStencilWriteMask;\n        VkPtr<PFN_vkCmdSetStencilReference> fCmdSetStencilReference;\n        VkPtr<PFN_vkCmdBindDescriptorSets> fCmdBindDescriptorSets;\n        VkPtr<PFN_vkCmdBindIndexBuffer> fCmdBindIndexBuffer;\n        VkPtr<PFN_vkCmdBindVertexBuffers> fCmdBindVertexBuffers;\n        VkPtr<PFN_vkCmdDraw> fCmdDraw;\n        VkPtr<PFN_vkCmdDrawIndexed> fCmdDrawIndexed;\n        VkPtr<PFN_vkCmdDrawIndirect> fCmdDrawIndirect;\n        VkPtr<PFN_vkCmdDrawIndexedIndirect> fCmdDrawIndexedIndirect;\n        VkPtr<PFN_vkCmdDispatch> fCmdDispatch;\n        VkPtr<PFN_vkCmdDispatchIndirect> fCmdDispatchIndirect;\n        VkPtr<PFN_vkCmdCopyBuffer> fCmdCopyBuffer;\n        VkPtr<PFN_vkCmdCopyImage> fCmdCopyImage;\n        VkPtr<PFN_vkCmdBlitImage> fCmdBlitImage;\n        VkPtr<PFN_vkCmdCopyBufferToImage> fCmdCopyBufferToImage;\n        VkPtr<PFN_vkCmdCopyImageToBuffer> fCmdCopyImageToBuffer;\n        VkPtr<PFN_vkCmdUpdateBuffer> fCmdUpdateBuffer;\n        VkPtr<PFN_vkCmdFillBuffer> fCmdFillBuffer;\n        VkPtr<PFN_vkCmdClearColorImage> fCmdClearColorImage;\n        VkPtr<PFN_vkCmdClearDepthStencilImage> fCmdClearDepthStencilImage;\n        VkPtr<PFN_vkCmdClearAttachments> fCmdClearAttachments;\n        VkPtr<PFN_vkCmdResolveImage> fCmdResolveImage;\n        VkPtr<PFN_vkCmdSetEvent> fCmdSetEvent;\n        VkPtr<PFN_vkCmdResetEvent> fCmdResetEvent;\n        VkPtr<PFN_vkCmdWaitEvents> fCmdWaitEvents;\n        VkPtr<PFN_vkCmdPipelineBarrier> fCmdPipelineBarrier;\n        VkPtr<PFN_vkCmdBeginQuery> fCmdBeginQuery;\n        VkPtr<PFN_vkCmdEndQuery> fCmdEndQuery;\n        VkPtr<PFN_vkCmdResetQueryPool> fCmdResetQueryPool;\n        VkPtr<PFN_vkCmdWriteTimestamp> fCmdWriteTimestamp;\n        VkPtr<PFN_vkCmdCopyQueryPoolResults> fCmdCopyQueryPoolResults;\n        VkPtr<PFN_vkCmdPushConstants> fCmdPushConstants;\n        VkPtr<PFN_vkCmdBeginRenderPass> fCmdBeginRenderPass;\n        VkPtr<PFN_vkCmdNextSubpass> fCmdNextSubpass;\n        VkPtr<PFN_vkCmdEndRenderPass> fCmdEndRenderPass;\n        VkPtr<PFN_vkCmdExecuteCommands> fCmdExecuteCommands;\n\n        VkPtr<PFN_vkCreateDebugReportCallbackEXT> fCreateDebugReportCallbackEXT;\n        VkPtr<PFN_vkDebugReportMessageEXT> fDebugReportMessageEXT;\n        VkPtr<PFN_vkDestroyDebugReportCallbackEXT> fDestroyDebugReportCallbackEXT;\n    } fFunctions;\n\n};\n\n#endif\n"
  },
  {
    "path": "include/gpu/vk/GrVkMemoryAllocator.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkMemoryAllocator_DEFINED\n#define GrVkMemoryAllocator_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"GrTypes.h\"\n#include \"GrVkDefines.h\"\n#include \"GrVkTypes.h\"\n\nclass GrVkMemoryAllocator : public SkRefCnt {\npublic:\n    enum class AllocationPropertyFlags {\n        kNone                = 0,\n        // Allocation will be placed in its own VkDeviceMemory and not suballocated from some larger\n        // block.\n        kDedicatedAllocation = 0x1,\n        // Says that the backing memory can only be accessed by the device. Additionally the device\n        // may lazily allocate the memory. This cannot be used with buffers that will be host\n        // visible. Setting this flag does not guarantee that we will allocate memory that respects\n        // it, but we will try to prefer memory that can respect it.\n        kLazyAllocation      = 0x2,\n        // The allocation will be mapped immediately and stay mapped until it is destroyed. This\n        // flag is only valid for buffers which are host visible (i.e. must have a usage other than\n        // BufferUsage::kGpuOnly).\n        kPersistentlyMapped  = 0x4,\n    };\n\n    GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(AllocationPropertyFlags);\n\n    enum class BufferUsage {\n        // Buffers that will only be accessed from the device (large const buffers). Will always be\n        // in device local memory.\n        kGpuOnly,\n        // Buffers that will be accessed on the host and copied to and from a GPU resource (transfer\n        // buffers). Will always be mappable and coherent memory.\n        kCpuOnly,\n        // Buffers that typically will be updated multiple times by the host and read on the gpu\n        // (e.g. uniform or vertex buffers). Will always be mappable memory, and will prefer to be\n        // in device local memory.\n        kCpuWritesGpuReads,\n        // Buffers which are typically writted to by the GPU and then read on the host. Will always\n        // be mappable memory, and will prefer coherent and cached memory.\n        kGpuWritesCpuReads,\n    };\n\n    virtual bool allocateMemoryForImage(VkImage image, AllocationPropertyFlags flags,\n                                        GrVkBackendMemory*) = 0;\n\n    virtual bool allocateMemoryForBuffer(VkBuffer buffer, BufferUsage usage,\n                                         AllocationPropertyFlags flags, GrVkBackendMemory*) = 0;\n\n    // Fills out the passed in GrVkAlloc struct for the passed in GrVkBackendMemory.\n    virtual void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const = 0;\n\n    // Maps the entire allocation and returns a pointer to the start of the allocation. The\n    // implementation may map more memory than just the allocation, but the returned pointer must\n    // point at the start of the memory for the requested allocation.\n    virtual void* mapMemory(const GrVkBackendMemory&) = 0;\n    virtual void unmapMemory(const GrVkBackendMemory&) = 0;\n\n    // The following two calls are used for managing non-coherent memory. The offset is relative to\n    // the start of the allocation and not the underlying VkDeviceMemory. Additionaly the client\n    // must make sure that the offset + size passed in is less that or equal to the allocation size.\n    // It is the responsibility of the implementation to make sure all alignment requirements are\n    // followed. The client should not have to deal with any sort of alignment issues.\n    virtual void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,\n                                   VkDeviceSize size) = 0;\n    virtual void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize offset,\n                                        VkDeviceSize size)= 0;\n\n    virtual void freeMemory(const GrVkBackendMemory&) = 0;\n\n    // Returns the total amount of memory that is allocated and in use by an allocation for this\n    // allocator.\n    virtual uint64_t totalUsedMemory() const = 0;\n\n    // Returns the total amount of memory that is allocated by this allocator.\n    virtual uint64_t totalAllocatedMemory() const = 0;\n};\n\nGR_MAKE_BITFIELD_CLASS_OPS(GrVkMemoryAllocator::AllocationPropertyFlags);\n\n#endif\n"
  },
  {
    "path": "include/gpu/vk/GrVkTypes.h",
    "content": "\n/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkTypes_DEFINED\n#define GrVkTypes_DEFINED\n\n#include \"GrTypes.h\"\n#include \"GrVkDefines.h\"\n\n/**\n * KHR_debug\n */\n/*typedef void (GR_GL_FUNCTION_TYPE* GrVkDEBUGPROC)(GrVkenum source,\n                                                  GrVkenum type,\n                                                  GrVkuint id,\n                                                  GrVkenum severity,\n                                                  GrVksizei length,\n                                                  const GrVkchar* message,\n                                                  const void* userParam);*/\n\n\n\n///////////////////////////////////////////////////////////////////////////////\n\ntypedef intptr_t GrVkBackendMemory;\n\n/**\n * Types for interacting with Vulkan resources created externally to Skia. GrBackendObjects for\n * Vulkan textures are really const GrVkImageInfo*\n */\nstruct GrVkAlloc {\n    GrVkAlloc()\n            : fMemory(VK_NULL_HANDLE)\n            , fOffset(0)\n            , fSize(0)\n            , fFlags(0)\n            , fBackendMemory(0)\n            , fUsesSystemHeap(false) {}\n\n    GrVkAlloc(VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, uint32_t flags)\n            : fMemory(memory)\n            , fOffset(offset)\n            , fSize(size)\n            , fFlags(flags)\n            , fBackendMemory(0)\n            , fUsesSystemHeap(false) {}\n\n    VkDeviceMemory    fMemory;  // can be VK_NULL_HANDLE iff is an RT and is borrowed\n    VkDeviceSize      fOffset;\n    VkDeviceSize      fSize;    // this can be indeterminate iff Tex uses borrow semantics\n    uint32_t          fFlags;\n    GrVkBackendMemory fBackendMemory; // handle to memory allocated via GrVkMemoryAllocator.\n\n    enum Flag {\n        kNoncoherent_Flag = 0x1,   // memory must be flushed to device after mapping\n        kMappable_Flag    = 0x2,   // memory is able to be mapped.\n    };\n\n    bool operator==(const GrVkAlloc& that) const {\n        return fMemory == that.fMemory && fOffset == that.fOffset && fSize == that.fSize &&\n               fFlags == that.fFlags && fUsesSystemHeap == that.fUsesSystemHeap;\n    }\n\nprivate:\n    friend class GrVkHeap; // For access to usesSystemHeap\n    bool fUsesSystemHeap;\n};\nstruct GrVkImageInfo {\n    VkImage        fImage;\n    GrVkAlloc      fAlloc;\n    VkImageTiling  fImageTiling;\n    VkImageLayout  fImageLayout;\n    VkFormat       fFormat;\n    uint32_t       fLevelCount;\n\n    GrVkImageInfo()\n            : fImage(VK_NULL_HANDLE)\n            , fAlloc()\n            , fImageTiling(VK_IMAGE_TILING_OPTIMAL)\n            , fImageLayout(VK_IMAGE_LAYOUT_UNDEFINED)\n            , fFormat(VK_FORMAT_UNDEFINED)\n            , fLevelCount(0) {}\n\n    GrVkImageInfo(VkImage image, GrVkAlloc alloc, VkImageTiling imageTiling, VkImageLayout layout,\n                  VkFormat format, uint32_t levelCount)\n            : fImage(image)\n            , fAlloc(alloc)\n            , fImageTiling(imageTiling)\n            , fImageLayout(layout)\n            , fFormat(format)\n            , fLevelCount(levelCount) {}\n\n    GrVkImageInfo(const GrVkImageInfo& info, VkImageLayout layout)\n            : fImage(info.fImage)\n            , fAlloc(info.fAlloc)\n            , fImageTiling(info.fImageTiling)\n            , fImageLayout(layout)\n            , fFormat(info.fFormat)\n            , fLevelCount(info.fLevelCount) {}\n\n    // This gives a way for a client to update the layout of the Image if they change the layout\n    // while we're still holding onto the wrapped texture. They will first need to get a handle\n    // to our internal GrVkImageInfo by calling getTextureHandle on a GrVkTexture.\n    void updateImageLayout(VkImageLayout layout) { fImageLayout = layout; }\n\n    bool operator==(const GrVkImageInfo& that) const {\n        return fImage == that.fImage && fAlloc == that.fAlloc &&\n               fImageTiling == that.fImageTiling && fImageLayout == that.fImageLayout &&\n               fFormat == that.fFormat && fLevelCount == that.fLevelCount;\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/pathops/SkPathOps.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkPathOps_DEFINED\n#define SkPathOps_DEFINED\n\n#include \"../private/SkTArray.h\"\n#include \"../private/SkTDArray.h\"\n#include \"SkPreConfig.h\"\n\nclass SkPath;\nstruct SkRect;\n\n\n// FIXME: move everything below into the SkPath class\n/**\n  *  The logical operations that can be performed when combining two paths.\n  */\nenum SkPathOp {\n    kDifference_SkPathOp,         //!< subtract the op path from the first path\n    kIntersect_SkPathOp,          //!< intersect the two paths\n    kUnion_SkPathOp,              //!< union (inclusive-or) the two paths\n    kXOR_SkPathOp,                //!< exclusive-or the two paths\n    kReverseDifference_SkPathOp,  //!< subtract the first path from the op path\n};\n\n/** Set this path to the result of applying the Op to this path and the\n    specified path: this = (this op operand).\n    The resulting path will be constructed from non-overlapping contours.\n    The curve order is reduced where possible so that cubics may be turned\n    into quadratics, and quadratics maybe turned into lines.\n\n    Returns true if operation was able to produce a result;\n    otherwise, result is unmodified.\n\n    @param one The first operand (for difference, the minuend)\n    @param two The second operand (for difference, the subtrahend)\n    @param op The operator to apply.\n    @param result The product of the operands. The result may be one of the\n                  inputs.\n    @return True if the operation succeeded.\n  */\nbool SK_API Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result);\n\n/** Set this path to a set of non-overlapping contours that describe the\n    same area as the original path.\n    The curve order is reduced where possible so that cubics may\n    be turned into quadratics, and quadratics maybe turned into lines.\n\n    Returns true if operation was able to produce a result;\n    otherwise, result is unmodified.\n\n    @param path The path to simplify.\n    @param result The simplified path. The result may be the input.\n    @return True if simplification succeeded.\n  */\nbool SK_API Simplify(const SkPath& path, SkPath* result);\n\n/** Set the resulting rectangle to the tight bounds of the path.\n\n    @param path The path measured.\n    @param result The tight bounds of the path.\n    @return True if the bounds could be computed.\n  */\nbool SK_API TightBounds(const SkPath& path, SkRect* result);\n\n/** Perform a series of path operations, optimized for unioning many paths together.\n  */\nclass SK_API SkOpBuilder {\npublic:\n    /** Add one or more paths and their operand. The builder is empty before the first\n        path is added, so the result of a single add is (emptyPath OP path).\n\n        @param path The second operand.\n        @param _operator The operator to apply to the existing and supplied paths.\n     */\n    void add(const SkPath& path, SkPathOp _operator);\n\n    /** Computes the sum of all paths and operands, and resets the builder to its\n        initial state.\n\n        @param result The product of the operands.\n        @return True if the operation succeeded.\n      */\n    bool resolve(SkPath* result);\n\nprivate:\n    SkTArray<SkPath> fPathRefs;\n    SkTDArray<SkPathOp> fOps;\n\n    static bool FixWinding(SkPath* path);\n    static void ReversePath(SkPath* path);\n    void reset();\n};\n\n#endif\n"
  },
  {
    "path": "include/ports/SkFontConfigInterface.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontConfigInterface_DEFINED\n#define SkFontConfigInterface_DEFINED\n\n#include \"SkFontStyle.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTypeface.h\"\n\nclass SkFontMgr;\n\n/**\n *  \\class SkFontConfigInterface\n *\n *  A simple interface for remotable font management.\n *  The global instance can be found with RefGlobal().\n */\nclass SK_API SkFontConfigInterface : public SkRefCnt {\npublic:\n\n    /**\n     *  Returns the global SkFontConfigInterface instance. If it is not\n     *  nullptr, calls ref() on it. The caller must balance this with a call to\n     *  unref(). The default SkFontConfigInterface is the result of calling\n     *  GetSingletonDirectInterface.\n     */\n    static sk_sp<SkFontConfigInterface> RefGlobal();\n\n    /**\n     *  Replace the current global instance with the specified one.\n     */\n    static void SetGlobal(sk_sp<SkFontConfigInterface> fc);\n\n    /**\n     *  This should be treated as private to the impl of SkFontConfigInterface.\n     *  Callers should not change or expect any particular values. It is meant\n     *  to be a union of possible storage types to aid the impl.\n     */\n    struct FontIdentity {\n        FontIdentity() : fID(0), fTTCIndex(0) {}\n\n        bool operator==(const FontIdentity& other) const {\n            return fID == other.fID &&\n                   fTTCIndex == other.fTTCIndex &&\n                   fString == other.fString;\n        }\n        bool operator!=(const FontIdentity& other) const {\n            return !(*this == other);\n        }\n\n        uint32_t    fID;\n        int32_t     fTTCIndex;\n        SkString    fString;\n        SkFontStyle fStyle;\n\n        // If buffer is NULL, just return the number of bytes that would have\n        // been written. Will pad contents to a multiple of 4.\n        size_t writeToMemory(void* buffer = nullptr) const;\n\n        // Recreate from a flattened buffer, returning the number of bytes read.\n        size_t readFromMemory(const void* buffer, size_t length);\n    };\n\n    /**\n     *  Given a familyName and style, find the best match.\n     *\n     *  If a match is found, return true and set its outFontIdentifier.\n     *      If outFamilyName is not null, assign the found familyName to it\n     *          (which may differ from the requested familyName).\n     *      If outStyle is not null, assign the found style to it\n     *          (which may differ from the requested style).\n     *\n     *  If a match is not found, return false, and ignore all out parameters.\n     */\n    virtual bool matchFamilyName(const char familyName[],\n                                 SkFontStyle requested,\n                                 FontIdentity* outFontIdentifier,\n                                 SkString* outFamilyName,\n                                 SkFontStyle* outStyle) = 0;\n\n    /**\n     *  Given a FontRef, open a stream to access its data, or return null\n     *  if the FontRef's data is not available. The caller is responsible for\n     *  deleting the stream when it is done accessing the data.\n     */\n    virtual SkStreamAsset* openStream(const FontIdentity&) = 0;\n\n    /**\n     *  Return an SkTypeface for the given FontIdentity.\n     *\n     *  The default implementation simply returns a new typeface built using data obtained from\n     *  openStream(), but derived classes may implement more complex caching schemes.\n     */\n    virtual sk_sp<SkTypeface> makeTypeface(const FontIdentity& identity) {\n        return SkTypeface::MakeFromStream(this->openStream(identity), identity.fTTCIndex);\n    }\n\n    /**\n     *  Return a singleton instance of a direct subclass that calls into\n     *  libfontconfig. This does not affect the refcnt of the returned instance.\n     */\n    static SkFontConfigInterface* GetSingletonDirectInterface();\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/ports/SkFontMgr.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_DEFINED\n#define SkFontMgr_DEFINED\n\n#include \"SkFontArguments.h\"\n#include \"SkFontStyle.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTypes.h\"\n\nclass SkData;\nclass SkFontData;\nclass SkStreamAsset;\nclass SkString;\nclass SkTypeface;\n\nclass SK_API SkFontStyleSet : public SkRefCnt {\npublic:\n    virtual int count() = 0;\n    virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;\n    virtual SkTypeface* createTypeface(int index) = 0;\n    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;\n\n    static SkFontStyleSet* CreateEmpty();\n\nprotected:\n    SkTypeface* matchStyleCSS3(const SkFontStyle& pattern);\n\nprivate:\n    typedef SkRefCnt INHERITED;\n};\n\nclass SK_API SkFontMgr : public SkRefCnt {\npublic:\n    int countFamilies() const;\n    void getFamilyName(int index, SkString* familyName) const;\n    SkFontStyleSet* createStyleSet(int index) const;\n\n    /**\n     *  The caller must call unref() on the returned object.\n     *  Never returns NULL; will return an empty set if the name is not found.\n     *\n     *  Passing nullptr as the parameter will return the default system family.\n     *  Note that most systems don't have a default system family, so passing nullptr will often\n     *  result in the empty set.\n     *\n     *  It is possible that this will return a style set not accessible from\n     *  createStyleSet(int) due to hidden or auto-activated fonts.\n     */\n    SkFontStyleSet* matchFamily(const char familyName[]) const;\n\n    /**\n     *  Find the closest matching typeface to the specified familyName and style\n     *  and return a ref to it. The caller must call unref() on the returned\n     *  object. Will never return NULL, as it will return the default font if\n     *  no matching font is found.\n     *\n     *  Passing |nullptr| as the parameter for |familyName| will return the\n     *  default system font.\n     *\n     *  It is possible that this will return a style set not accessible from\n     *  createStyleSet(int) or matchFamily(const char[]) due to hidden or\n     *  auto-activated fonts.\n     */\n    SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&) const;\n\n    /**\n     *  Use the system fallback to find a typeface for the given character.\n     *  Note that bcp47 is a combination of ISO 639, 15924, and 3166-1 codes,\n     *  so it is fine to just pass a ISO 639 here.\n     *\n     *  Will return NULL if no family can be found for the character\n     *  in the system fallback.\n     *\n     *  Passing |nullptr| as the parameter for |familyName| will return the\n     *  default system font.\n     *\n     *  bcp47[0] is the least significant fallback, bcp47[bcp47Count-1] is the\n     *  most significant. If no specified bcp47 codes match, any font with the\n     *  requested character will be matched.\n     */\n    SkTypeface* matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,\n                                          const char* bcp47[], int bcp47Count,\n                                          SkUnichar character) const;\n\n    SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&) const;\n\n    /**\n     *  Create a typeface for the specified data and TTC index (pass 0 for none)\n     *  or NULL if the data is not recognized. The caller must call unref() on\n     *  the returned object if it is not null.\n     */\n    sk_sp<SkTypeface> makeFromData(sk_sp<SkData>, int ttcIndex = 0) const;\n\n    /**\n     *  Create a typeface for the specified stream and TTC index\n     *  (pass 0 for none) or NULL if the stream is not recognized. The caller\n     *  must call unref() on the returned object if it is not null.\n     */\n    sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, int ttcIndex = 0) const;\n\n    /* Experimental, API subject to change. */\n    sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const;\n\n    /**\n     *  Create a typeface from the specified font data.\n     *  Will return NULL if the typeface could not be created.\n     *  The caller must call unref() on the returned object if it is not null.\n     */\n    sk_sp<SkTypeface> makeFromFontData(std::unique_ptr<SkFontData>) const;\n\n    /**\n     *  Create a typeface for the specified fileName and TTC index\n     *  (pass 0 for none) or NULL if the file is not found, or its contents are\n     *  not recognized. The caller must call unref() on the returned object\n     *  if it is not null.\n     */\n    sk_sp<SkTypeface> makeFromFile(const char path[], int ttcIndex = 0) const;\n\n    sk_sp<SkTypeface> legacyMakeTypeface(const char familyName[], SkFontStyle style) const;\n\n    /** Return the default fontmgr. */\n    static sk_sp<SkFontMgr> RefDefault();\n\nprotected:\n    virtual int onCountFamilies() const = 0;\n    virtual void onGetFamilyName(int index, SkString* familyName) const = 0;\n    virtual SkFontStyleSet* onCreateStyleSet(int index)const  = 0;\n\n    /** May return NULL if the name is not found. */\n    virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const = 0;\n\n    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],\n                                           const SkFontStyle&) const = 0;\n    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,\n                                                    const char* bcp47[], int bcp47Count,\n                                                    SkUnichar character) const = 0;\n    virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,\n                                         const SkFontStyle&) const = 0;\n\n    virtual sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const = 0;\n    virtual sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,\n                                                    int ttcIndex) const = 0;\n    virtual sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,\n                                                   const SkFontArguments&) const;\n    virtual sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const;\n    virtual sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const = 0;\n\n    virtual sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const = 0;\n\nprivate:\n\n    /** Implemented by porting layer to return the default factory. */\n    static sk_sp<SkFontMgr> Factory();\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/ports/SkFontMgr_FontConfigInterface.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_FontConfigInterface_DEFINED\n#define SkFontMgr_FontConfigInterface_DEFINED\n\n#include \"SkTypes.h\"\n#include \"SkRefCnt.h\"\n\nclass SkFontMgr;\nclass SkFontConfigInterface;\n\n/** Creates a SkFontMgr which wraps a SkFontConfigInterface. */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_FCI(sk_sp<SkFontConfigInterface> fci);\n\n#endif // #ifndef SkFontMgr_FontConfigInterface_DEFINED\n"
  },
  {
    "path": "include/ports/SkFontMgr_android.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_android_DEFINED\n#define SkFontMgr_android_DEFINED\n\n#include \"SkRefCnt.h\"\n\nclass SkFontMgr;\n\nstruct SkFontMgr_Android_CustomFonts {\n    /** When specifying custom fonts, indicates how to use system fonts. */\n    enum SystemFontUse {\n        kOnlyCustom, /** Use only custom fonts. NDK compliant. */\n        kPreferCustom, /** Use custom fonts before system fonts. */\n        kPreferSystem /** Use system fonts before custom fonts. */\n    };\n    /** Whether or not to use system fonts. */\n    SystemFontUse fSystemFontUse;\n\n    /** Base path to resolve relative font file names. If a directory, should end with '/'. */\n    const char* fBasePath;\n\n    /** Optional custom configuration file to use. */\n    const char* fFontsXml;\n\n    /** Optional custom configuration file for fonts which provide fallback.\n     *  In the new style (version > 21) fontsXml format is used, this should be NULL.\n     */\n    const char* fFallbackFontsXml;\n\n    /** Optional custom flag. If set to true the SkFontMgr will acquire all requisite\n     *  system IO resources on initialization.\n     */\n    bool fIsolated;\n};\n\n/** Create a font manager for Android. If 'custom' is NULL, use only system fonts. */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_Android(const SkFontMgr_Android_CustomFonts* custom);\n\n#endif // SkFontMgr_android_DEFINED\n"
  },
  {
    "path": "include/ports/SkFontMgr_directory.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_directory_DEFINED\n#define SkFontMgr_directory_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkTypes.h\"\n\nclass SkFontMgr;\n\n/** Create a custom font manager which scans a given directory for font files.\n *  This font manager uses FreeType for rendering.\n */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Directory(const char* dir);\n\n#endif // SkFontMgr_directory_DEFINED\n"
  },
  {
    "path": "include/ports/SkFontMgr_empty.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_empty_DEFINED\n#define SkFontMgr_empty_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkTypes.h\"\n\nclass SkFontMgr;\n\n/** Create a custom font manager that contains no built-in fonts.\n *  This font manager uses FreeType for rendering.\n */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_Custom_Empty();\n\n#endif // SkFontMgr_empty_DEFINED\n"
  },
  {
    "path": "include/ports/SkFontMgr_fontconfig.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_fontconfig_DEFINED\n#define SkFontMgr_fontconfig_DEFINED\n\n#include \"SkRefCnt.h\"\n#include <fontconfig/fontconfig.h>\n\nclass SkFontMgr;\n\n/** Create a font manager around a FontConfig instance.\n *  If 'fc' is NULL, will use a new default config.\n *  Takes ownership of 'fc' and will call FcConfigDestroy on it.\n */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_FontConfig(FcConfig* fc);\n\n#endif // #ifndef SkFontMgr_fontconfig_DEFINED\n"
  },
  {
    "path": "include/ports/SkFontMgr_indirect.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFontMgr_indirect_DEFINED\n#define SkFontMgr_indirect_DEFINED\n\n#include \"../private/SkMutex.h\"\n#include \"../private/SkOnce.h\"\n#include \"../private/SkTArray.h\"\n#include \"SkFontMgr.h\"\n#include \"SkRefCnt.h\"\n#include \"SkRemotableFontMgr.h\"\n#include \"SkTypeface.h\"\n#include \"SkTypes.h\"\n\nclass SkData;\nclass SkFontStyle;\nclass SkStreamAsset;\nclass SkString;\n\nclass SK_API SkFontMgr_Indirect : public SkFontMgr {\npublic:\n    // TODO: The SkFontMgr is only used for createFromStream/File/Data.\n    // In the future these calls should be broken out into their own interface\n    // with a name like SkFontRenderer.\n    SkFontMgr_Indirect(sk_sp<SkFontMgr> impl, sk_sp<SkRemotableFontMgr> proxy)\n        : fImpl(std::move(impl)), fProxy(std::move(proxy))\n    { }\n\nprotected:\n    int onCountFamilies() const override;\n    void onGetFamilyName(int index, SkString* familyName) const override;\n    SkFontStyleSet* onCreateStyleSet(int index) const override;\n\n    SkFontStyleSet* onMatchFamily(const char familyName[]) const override;\n\n    SkTypeface* onMatchFamilyStyle(const char familyName[],\n                                   const SkFontStyle& fontStyle) const override;\n\n    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],\n                                            const SkFontStyle&,\n                                            const char* bcp47[],\n                                            int bcp47Count,\n                                            SkUnichar character) const override;\n\n    SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,\n                                 const SkFontStyle& fontStyle) const override;\n\n    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>, int ttcIndex) const override;\n    sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override;\n    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override;\n    sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const override;\n\nprivate:\n    SkTypeface* createTypefaceFromFontId(const SkFontIdentity& fontId) const;\n\n    sk_sp<SkFontMgr> fImpl;\n    sk_sp<SkRemotableFontMgr> fProxy;\n\n    struct DataEntry {\n        uint32_t fDataId;  // key1\n        uint32_t fTtcIndex;  // key2\n        SkTypeface* fTypeface;  // value: weak ref to typeface\n\n        DataEntry() { }\n\n        DataEntry(DataEntry&& that)\n            : fDataId(that.fDataId)\n            , fTtcIndex(that.fTtcIndex)\n            , fTypeface(that.fTypeface)\n        {\n            SkDEBUGCODE(that.fDataId = SkFontIdentity::kInvalidDataId;)\n            SkDEBUGCODE(that.fTtcIndex = 0xbbadbeef;)\n            that.fTypeface = nullptr;\n        }\n\n        ~DataEntry() {\n            if (fTypeface) {\n                fTypeface->weak_unref();\n            }\n        }\n    };\n    /**\n     *  This cache is essentially { dataId: { ttcIndex: typeface } }\n     *  For data caching we want a mapping from data id to weak references to\n     *  typefaces with that data id. By storing the index next to the typeface,\n     *  this data cache also acts as a typeface cache.\n     */\n    mutable SkTArray<DataEntry> fDataCache;\n    mutable SkMutex fDataCacheMutex;\n\n    friend class SkStyleSet_Indirect;\n};\n\n#endif\n"
  },
  {
    "path": "include/ports/SkRemotableFontMgr.h",
    "content": "/*\n * Copyright 2014 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRemotableFontMgr_DEFINED\n#define SkRemotableFontMgr_DEFINED\n\n#include \"../private/SkTemplates.h\"\n#include \"SkFontStyle.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTypes.h\"\n\nclass SkDataTable;\nclass SkStreamAsset;\n\nstruct SK_API SkFontIdentity {\n    static const uint32_t kInvalidDataId = 0xFFFFFFFF;\n\n    // Note that fDataId is a data identifier, not a font identifier.\n    // (fDataID, fTtcIndex) can be seen as a font identifier.\n    uint32_t fDataId;\n    uint32_t fTtcIndex;\n\n    // On Linux/FontConfig there is also the ability to specify preferences for rendering\n    // antialias, embedded bitmaps, autohint, hinting, hintstyle, lcd rendering\n    // may all be set or set to no-preference\n    // (No-preference is resolved against globals set by the platform)\n    // Since they may be selected against, these are really 'extensions' to SkFontStyle.\n    // SkFontStyle should pick these up.\n    SkFontStyle fFontStyle;\n};\n\nclass SK_API SkRemotableFontIdentitySet : public SkRefCnt {\npublic:\n    SkRemotableFontIdentitySet(int count, SkFontIdentity** data);\n\n    int count() const { return fCount; }\n    const SkFontIdentity& at(int index) const { return fData[index]; }\n\n    static SkRemotableFontIdentitySet* NewEmpty();\n\nprivate:\n    SkRemotableFontIdentitySet() : fCount(0), fData() { }\n\n    friend SkRemotableFontIdentitySet* sk_remotable_font_identity_set_new();\n\n    int fCount;\n    SkAutoTMalloc<SkFontIdentity> fData;\n\n    typedef SkRefCnt INHERITED;\n};\n\nclass SK_API SkRemotableFontMgr : public SkRefCnt {\npublic:\n    /**\n     *  Returns all of the fonts with the given familyIndex.\n     *  Returns NULL if the index is out of bounds.\n     *  Returns empty if there are no fonts at the given index.\n     *\n     *  The caller must unref() the returned object.\n     */\n    virtual SkRemotableFontIdentitySet* getIndex(int familyIndex) const = 0;\n\n    /**\n     *  Returns the closest match to the given style in the given index.\n     *  If there are no available fonts at the given index, the return value's\n     *  data id will be kInvalidDataId.\n     */\n    virtual SkFontIdentity matchIndexStyle(int familyIndex, const SkFontStyle&) const = 0;\n\n    /**\n     *  Returns all the fonts on the system with the given name.\n     *  If the given name is NULL, will return the default font family.\n     *  Never returns NULL; will return an empty set if the name is not found.\n     *\n     *  It is possible that this will return fonts not accessible from\n     *  getIndex(int) or matchIndexStyle(int, SkFontStyle) due to\n     *  hidden or auto-activated fonts.\n     *\n     *  The matching may be done in a system dependent way. The name may be\n     *  matched case-insensitive, there may be system aliases which resolve,\n     *  and names outside the current locale may be considered. However, this\n     *  should only return fonts which are somehow associated with the requested\n     *  name.\n     *\n     *  The caller must unref() the returned object.\n     */\n    virtual SkRemotableFontIdentitySet* matchName(const char familyName[]) const = 0;\n\n    /**\n     *  Returns the closest matching font to the specified name and style.\n     *  If there are no available fonts which match the name, the return value's\n     *  data id will be kInvalidDataId.\n     *  If the given name is NULL, the match will be against any default fonts.\n     *\n     *  It is possible that this will return a font identity not accessible from\n     *  methods returning sets due to hidden or auto-activated fonts.\n     *\n     *  The matching may be done in a system dependent way. The name may be\n     *  matched case-insensitive, there may be system aliases which resolve,\n     *  and names outside the current locale may be considered. However, this\n     *  should only return a font which is somehow associated with the requested\n     *  name.\n     *\n     *  The caller must unref() the returned object.\n     */\n    virtual SkFontIdentity matchNameStyle(const char familyName[], const SkFontStyle&) const = 0;\n\n    /**\n     *  Use the system fall-back to find a font for the given character.\n     *  If no font can be found for the character, the return value's data id\n     *  will be kInvalidDataId.\n     *  If the name is NULL, the match will start against any default fonts.\n     *  If the bpc47 is NULL, a default locale will be assumed.\n     *\n     *  Note that bpc47 is a combination of ISO 639, 15924, and 3166-1 codes,\n     *  so it is fine to just pass a ISO 639 here.\n     */\n    virtual SkFontIdentity matchNameStyleCharacter(const char familyName[], const SkFontStyle&,\n                                                   const char* bcp47[], int bcp47Count,\n                                                   SkUnichar character) const=0;\n\n    /**\n     *  Returns the data for the given data id.\n     *  Will return NULL if the data id is invalid.\n     *  Note that this is a data id, not a font id.\n     *\n     *  The caller must unref() the returned object.\n     */\n    virtual SkStreamAsset* getData(int dataId) const = 0;\n\nprivate:\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/ports/SkTypeface_mac.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTypeface_mac_DEFINED\n#define SkTypeface_mac_DEFINED\n\n#include \"SkTypeface.h\"\n\n#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)\n\n#include <CoreFoundation/CoreFoundation.h>\n\n#ifdef SK_BUILD_FOR_MAC\n#import <ApplicationServices/ApplicationServices.h>\n#endif\n\n#ifdef SK_BUILD_FOR_IOS\n#include <CoreText/CoreText.h>\n#endif\n\n/**\n *  Like the other Typeface create methods, this returns a new reference to the\n *  corresponding typeface for the specified CTFontRef. The caller must call\n *  unref() when it is finished.\n *\n *  The CFTypeRef parameter, if provided, will be kept referenced for the\n *  lifetime of the SkTypeface. This was introduced as a means to work around\n *  https://crbug.com/413332 .\n */\nSK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef, CFTypeRef = NULL);\n\n/**\n *  Returns the platform-specific CTFontRef handle for a\n *  given SkTypeface. Note that the returned CTFontRef gets\n *  released when the source SkTypeface is destroyed.\n *\n *  This method is deprecated. It may only be used by Blink Mac\n *  legacy code in special cases related to text-shaping\n *  with AAT fonts, clipboard handling and font fallback.\n *  See https://code.google.com/p/skia/issues/detail?id=3408\n */\nSK_API extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face);\n\n#endif  // defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)\n#endif  // SkTypeface_mac_DEFINED\n"
  },
  {
    "path": "include/ports/SkTypeface_win.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTypeface_win_DEFINED\n#define SkTypeface_win_DEFINED\n\n#include \"../private/SkLeanWindows.h\"\n#include \"SkTypeface.h\"\n\n#ifdef SK_BUILD_FOR_WIN\n\n/**\n *  Like the other Typeface create methods, this returns a new reference to the\n *  corresponding typeface for the specified logfont. The caller is responsible\n *  for calling unref() when it is finished.\n */\nSK_API SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);\n\n/**\n *  Copy the LOGFONT associated with this typeface into the lf parameter. Note\n *  that the lfHeight will need to be set afterwards, since the typeface does\n *  not track this (the paint does).\n *  typeface may be NULL, in which case we return the logfont for the default font.\n */\nSK_API void SkLOGFONTFromTypeface(const SkTypeface* typeface, LOGFONT* lf);\n\n/**\n  *  Set an optional callback to ensure that the data behind a LOGFONT is loaded.\n  *  This will get called if Skia tries to access the data but hits a failure.\n  *  Normally this is null, and is only required if the font data needs to be\n  *  remotely (re)loaded.\n  */\nSK_API void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*)(const LOGFONT&));\n\n// Experimental!\n//\nclass SkFontMgr;\nclass SkRemotableFontMgr;\nstruct IDWriteFactory;\nstruct IDWriteFontCollection;\nstruct IDWriteFontFallback;\n\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_GDI();\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory = NULL,\n                                                  IDWriteFontCollection* collection = NULL);\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWrite(IDWriteFactory* factory,\n                                                  IDWriteFontCollection* collection,\n                                                  IDWriteFontFallback* fallback);\n\n/**\n *  Creates an SkFontMgr which renders using DirectWrite and obtains its data\n *  from the SkRemotableFontMgr.\n *\n *  If DirectWrite could not be initialized, will return NULL.\n */\nSK_API sk_sp<SkFontMgr> SkFontMgr_New_DirectWriteRenderer(sk_sp<SkRemotableFontMgr>);\n\n/**\n *  Creates an SkRemotableFontMgr backed by DirectWrite using the default\n *  system font collection in the current locale.\n *\n *  If DirectWrite could not be initialized, will return NULL.\n */\nSK_API sk_sp<SkRemotableFontMgr> SkRemotableFontMgr_New_DirectWrite();\n\n#endif  // SK_BUILD_FOR_WIN\n#endif  // SkTypeface_win_DEFINED\n"
  },
  {
    "path": "include/private/GrAuditTrail.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrAuditTrail_DEFINED\n#define GrAuditTrail_DEFINED\n\n#include \"GrConfig.h\"\n#include \"GrGpuResource.h\"\n#include \"GrRenderTargetProxy.h\"\n#include \"SkRect.h\"\n#include \"SkString.h\"\n#include \"SkTArray.h\"\n#include \"SkTHash.h\"\n\nclass GrOp;\n\n/*\n * GrAuditTrail collects a list of draw ops, detailed information about those ops, and can dump them\n * to json.\n *\n * Capturing this information is expensive and consumes a lot of memory, therefore it is important\n * to enable auditing only when required and disable it promptly. The AutoEnable class helps to\n * ensure that the audit trail is disabled in a timely fashion. Once the information has been dealt\n * with, be sure to call reset(), or the log will simply keep growing.\n */\nclass GrAuditTrail {\npublic:\n    GrAuditTrail()\n    : fClientID(kGrAuditTrailInvalidID)\n    , fEnabled(false) {}\n\n    class AutoEnable {\n    public:\n        AutoEnable(GrAuditTrail* auditTrail)\n            : fAuditTrail(auditTrail) {\n            SkASSERT(!fAuditTrail->isEnabled());\n            fAuditTrail->setEnabled(true);\n        }\n\n        ~AutoEnable() {\n            SkASSERT(fAuditTrail->isEnabled());\n            fAuditTrail->setEnabled(false);\n        }\n\n    private:\n        GrAuditTrail* fAuditTrail;\n    };\n\n    class AutoManageOpList {\n    public:\n        AutoManageOpList(GrAuditTrail* auditTrail)\n                : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {}\n\n        ~AutoManageOpList() { fAuditTrail->fullReset(); }\n\n    private:\n        AutoEnable fAutoEnable;\n        GrAuditTrail* fAuditTrail;\n    };\n\n    class AutoCollectOps {\n    public:\n        AutoCollectOps(GrAuditTrail* auditTrail, int clientID)\n                : fAutoEnable(auditTrail), fAuditTrail(auditTrail) {\n            fAuditTrail->setClientID(clientID);\n        }\n\n        ~AutoCollectOps() { fAuditTrail->setClientID(kGrAuditTrailInvalidID); }\n\n    private:\n        AutoEnable fAutoEnable;\n        GrAuditTrail* fAuditTrail;\n    };\n\n    void pushFrame(const char* framename) {\n        SkASSERT(fEnabled);\n        fCurrentStackTrace.push_back(SkString(framename));\n    }\n\n    void addOp(const GrOp*, GrRenderTargetProxy::UniqueID proxyID);\n\n    void opsCombined(const GrOp* consumer, const GrOp* consumed);\n\n    // Because op combining is heavily dependent on sequence of draw calls, these calls will only\n    // produce valid information for the given draw sequence which preceeded them. Specifically, ops\n    // of future draw calls may combine with previous ops and thus would invalidate the json. What\n    // this means is that for some sequence of draw calls N, the below toJson calls will only\n    // produce JSON which reflects N draw calls. This JSON may or may not be accurate for N + 1 or\n    // N - 1 draws depending on the actual combining algorithm used.\n    SkString toJson(bool prettyPrint = false) const;\n\n    // returns a json string of all of the ops associated with a given client id\n    SkString toJson(int clientID, bool prettyPrint = false) const;\n\n    bool isEnabled() { return fEnabled; }\n    void setEnabled(bool enabled) { fEnabled = enabled; }\n\n    void setClientID(int clientID) { fClientID = clientID; }\n\n    // We could just return our internal bookkeeping struct if copying the data out becomes\n    // a performance issue, but until then its nice to decouple\n    struct OpInfo {\n        struct Op {\n            int    fClientID;\n            SkRect fBounds;\n        };\n\n        SkRect                   fBounds;\n        GrSurfaceProxy::UniqueID fProxyUniqueID;\n        SkTArray<Op>             fOps;\n    };\n\n    void getBoundsByClientID(SkTArray<OpInfo>* outInfo, int clientID);\n    void getBoundsByOpListID(OpInfo* outInfo, int opListID);\n\n    void fullReset();\n\n    static const int kGrAuditTrailInvalidID;\n\nprivate:\n    // TODO if performance becomes an issue, we can move to using SkVarAlloc\n    struct Op {\n        SkString toJson() const;\n        SkString fName;\n        SkTArray<SkString> fStackTrace;\n        SkRect fBounds;\n        int fClientID;\n        int fOpListID;\n        int fChildID;\n    };\n    typedef SkTArray<std::unique_ptr<Op>, true> OpPool;\n\n    typedef SkTArray<Op*> Ops;\n\n    struct OpNode {\n        OpNode(const GrSurfaceProxy::UniqueID& proxyID) : fProxyUniqueID(proxyID) { }\n        SkString toJson() const;\n\n        SkRect                         fBounds;\n        Ops                            fChildren;\n        const GrSurfaceProxy::UniqueID fProxyUniqueID;\n    };\n    typedef SkTArray<std::unique_ptr<OpNode>, true> OpList;\n\n    void copyOutFromOpList(OpInfo* outOpInfo, int opListID);\n\n    template <typename T>\n    static void JsonifyTArray(SkString* json, const char* name, const T& array,\n                              bool addComma);\n\n    OpPool fOpPool;\n    SkTHashMap<uint32_t, int> fIDLookup;\n    SkTHashMap<int, Ops*> fClientIDLookup;\n    OpList fOpList;\n    SkTArray<SkString> fCurrentStackTrace;\n\n    // The client can pass in an optional client ID which we will use to mark the ops\n    int fClientID;\n    bool fEnabled;\n};\n\n#define GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, invoke, ...) \\\n    if (audit_trail->isEnabled()) {                           \\\n        audit_trail->invoke(__VA_ARGS__);                     \\\n    }\n\n#define GR_AUDIT_TRAIL_AUTO_FRAME(audit_trail, framename) \\\n    GR_AUDIT_TRAIL_INVOKE_GUARD((audit_trail), pushFrame, framename);\n\n#define GR_AUDIT_TRAIL_RESET(audit_trail) \\\n    //GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, fullReset);\n\n#define GR_AUDIT_TRAIL_ADD_OP(audit_trail, op, proxy_id) \\\n    GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, addOp, op, proxy_id);\n\n#define GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(audit_trail, combineWith, op) \\\n    GR_AUDIT_TRAIL_INVOKE_GUARD(audit_trail, opsCombined, combineWith, op);\n\n#define GR_AUDIT_TRAIL_OP_RESULT_NEW(audit_trail, op) // Doesn't do anything now, one day...\n\n#endif\n"
  },
  {
    "path": "include/private/GrCCClipPath.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrCCClipPath_DEFINED\n#define GrCCClipPath_DEFINED\n\n#include \"GrTextureProxy.h\"\n#include \"SkPath.h\"\n\nclass GrCCAtlas;\nclass GrCCPerFlushResources;\nclass GrOnFlushResourceProvider;\nclass GrProxyProvider;\n\n/**\n * These are keyed by SkPath generation ID, and store which device-space paths are accessed and\n * where by clip FPs in a given opList. A single GrCCClipPath can be referenced by multiple FPs. At\n * flush time their coverage count masks are packed into atlas(es) alongside normal DrawPathOps.\n */\nclass GrCCClipPath {\npublic:\n    GrCCClipPath() = default;\n    GrCCClipPath(const GrCCClipPath&) = delete;\n\n    ~GrCCClipPath() {\n        // Ensure no clip FPs exist with a dangling pointer back into this class.\n        SkASSERT(!fAtlasLazyProxy || fAtlasLazyProxy->isUnique_debugOnly());\n        // Ensure no lazy proxy callbacks exist with a dangling pointer back into this class.\n        SkASSERT(fHasAtlasTransform);\n    }\n\n    bool isInitialized() const { return fAtlasLazyProxy != nullptr; }\n    void init(GrProxyProvider* proxyProvider,\n              const SkPath& deviceSpacePath, const SkIRect& accessRect,\n              int rtWidth, int rtHeight);\n\n    void addAccess(const SkIRect& accessRect) {\n        SkASSERT(this->isInitialized());\n        fAccessRect.join(accessRect);\n    }\n    GrTextureProxy* atlasLazyProxy() const {\n        SkASSERT(this->isInitialized());\n        return fAtlasLazyProxy.get();\n    }\n    const SkPath& deviceSpacePath() const {\n        SkASSERT(this->isInitialized());\n        return fDeviceSpacePath;\n    }\n    const SkIRect& pathDevIBounds() const {\n        SkASSERT(this->isInitialized());\n        return fPathDevIBounds;\n    }\n\n    void renderPathInAtlas(GrCCPerFlushResources*, GrOnFlushResourceProvider*);\n\n    const SkVector& atlasScale() const { SkASSERT(fHasAtlasTransform); return fAtlasScale; }\n    const SkVector& atlasTranslate() const { SkASSERT(fHasAtlasTransform); return fAtlasTranslate; }\n\nprivate:\n    sk_sp<GrTextureProxy> fAtlasLazyProxy;\n    SkPath fDeviceSpacePath;\n    SkIRect fPathDevIBounds;\n    SkIRect fAccessRect;\n\n    const GrCCAtlas* fAtlas = nullptr;\n    int16_t fAtlasOffsetX;\n    int16_t fAtlasOffsetY;\n    SkDEBUGCODE(bool fHasAtlas = false);\n\n    SkVector fAtlasScale;\n    SkVector fAtlasTranslate;\n    SkDEBUGCODE(bool fHasAtlasTransform = false);\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrCCPerOpListPaths.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrCCPerOpListPaths_DEFINED\n#define GrCCPerOpListPaths_DEFINED\n\n#include \"SkArenaAlloc.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTInternalLList.h\"\n#include \"GrCCClipPath.h\"\n#include <map>\n\nclass GrCCDrawPathsOp;\nclass GrCCPerFlushResources;\n\n/**\n * Tracks all the CCPR paths in a given opList that will be drawn when it flushes.\n */\n// DDL TODO: given the usage pattern in DDL mode, this could probably be non-atomic refcounting.\nclass GrCCPerOpListPaths : public SkRefCnt {\npublic:\n    ~GrCCPerOpListPaths();\n\n    SkTInternalLList<GrCCDrawPathsOp> fDrawOps;\n    std::map<uint32_t, GrCCClipPath> fClipPaths;\n    SkSTArenaAlloc<10 * 1024> fAllocator{10 * 1024 * 2};\n    sk_sp<const GrCCPerFlushResources> fFlushResources;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrColor.h",
    "content": "\n/*\n * Copyright 2010 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n\n#ifndef GrColor_DEFINED\n#define GrColor_DEFINED\n\n#include \"GrTypes.h\"\n#include \"SkColor.h\"\n#include \"SkColorPriv.h\"\n#include \"SkUnPreMultiply.h\"\n\n/**\n * GrColor is 4 bytes for R, G, B, A, in a specific order defined below. Whether the color is\n * premultiplied or not depends on the context in which it is being used.\n */\ntypedef uint32_t GrColor;\n\n// shift amount to assign a component to a GrColor int\n// These shift values are chosen for compatibility with GL attrib arrays\n// ES doesn't allow BGRA vertex attrib order so if they were not in this order\n// we'd have to swizzle in shaders.\n#ifdef SK_CPU_BENDIAN\n    #define GrColor_SHIFT_R     24\n    #define GrColor_SHIFT_G     16\n    #define GrColor_SHIFT_B     8\n    #define GrColor_SHIFT_A     0\n#else\n    #define GrColor_SHIFT_R     0\n    #define GrColor_SHIFT_G     8\n    #define GrColor_SHIFT_B     16\n    #define GrColor_SHIFT_A     24\n#endif\n\n/**\n *  Pack 4 components (RGBA) into a GrColor int\n */\nstatic inline GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a) {\n    SkASSERT((uint8_t)r == r);\n    SkASSERT((uint8_t)g == g);\n    SkASSERT((uint8_t)b == b);\n    SkASSERT((uint8_t)a == a);\n    return  (r << GrColor_SHIFT_R) |\n            (g << GrColor_SHIFT_G) |\n            (b << GrColor_SHIFT_B) |\n            (a << GrColor_SHIFT_A);\n}\n\n/**\n *  Packs a color with an alpha channel replicated across all four channels.\n */\nstatic inline GrColor GrColorPackA4(unsigned a) {\n    SkASSERT((uint8_t)a == a);\n    return  (a << GrColor_SHIFT_R) |\n            (a << GrColor_SHIFT_G) |\n            (a << GrColor_SHIFT_B) |\n            (a << GrColor_SHIFT_A);\n}\n\n// extract a component (byte) from a GrColor int\n\n#define GrColorUnpackR(color)   (((color) >> GrColor_SHIFT_R) & 0xFF)\n#define GrColorUnpackG(color)   (((color) >> GrColor_SHIFT_G) & 0xFF)\n#define GrColorUnpackB(color)   (((color) >> GrColor_SHIFT_B) & 0xFF)\n#define GrColorUnpackA(color)   (((color) >> GrColor_SHIFT_A) & 0xFF)\n\n/**\n *  Since premultiplied means that alpha >= color, we construct a color with\n *  each component==255 and alpha == 0 to be \"illegal\"\n */\n#define GrColor_ILLEGAL     (~(0xFF << GrColor_SHIFT_A))\n\n#define GrColor_WHITE 0xFFFFFFFF\n#define GrColor_TRANSPARENT_BLACK 0x0\n\n/**\n * Assert in debug builds that a GrColor is premultiplied.\n */\nstatic inline void GrColorIsPMAssert(GrColor SkDEBUGCODE(c)) {\n#ifdef SK_DEBUG\n    unsigned a = GrColorUnpackA(c);\n    unsigned r = GrColorUnpackR(c);\n    unsigned g = GrColorUnpackG(c);\n    unsigned b = GrColorUnpackB(c);\n\n    SkASSERT(r <= a);\n    SkASSERT(g <= a);\n    SkASSERT(b <= a);\n#endif\n}\n\n/** Inverts each color channel. */\nstatic inline GrColor GrInvertColor(GrColor c) {\n    U8CPU a = GrColorUnpackA(c);\n    U8CPU r = GrColorUnpackR(c);\n    U8CPU g = GrColorUnpackG(c);\n    U8CPU b = GrColorUnpackB(c);\n    return GrColorPackRGBA(0xff - r, 0xff - g, 0xff - b, 0xff - a);\n}\n\nstatic inline GrColor GrColorMul(GrColor c0, GrColor c1) {\n    U8CPU r = SkMulDiv255Round(GrColorUnpackR(c0), GrColorUnpackR(c1));\n    U8CPU g = SkMulDiv255Round(GrColorUnpackG(c0), GrColorUnpackG(c1));\n    U8CPU b = SkMulDiv255Round(GrColorUnpackB(c0), GrColorUnpackB(c1));\n    U8CPU a = SkMulDiv255Round(GrColorUnpackA(c0), GrColorUnpackA(c1));\n    return GrColorPackRGBA(r, g, b, a);\n}\n\nstatic inline GrColor GrColorSatAdd(GrColor c0, GrColor c1) {\n    unsigned r = SkTMin<unsigned>(GrColorUnpackR(c0) + GrColorUnpackR(c1), 0xff);\n    unsigned g = SkTMin<unsigned>(GrColorUnpackG(c0) + GrColorUnpackG(c1), 0xff);\n    unsigned b = SkTMin<unsigned>(GrColorUnpackB(c0) + GrColorUnpackB(c1), 0xff);\n    unsigned a = SkTMin<unsigned>(GrColorUnpackA(c0) + GrColorUnpackA(c1), 0xff);\n    return GrColorPackRGBA(r, g, b, a);\n}\n\n/** Converts a GrColor to an rgba array of GrGLfloat */\nstatic inline void GrColorToRGBAFloat(GrColor color, float rgba[4]) {\n    static const float ONE_OVER_255 = 1.f / 255.f;\n    rgba[0] = GrColorUnpackR(color) * ONE_OVER_255;\n    rgba[1] = GrColorUnpackG(color) * ONE_OVER_255;\n    rgba[2] = GrColorUnpackB(color) * ONE_OVER_255;\n    rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;\n}\n\n/** Normalizes and coverts an uint8_t to a float. [0, 255] -> [0.0, 1.0] */\nstatic inline float GrNormalizeByteToFloat(uint8_t value) {\n    static const float ONE_OVER_255 = 1.f / 255.f;\n    return value * ONE_OVER_255;\n}\n\n/** Determines whether the color is opaque or not. */\nstatic inline bool GrColorIsOpaque(GrColor color) {\n    return (color & (0xFFU << GrColor_SHIFT_A)) == (0xFFU << GrColor_SHIFT_A);\n}\n\nstatic inline GrColor GrPremulColor(GrColor color) {\n    unsigned r = GrColorUnpackR(color);\n    unsigned g = GrColorUnpackG(color);\n    unsigned b = GrColorUnpackB(color);\n    unsigned a = GrColorUnpackA(color);\n    return GrColorPackRGBA(SkMulDiv255Round(r, a),\n                           SkMulDiv255Round(g, a),\n                           SkMulDiv255Round(b, a),\n                           a);\n}\n\n/** Returns an unpremuled version of the GrColor. */\nstatic inline GrColor GrUnpremulColor(GrColor color) {\n    GrColorIsPMAssert(color);\n    unsigned r = GrColorUnpackR(color);\n    unsigned g = GrColorUnpackG(color);\n    unsigned b = GrColorUnpackB(color);\n    unsigned a = GrColorUnpackA(color);\n    SkPMColor colorPM = SkPackARGB32(a, r, g, b);\n    SkColor colorUPM = SkUnPreMultiply::PMColorToColor(colorPM);\n\n    r = SkColorGetR(colorUPM);\n    g = SkColorGetG(colorUPM);\n    b = SkColorGetB(colorUPM);\n    a = SkColorGetA(colorUPM);\n\n    return GrColorPackRGBA(r, g, b, a);\n}\n\n\n/**\n* Similarly, GrColor4f is 4 floats for R, G, B, A, in that order. And like GrColor, whether\n* the color is premultiplied or not depends on the context.\n*/\nstruct GrColor4f {\n    float fRGBA[4];\n\n    GrColor4f() {}\n    GrColor4f(float r, float g, float b, float a) {\n        fRGBA[0] = r;\n        fRGBA[1] = g;\n        fRGBA[2] = b;\n        fRGBA[3] = a;\n    }\n\n    enum Illegal_Constructor {\n        kIllegalConstructor\n    };\n    GrColor4f(Illegal_Constructor) {\n        fRGBA[0] = SK_FloatNaN;\n        fRGBA[1] = SK_FloatNaN;\n        fRGBA[2] = SK_FloatNaN;\n        fRGBA[3] = SK_FloatNaN;\n    }\n\n    static GrColor4f OpaqueWhite() {\n        return GrColor4f(1.0f, 1.0f, 1.0f, 1.0f);\n    }\n\n    static GrColor4f TransparentBlack() {\n        return GrColor4f(0.0f, 0.0f, 0.0f, 0.0f);\n    }\n\n    static GrColor4f FromGrColor(GrColor color) {\n        GrColor4f result;\n        GrColorToRGBAFloat(color, result.fRGBA);\n        return result;\n    }\n\n    static GrColor4f FromSkColor4f(const SkColor4f& color) {\n        return GrColor4f(color.fR, color.fG, color.fB, color.fA);\n    }\n\n    GrColor4f modulate(const GrColor4f& x) const {\n        return GrColor4f(fRGBA[0] * x.fRGBA[0],\n                         fRGBA[1] * x.fRGBA[1],\n                         fRGBA[2] * x.fRGBA[2],\n                         fRGBA[3] * x.fRGBA[3]);\n    }\n\n    GrColor4f mulByScalar(float x) const {\n        return GrColor4f(fRGBA[0] * x, fRGBA[1] * x, fRGBA[2] * x, fRGBA[3] * x);\n    }\n\n    bool operator==(const GrColor4f& other) const {\n        return\n            fRGBA[0] == other.fRGBA[0] &&\n            fRGBA[1] == other.fRGBA[1] &&\n            fRGBA[2] == other.fRGBA[2] &&\n            fRGBA[3] == other.fRGBA[3];\n    }\n    bool operator!=(const GrColor4f& other) const {\n        return !(*this == other);\n    }\n\n    GrColor toGrColor() const {\n        return GrColorPackRGBA(\n            SkTPin<unsigned>(static_cast<unsigned>(fRGBA[0] * 255.0f + 0.5f), 0, 255),\n            SkTPin<unsigned>(static_cast<unsigned>(fRGBA[1] * 255.0f + 0.5f), 0, 255),\n            SkTPin<unsigned>(static_cast<unsigned>(fRGBA[2] * 255.0f + 0.5f), 0, 255),\n            SkTPin<unsigned>(static_cast<unsigned>(fRGBA[3] * 255.0f + 0.5f), 0, 255));\n    }\n\n    SkColor4f toSkColor4f() const {\n        return SkColor4f { fRGBA[0], fRGBA[1], fRGBA[2], fRGBA[3] };\n    }\n\n    GrColor4f opaque() const {\n        return GrColor4f(fRGBA[0], fRGBA[1], fRGBA[2], 1.0f);\n    }\n\n    bool isOpaque() const {\n        return fRGBA[3] >= 1.f;  // just in case precision causes a superopaque value.\n    }\n\n    GrColor4f premul() const {\n        float a = fRGBA[3];\n        return GrColor4f(fRGBA[0] * a, fRGBA[1] * a, fRGBA[2] * a, a);\n    }\n\n    GrColor4f unpremul() const {\n        float a = fRGBA[3];\n        if (a <= 0.0f) {\n            return GrColor4f(0.0f, 0.0f, 0.0f, 0.0f);\n        }\n        float invAlpha = 1.0f / a;\n        return GrColor4f(fRGBA[0] * invAlpha, fRGBA[1] * invAlpha, fRGBA[2] * invAlpha, a);\n    }\n};\n\n/**\n * Flags used for bitfields of color components. They are defined so that the bit order reflects the\n * GrColor shift order.\n */\nenum GrColorComponentFlags {\n    kR_GrColorComponentFlag = 1 << (GrColor_SHIFT_R / 8),\n    kG_GrColorComponentFlag = 1 << (GrColor_SHIFT_G / 8),\n    kB_GrColorComponentFlag = 1 << (GrColor_SHIFT_B / 8),\n    kA_GrColorComponentFlag = 1 << (GrColor_SHIFT_A / 8),\n\n    kNone_GrColorComponentFlags = 0,\n\n    kRGB_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |\n                                  kB_GrColorComponentFlag),\n\n    kRGBA_GrColorComponentFlags = (kR_GrColorComponentFlag | kG_GrColorComponentFlag |\n                                   kB_GrColorComponentFlag | kA_GrColorComponentFlag)\n};\n\nGR_MAKE_BITFIELD_OPS(GrColorComponentFlags)\n\n#endif\n"
  },
  {
    "path": "include/private/GrGLSL.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrGLSL_DEFINED\n#define GrGLSL_DEFINED\n\n#include \"GrTypesPriv.h\"\n#include \"SkString.h\"\n\nclass GrShaderCaps;\n\n// Limited set of GLSL versions we build shaders for. Caller should round\n// down the GLSL version to one of these enums.\nenum GrGLSLGeneration {\n    /**\n     * Desktop GLSL 1.10 and ES2 shading language (based on desktop GLSL 1.20)\n     */\n    k110_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 1.30\n     */\n    k130_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 1.40\n     */\n    k140_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 1.50\n     */\n    k150_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 3.30, and ES GLSL 3.00\n     */\n    k330_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 4.00\n     */\n    k400_GrGLSLGeneration,\n    /**\n     * Desktop GLSL 4.20\n     */\n    k420_GrGLSLGeneration,\n    /**\n     * ES GLSL 3.10 only TODO Make GLSLCap objects to make this more granular\n     */\n    k310es_GrGLSLGeneration,\n    /**\n     * ES GLSL 3.20\n     */\n    k320es_GrGLSLGeneration,\n};\n\nbool GrGLSLSupportsNamedFragmentShaderOutputs(GrGLSLGeneration);\n\n/**\n * Adds a line of GLSL code to declare the default precision for float types.\n */\nvoid GrGLSLAppendDefaultFloatPrecisionDeclaration(GrSLPrecision,\n                                                  const GrShaderCaps&,\n                                                  SkString* out);\n\n/**\n * Converts a GrSLPrecision to its corresponding GLSL precision qualifier.\n */\nstatic inline const char* GrGLSLPrecisionString(GrSLPrecision p) {\n    switch (p) {\n        case kLow_GrSLPrecision:\n            return \"lowp\";\n        case kMedium_GrSLPrecision:\n            return \"mediump\";\n        case kHigh_GrSLPrecision:\n            return \"highp\";\n        case kDefault_GrSLPrecision:\n            return \"\";\n        default:\n            SK_ABORT(\"Unexpected precision type.\");\n            return \"\";\n    }\n}\n\n/**\n * Converts a GrSLType to a string containing the name of the equivalent GLSL type.\n */\nconst char* GrGLSLTypeString(const GrShaderCaps* shaderCaps, GrSLType t);\n\n#endif\n"
  },
  {
    "path": "include/private/GrOpList.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrOpList_DEFINED\n#define GrOpList_DEFINED\n\n#include \"GrColor.h\"\n#include \"GrSurfaceProxyRef.h\"\n#include \"GrTextureProxy.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTDArray.h\"\n\nclass GrAuditTrail;\nclass GrCaps;\nclass GrOpFlushState;\nclass GrRenderTargetOpList;\nclass GrResourceAllocator;\nclass GrResourceProvider;\nclass GrSurfaceProxy;\nclass GrTextureOpList;\n\nstruct SkIPoint;\nstruct SkIRect;\n\nclass GrOpList : public SkRefCnt {\npublic:\n    GrOpList(GrResourceProvider*, GrSurfaceProxy*, GrAuditTrail*);\n    ~GrOpList() override;\n\n    // These four methods are invoked at flush time\n    bool instantiate(GrResourceProvider* resourceProvider);\n    // Instantiates any \"threaded\" texture proxies that are being prepared elsewhere\n    void instantiateDeferredProxies(GrResourceProvider* resourceProvider);\n    void prepare(GrOpFlushState* flushState);\n    bool execute(GrOpFlushState* flushState) { return this->onExecute(flushState); }\n\n    virtual bool copySurface(const GrCaps& caps,\n                             GrSurfaceProxy* dst,\n                             GrSurfaceProxy* src,\n                             const SkIRect& srcRect,\n                             const SkIPoint& dstPoint) = 0;\n\n    virtual void makeClosed(const GrCaps&) {\n        if (!this->isClosed()) {\n            this->setFlag(kClosed_Flag);\n            fTarget.removeRef();\n        }\n    }\n\n    // Called when this class will survive a flush and needs to truncate its ops and start over.\n    // TODO: ultimately it should be invalid for an op list to survive a flush.\n    // https://bugs.chromium.org/p/skia/issues/detail?id=7111\n    virtual void endFlush();\n\n    bool isClosed() const { return this->isSetFlag(kClosed_Flag); }\n\n    /*\n     * Notify this GrOpList that it relies on the contents of 'dependedOn'\n     */\n    void addDependency(GrSurfaceProxy* dependedOn, const GrCaps& caps);\n\n    /*\n     * Does this opList depend on 'dependedOn'?\n     */\n    bool dependsOn(GrOpList* dependedOn) const {\n        for (int i = 0; i < fDependencies.count(); ++i) {\n            if (fDependencies[i] == dependedOn) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /*\n     * Safely cast this GrOpList to a GrTextureOpList (if possible).\n     */\n    virtual GrTextureOpList* asTextureOpList() { return nullptr; }\n\n    /*\n     * Safely case this GrOpList to a GrRenderTargetOpList (if possible).\n     */\n    virtual GrRenderTargetOpList* asRenderTargetOpList() { return nullptr; }\n\n    uint32_t uniqueID() const { return fUniqueID; }\n\n    /*\n     * Dump out the GrOpList dependency DAG\n     */\n    SkDEBUGCODE(virtual void dump(bool printDependencies) const;)\n\n    SkDEBUGCODE(virtual int numOps() const = 0;)\n    SkDEBUGCODE(virtual int numClips() const { return 0; })\n\n    // TODO: it would be nice for this to be hidden\n    void setStencilLoadOp(GrLoadOp loadOp) { fStencilLoadOp = loadOp; }\n\nprotected:\n    bool isInstantiated() const;\n\n    GrSurfaceProxyRef fTarget;\n    GrAuditTrail*     fAuditTrail;\n\n    GrLoadOp          fColorLoadOp    = GrLoadOp::kLoad;\n    GrColor           fLoadClearColor = 0x0;\n    GrLoadOp          fStencilLoadOp  = GrLoadOp::kLoad;\n\n    // List of texture proxies whose contents are being prepared on a worker thread\n    SkTArray<GrTextureProxy*, true> fDeferredProxies;\n\nprivate:\n    friend class GrDrawingManager; // for resetFlag, TopoSortTraits & gatherProxyIntervals\n\n    // Remove all Ops which reference proxies that have not been instantiated.\n    virtual void purgeOpsWithUninstantiatedProxies() = 0;\n\n    // Feed proxy usage intervals to the GrResourceAllocator class\n    virtual void gatherProxyIntervals(GrResourceAllocator*) const = 0;\n\n    static uint32_t CreateUniqueID();\n\n    enum Flags {\n        kClosed_Flag    = 0x01,   //!< This GrOpList can't accept any more ops\n\n        kWasOutput_Flag = 0x02,   //!< Flag for topological sorting\n        kTempMark_Flag  = 0x04,   //!< Flag for topological sorting\n    };\n\n    void setFlag(uint32_t flag) {\n        fFlags |= flag;\n    }\n\n    void resetFlag(uint32_t flag) {\n        fFlags &= ~flag;\n    }\n\n    bool isSetFlag(uint32_t flag) const {\n        return SkToBool(fFlags & flag);\n    }\n\n    struct TopoSortTraits {\n        static void Output(GrOpList* opList, int /* index */) {\n            opList->setFlag(GrOpList::kWasOutput_Flag);\n        }\n        static bool WasOutput(const GrOpList* opList) {\n            return opList->isSetFlag(GrOpList::kWasOutput_Flag);\n        }\n        static void SetTempMark(GrOpList* opList) {\n            opList->setFlag(GrOpList::kTempMark_Flag);\n        }\n        static void ResetTempMark(GrOpList* opList) {\n            opList->resetFlag(GrOpList::kTempMark_Flag);\n        }\n        static bool IsTempMarked(const GrOpList* opList) {\n            return opList->isSetFlag(GrOpList::kTempMark_Flag);\n        }\n        static int NumDependencies(const GrOpList* opList) {\n            return opList->fDependencies.count();\n        }\n        static GrOpList* Dependency(GrOpList* opList, int index) {\n            return opList->fDependencies[index];\n        }\n    };\n\n    virtual void onPrepare(GrOpFlushState* flushState) = 0;\n    virtual bool onExecute(GrOpFlushState* flushState) = 0;\n\n    void addDependency(GrOpList* dependedOn);\n\n    uint32_t               fUniqueID;\n    uint32_t               fFlags;\n\n    // 'this' GrOpList relies on the output of the GrOpLists in 'fDependencies'\n    SkSTArray<1, GrOpList*, true> fDependencies;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrRenderTargetProxy.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrRenderTargetProxy_DEFINED\n#define GrRenderTargetProxy_DEFINED\n\n#include \"GrSurfaceProxy.h\"\n#include \"GrTypesPriv.h\"\n\nclass GrResourceProvider;\nclass GrRenderTargetProxyPriv;\n\n// This class delays the acquisition of RenderTargets until they are actually\n// required\n// Beware: the uniqueID of the RenderTargetProxy will usually be different than\n// the uniqueID of the RenderTarget it represents!\nclass GrRenderTargetProxy : virtual public GrSurfaceProxy {\npublic:\n    GrRenderTargetProxy* asRenderTargetProxy() override { return this; }\n    const GrRenderTargetProxy* asRenderTargetProxy() const override { return this; }\n\n    // Actually instantiate the backing rendertarget, if necessary.\n    bool instantiate(GrResourceProvider*) override;\n\n    GrFSAAType fsaaType() const {\n        if (fSampleCnt <= 1) {\n            SkASSERT(!this->hasMixedSamples());\n            return GrFSAAType::kNone;\n        }\n        return this->hasMixedSamples() ? GrFSAAType::kMixedSamples : GrFSAAType::kUnifiedMSAA;\n    }\n\n    /*\n     * When instantiated does this proxy require a stencil buffer?\n     */\n    void setNeedsStencil() { fNeedsStencil = true; }\n    bool needsStencil() const { return fNeedsStencil; }\n\n    /**\n     * Returns the number of samples/pixel in the stencil buffer (One if non-MSAA).\n     */\n    int numStencilSamples() const { return fSampleCnt; }\n\n    /**\n     * Returns the number of samples/pixel in the color buffer (One if non-MSAA or mixed sampled).\n     */\n    int numColorSamples() const {\n        return GrFSAAType::kMixedSamples == this->fsaaType() ? 1 : fSampleCnt;\n    }\n\n    int maxWindowRectangles(const GrCaps& caps) const;\n\n    // TODO: move this to a priv class!\n    bool refsWrappedObjects() const;\n\n    // Provides access to special purpose functions.\n    GrRenderTargetProxyPriv rtPriv();\n    const GrRenderTargetProxyPriv rtPriv() const;\n\nprotected:\n    friend class GrProxyProvider;  // for ctors\n    friend class GrRenderTargetProxyPriv;\n\n    // Deferred version\n    GrRenderTargetProxy(const GrCaps&, const GrSurfaceDesc&, GrSurfaceOrigin, SkBackingFit,\n                        SkBudgeted, GrInternalSurfaceFlags);\n\n    // Lazy-callback version\n    // There are two main use cases for lazily-instantiated proxies:\n    //   basic knowledge - width, height, config, samples, origin are known\n    //   minimal knowledge - only config is known.\n    //\n    // The basic knowledge version is used for DDL where we know the type of proxy we are going to\n    // use, but we don't have access to the GPU yet to instantiate it.\n    //\n    // The minimal knowledge version is used for CCPR where we are generating an atlas but we do not\n    // know the final size until flush time.\n    GrRenderTargetProxy(LazyInstantiateCallback&&, LazyInstantiationType lazyType,\n                        const GrSurfaceDesc&, GrSurfaceOrigin, SkBackingFit, SkBudgeted,\n                        GrInternalSurfaceFlags);\n\n    // Wrapped version\n    GrRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin);\n\n    sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;\n\nprivate:\n    void setHasMixedSamples() {\n        fSurfaceFlags |= GrInternalSurfaceFlags::kMixedSampled;\n    }\n    bool hasMixedSamples() const { return fSurfaceFlags & GrInternalSurfaceFlags::kMixedSampled; }\n\n    void setSupportsWindowRects() {\n        fSurfaceFlags |= GrInternalSurfaceFlags::kWindowRectsSupport;\n    }\n    bool supportsWindowRects() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kWindowRectsSupport;\n    }\n\n    void setGLRTFBOIDIs0() {\n        fSurfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;\n    }\n    bool glRTFBOIDIs0() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kGLRTFBOIDIs0;\n    }\n\n\n    size_t onUninstantiatedGpuMemorySize() const override;\n    SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;)\n\n    int                 fSampleCnt;\n    bool                fNeedsStencil;\n\n    // For wrapped render targets the actual GrRenderTarget is stored in the GrIORefProxy class.\n    // For deferred proxies that pointer is filled in when we need to instantiate the\n    // deferred resource.\n\n    typedef GrSurfaceProxy INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrSharedEnums.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSharedEnums_DEFINED\n#define GrSharedEnums_DEFINED\n\n/*************************************************************************************************/\n/* This file is used from both C++ and SkSL, so we need to stick to syntax compatible with both. */\n/*************************************************************************************************/\n\n/**\n * We have coverage effects that clip rendering to the edge of some geometric primitive.\n * This enum specifies how that clipping is performed. Not all factories that take a\n * GrProcessorEdgeType will succeed with all values and it is up to the caller to check for\n * a NULL return.\n */\nenum class GrClipEdgeType {\n    kFillBW,\n    kFillAA,\n    kInverseFillBW,\n    kInverseFillAA,\n    kHairlineAA,\n\n    kLast = kHairlineAA\n};\n\nenum class PMConversion {\n    kToPremul        = 0,\n    kToUnpremul      = 1,\n    kPMConversionCnt = 2\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrSingleOwner.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSingleOwner_DEFINED\n#define GrSingleOwner_DEFINED\n\n#include \"SkTypes.h\"\n\n#ifdef SK_DEBUG\n#include \"SkMutex.h\"\n#include \"SkThreadID.h\"\n\n// This is a debug tool to verify an object is only being used from one thread at a time.\nclass GrSingleOwner {\npublic:\n     GrSingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {}\n\n     struct AutoEnforce {\n         AutoEnforce(GrSingleOwner* so) : fSO(so) { fSO->enter(); }\n         ~AutoEnforce() { fSO->exit(); }\n\n         GrSingleOwner* fSO;\n     };\n\nprivate:\n     void enter() {\n         SkAutoMutexAcquire lock(fMutex);\n         SkThreadID self = SkGetThreadID();\n         SkASSERT(fOwner == self || fOwner == kIllegalThreadID);\n         fReentranceCount++;\n         fOwner = self;\n     }\n\n     void exit() {\n         SkAutoMutexAcquire lock(fMutex);\n         SkASSERT(fOwner == SkGetThreadID());\n         fReentranceCount--;\n         if (fReentranceCount == 0) {\n             fOwner = kIllegalThreadID;\n         }\n     }\n\n     SkMutex fMutex;\n     SkThreadID fOwner;    // guarded by fMutex\n     int fReentranceCount; // guarded by fMutex\n};\n#else\nclass GrSingleOwner {}; // Provide a dummy implementation so we can pass pointers to constructors\n#endif\n\n#endif\n"
  },
  {
    "path": "include/private/GrSurfaceProxy.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSurfaceProxy_DEFINED\n#define GrSurfaceProxy_DEFINED\n\n#include \"GrGpuResource.h\"\n#include \"GrSurface.h\"\n\n#include \"SkRect.h\"\n\nclass GrBackendTexture;\nclass GrCaps;\nclass GrOpList;\nclass GrProxyProvider;\nclass GrRenderTargetOpList;\nclass GrRenderTargetProxy;\nclass GrResourceProvider;\nclass GrSurfaceContext;\nclass GrSurfaceProxyPriv;\nclass GrTextureOpList;\nclass GrTextureProxy;\n\n// This class replicates the functionality GrIORef<GrSurface> but tracks the\n// utilitization for later resource allocation (for the deferred case) and\n// forwards on the utilization in the wrapped case\nclass GrIORefProxy : public SkNoncopyable {\npublic:\n    void ref() const {\n        this->validate();\n\n        ++fRefCnt;\n        if (fTarget) {\n            fTarget->ref();\n        }\n    }\n\n    void unref() const {\n        this->validate();\n\n        if (fTarget) {\n            fTarget->unref();\n        }\n\n        --fRefCnt;\n        this->didRemoveRefOrPendingIO();\n    }\n\n#ifdef SK_DEBUG\n    bool isUnique_debugOnly() const { // For asserts.\n        SkASSERT(fRefCnt >= 0 && fPendingWrites >= 0 && fPendingReads >= 0);\n        return 1 == fRefCnt + fPendingWrites + fPendingReads;\n    }\n#endif\n\n    void release() {\n        // The proxy itself may still have multiple refs. It can be owned by an SkImage and multiple\n        // SkDeferredDisplayLists at the same time if we are using DDLs.\n        SkASSERT(0 == fPendingReads);\n        SkASSERT(0 == fPendingWrites);\n\n        SkASSERT(fRefCnt == fTarget->fRefCnt);\n        SkASSERT(!fTarget->internalHasPendingIO());\n        // In the current hybrid world, the proxy and backing surface are ref/unreffed in\n        // synchrony. In this instance we're deInstantiating the proxy so, regardless of the\n        // number of refs on the backing surface, we're going to remove it. If/when the proxy\n        // is re-instantiated all the refs on the proxy (presumably due to multiple uses in ops)\n        // will be transfered to the new surface.\n        for (int refs = fTarget->fRefCnt; refs; --refs) {\n            fTarget->unref();\n        }\n        fTarget = nullptr;\n    }\n\n    void validate() const {\n#ifdef SK_DEBUG\n        SkASSERT(fRefCnt >= 0);\n        SkASSERT(fPendingReads >= 0);\n        SkASSERT(fPendingWrites >= 0);\n        SkASSERT(fRefCnt + fPendingReads + fPendingWrites >= 1);\n\n        if (fTarget) {\n            // The backing GrSurface can have more refs than the proxy if the proxy\n            // started off wrapping an external resource (that came in with refs).\n            // The GrSurface should never have fewer refs than the proxy however.\n            SkASSERT(fTarget->fRefCnt >= fRefCnt);\n            SkASSERT(fTarget->fPendingReads >= fPendingReads);\n            SkASSERT(fTarget->fPendingWrites >= fPendingWrites);\n        }\n#endif\n    }\n\n    int32_t getProxyRefCnt_TestOnly() const;\n    int32_t getBackingRefCnt_TestOnly() const;\n    int32_t getPendingReadCnt_TestOnly() const;\n    int32_t getPendingWriteCnt_TestOnly() const;\n\n    void addPendingRead() const {\n        this->validate();\n\n        ++fPendingReads;\n        if (fTarget) {\n            fTarget->addPendingRead();\n        }\n    }\n\n    void completedRead() const {\n        this->validate();\n\n        if (fTarget) {\n            fTarget->completedRead();\n        }\n\n        --fPendingReads;\n        this->didRemoveRefOrPendingIO();\n    }\n\n    void addPendingWrite() const {\n        this->validate();\n\n        ++fPendingWrites;\n        if (fTarget) {\n            fTarget->addPendingWrite();\n        }\n    }\n\n    void completedWrite() const {\n        this->validate();\n\n        if (fTarget) {\n            fTarget->completedWrite();\n        }\n\n        --fPendingWrites;\n        this->didRemoveRefOrPendingIO();\n    }\n\nprotected:\n    GrIORefProxy() : fTarget(nullptr), fRefCnt(1), fPendingReads(0), fPendingWrites(0) {}\n    GrIORefProxy(sk_sp<GrSurface> surface) : fRefCnt(1), fPendingReads(0), fPendingWrites(0) {\n        // Since we're manually forwarding on refs & unrefs we don't want sk_sp doing\n        // anything extra.\n        fTarget = surface.release();\n    }\n    virtual ~GrIORefProxy() {\n        // We don't unref 'fTarget' here since the 'unref' method will already\n        // have forwarded on the unref call that got us here.\n    }\n\n    // This GrIORefProxy was deferred before but has just been instantiated. To\n    // make all the reffing & unreffing work out we now need to transfer any deferred\n    // refs & unrefs to the new GrSurface\n    void transferRefs() {\n        SkASSERT(fTarget);\n\n        SkASSERT(fTarget->fRefCnt > 0);\n        fTarget->fRefCnt += (fRefCnt-1); // don't xfer the proxy's creation ref\n        fTarget->fPendingReads += fPendingReads;\n        fTarget->fPendingWrites += fPendingWrites;\n    }\n\n    bool internalHasPendingIO() const {\n        if (fTarget) {\n            return fTarget->internalHasPendingIO();\n        }\n\n        return SkToBool(fPendingWrites | fPendingReads);\n    }\n\n    bool internalHasPendingWrite() const {\n        if (fTarget) {\n            return fTarget->internalHasPendingWrite();\n        }\n\n        return SkToBool(fPendingWrites);\n    }\n\n    // For deferred proxies this will be null. For wrapped proxies it will point to the\n    // wrapped resource.\n    GrSurface* fTarget;\n\nprivate:\n    // This class is used to manage conversion of refs to pending reads/writes.\n    friend class GrSurfaceProxyRef;\n    template <typename, GrIOType> friend class GrPendingIOResource;\n\n    void didRemoveRefOrPendingIO() const {\n        if (0 == fPendingReads && 0 == fPendingWrites && 0 == fRefCnt) {\n            delete this;\n        }\n    }\n\n    mutable int32_t fRefCnt;\n    mutable int32_t fPendingReads;\n    mutable int32_t fPendingWrites;\n};\n\nclass GrSurfaceProxy : public GrIORefProxy {\npublic:\n    enum class LazyInstantiationType {\n        kSingleUse,         // Instantiation callback is allowed to be called only once\n        kMultipleUse,       // Instantiation callback can be called multiple times.\n        kUninstantiate,     // Instantiation callback can be called multiple times,\n                            // but we will uninstantiate the proxy after every flush\n    };\n\n    enum class LazyState {\n        kNot,       // The proxy is instantiated or does not have a lazy callback\n        kPartially, // The proxy has a lazy callback but knows basic information about itself.\n        kFully,     // The proxy has a lazy callback and also doesn't know its width, height, etc.\n    };\n\n    LazyState lazyInstantiationState() const {\n        if (fTarget || !SkToBool(fLazyInstantiateCallback)) {\n            return LazyState::kNot;\n        } else {\n            if (fWidth <= 0) {\n                SkASSERT(fHeight <= 0);\n                return LazyState::kFully;\n            } else {\n                SkASSERT(fHeight > 0);\n                return LazyState::kPartially;\n            }\n        }\n    }\n\n    GrPixelConfig config() const { return fConfig; }\n    int width() const {\n        SkASSERT(LazyState::kFully != this->lazyInstantiationState());\n        return fWidth;\n    }\n    int height() const {\n        SkASSERT(LazyState::kFully != this->lazyInstantiationState());\n        return fHeight;\n    }\n    int worstCaseWidth() const;\n    int worstCaseHeight() const;\n    /**\n     * Helper that gets the width and height of the surface as a bounding rectangle.\n     */\n    SkRect getBoundsRect() const {\n        SkASSERT(LazyState::kFully != this->lazyInstantiationState());\n        return SkRect::MakeIWH(this->width(), this->height());\n    }\n    /**\n     * Helper that gets the worst case width and height of the surface as a bounding rectangle.\n     */\n    SkRect getWorstCaseBoundsRect() const {\n        SkASSERT(LazyState::kFully != this->lazyInstantiationState());\n        return SkRect::MakeIWH(this->worstCaseWidth(), this->worstCaseHeight());\n    }\n\n    GrSurfaceOrigin origin() const {\n        SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);\n        return fOrigin;\n    }\n\n    class UniqueID {\n    public:\n        static UniqueID InvalidID() {\n            return UniqueID(uint32_t(SK_InvalidUniqueID));\n        }\n\n        // wrapped\n        explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }\n        // deferred and lazy-callback\n        UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }\n\n        uint32_t asUInt() const { return fID; }\n\n        bool operator==(const UniqueID& other) const {\n            return fID == other.fID;\n        }\n        bool operator!=(const UniqueID& other) const {\n            return !(*this == other);\n        }\n\n        void makeInvalid() { fID = SK_InvalidUniqueID; }\n        bool isInvalid() const { return SK_InvalidUniqueID == fID; }\n\n    private:\n        explicit UniqueID(uint32_t id) : fID(id) {}\n\n        uint32_t fID;\n    };\n\n    /*\n     * The contract for the uniqueID is:\n     *   for wrapped resources:\n     *      the uniqueID will match that of the wrapped resource\n     *\n     *   for deferred resources:\n     *      the uniqueID will be different from the real resource, when it is allocated\n     *      the proxy's uniqueID will not change across the instantiate call\n     *\n     *    the uniqueIDs of the proxies and the resources draw from the same pool\n     *\n     * What this boils down to is that the uniqueID of a proxy can be used to consistently\n     * track/identify a proxy but should never be used to distinguish between\n     * resources and proxies - beware!\n     */\n    UniqueID uniqueID() const { return fUniqueID; }\n\n    UniqueID underlyingUniqueID() const {\n        if (fTarget) {\n            return UniqueID(fTarget->uniqueID());\n        }\n\n        return fUniqueID;\n    }\n\n    virtual bool instantiate(GrResourceProvider* resourceProvider) = 0;\n\n    void deInstantiate();\n\n    /**\n     * @return the texture proxy associated with the surface proxy, may be NULL.\n     */\n    virtual GrTextureProxy* asTextureProxy() { return nullptr; }\n    virtual const GrTextureProxy* asTextureProxy() const { return nullptr; }\n\n    /**\n     * @return the render target proxy associated with the surface proxy, may be NULL.\n     */\n    virtual GrRenderTargetProxy* asRenderTargetProxy() { return nullptr; }\n    virtual const GrRenderTargetProxy* asRenderTargetProxy() const { return nullptr; }\n\n    /**\n     * Does the resource count against the resource budget?\n     */\n    SkBudgeted isBudgeted() const { return fBudgeted; }\n\n    void setLastOpList(GrOpList* opList);\n    GrOpList* getLastOpList() { return fLastOpList; }\n\n    GrRenderTargetOpList* getLastRenderTargetOpList();\n    GrTextureOpList* getLastTextureOpList();\n\n    /**\n     * Retrieves the amount of GPU memory that will be or currently is used by this resource\n     * in bytes. It is approximate since we aren't aware of additional padding or copies made\n     * by the driver.\n     *\n     * @return the amount of GPU memory used in bytes\n     */\n    size_t gpuMemorySize() const {\n        SkASSERT(LazyState::kFully != this->lazyInstantiationState());\n        if (fTarget) {\n            return fTarget->gpuMemorySize();\n        }\n        if (kInvalidGpuMemorySize == fGpuMemorySize) {\n            fGpuMemorySize = this->onUninstantiatedGpuMemorySize();\n            SkASSERT(kInvalidGpuMemorySize != fGpuMemorySize);\n        }\n        return fGpuMemorySize;\n    }\n\n    // Helper function that creates a temporary SurfaceContext to perform the copy\n    // It always returns a kExact-backed proxy bc it is used when converting an SkSpecialImage\n    // to an SkImage. The copy is is not a render target and not multisampled.\n    static sk_sp<GrTextureProxy> Copy(GrContext*, GrSurfaceProxy* src, GrMipMapped,\n                                      SkIRect srcRect, SkBudgeted);\n\n    // Copy the entire 'src'\n    // It always returns a kExact-backed proxy bc it is used in SkGpuDevice::snapSpecial\n    static sk_sp<GrTextureProxy> Copy(GrContext* context, GrSurfaceProxy* src, GrMipMapped,\n                                      SkBudgeted budgeted);\n\n    // Test-only entry point - should decrease in use as proxies propagate\n    static sk_sp<GrSurfaceContext> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,\n                                            GrSurfaceOrigin, GrSurfaceProxy* srcProxy);\n\n    bool isWrapped_ForTesting() const;\n\n    SkDEBUGCODE(void validate(GrContext*) const;)\n\n    // Provides access to functions that aren't part of the public API.\n    inline GrSurfaceProxyPriv priv();\n    inline const GrSurfaceProxyPriv priv() const;\n\n    GrInternalSurfaceFlags testingOnly_getFlags() const;\n\nprotected:\n    // Deferred version\n    GrSurfaceProxy(const GrSurfaceDesc& desc, GrSurfaceOrigin origin, SkBackingFit fit,\n                   SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)\n            : GrSurfaceProxy(nullptr, LazyInstantiationType::kSingleUse, desc, origin, fit,\n                             budgeted, surfaceFlags) {\n        // Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources\n    }\n\n    using LazyInstantiateCallback = std::function<sk_sp<GrSurface>(GrResourceProvider*)>;\n\n    // Lazy-callback version\n    GrSurfaceProxy(LazyInstantiateCallback&&, LazyInstantiationType,\n                   const GrSurfaceDesc&, GrSurfaceOrigin, SkBackingFit,\n                   SkBudgeted, GrInternalSurfaceFlags);\n\n    // Wrapped version\n    GrSurfaceProxy(sk_sp<GrSurface>, GrSurfaceOrigin, SkBackingFit);\n\n    virtual ~GrSurfaceProxy();\n\n    friend class GrSurfaceProxyPriv;\n\n    // Methods made available via GrSurfaceProxyPriv\n    bool hasPendingIO() const {\n        return this->internalHasPendingIO();\n    }\n\n    bool hasPendingWrite() const {\n        return this->internalHasPendingWrite();\n    }\n\n    void computeScratchKey(GrScratchKey*) const;\n\n    virtual sk_sp<GrSurface> createSurface(GrResourceProvider*) const = 0;\n    void assign(sk_sp<GrSurface> surface);\n\n    sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt, bool needsStencil,\n                                       GrSurfaceDescFlags descFlags, GrMipMapped) const;\n\n    bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt, bool needsStencil,\n                         GrSurfaceDescFlags descFlags, GrMipMapped, const GrUniqueKey*);\n\n    // In many cases these flags aren't actually known until the proxy has been instantiated.\n    // However, Ganesh frequently needs to change its behavior based on these settings. For\n    // internally create proxies we will know these properties ahead of time. For wrapped\n    // proxies we will copy the properties off of the GrSurface. For lazy proxies we force the\n    // call sites to provide the required information ahead of time. At instantiation time\n    // we verify that the assumed properties match the actual properties.\n    GrInternalSurfaceFlags fSurfaceFlags;\n\nprivate:\n    // For wrapped resources, 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always be filled in\n    // from the wrapped resource.\n    GrPixelConfig          fConfig;\n    int                    fWidth;\n    int                    fHeight;\n    GrSurfaceOrigin        fOrigin;\n    SkBackingFit           fFit;      // always kApprox for lazy-callback resources\n                                      // always kExact for wrapped resources\n    mutable SkBudgeted     fBudgeted; // always kYes for lazy-callback resources\n                                      // set from the backing resource for wrapped resources\n                                      // mutable bc of SkSurface/SkImage wishy-washiness\n\n    const UniqueID         fUniqueID; // set from the backing resource for wrapped resources\n\n    LazyInstantiateCallback fLazyInstantiateCallback;\n    // If this is set to kSingleuse, then after one call to fLazyInstantiateCallback we will cleanup\n    // the lazy callback and then delete it. This will allow for any refs and resources being held\n    // by the standard function to be released. This is specifically useful in non-dll cases where\n    // we make lazy proxies and instantiate them immediately.\n    // Note: This is ignored if fLazyInstantiateCallback is null.\n    LazyInstantiationType  fLazyInstantiationType;\n\n    SkDEBUGCODE(void validateSurface(const GrSurface*);)\n    SkDEBUGCODE(virtual void onValidateSurface(const GrSurface*) = 0;)\n\n    static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);\n    SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })\n\n    virtual size_t onUninstantiatedGpuMemorySize() const = 0;\n\n    bool                   fNeedsClear;\n\n    // This entry is lazily evaluated so, when the proxy wraps a resource, the resource\n    // will be called but, when the proxy is deferred, it will compute the answer itself.\n    // If the proxy computes its own answer that answer is checked (in debug mode) in\n    // the instantiation method.\n    mutable size_t         fGpuMemorySize;\n\n    // The last opList that wrote to or is currently going to write to this surface\n    // The opList can be closed (e.g., no surface context is currently bound\n    // to this proxy).\n    // This back-pointer is required so that we can add a dependancy between\n    // the opList used to create the current contents of this surface\n    // and the opList of a destination surface to which this one is being drawn or copied.\n    // This pointer is unreffed. OpLists own a ref on their surface proxies.\n    GrOpList*              fLastOpList;\n\n    typedef GrIORefProxy INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrSurfaceProxyRef.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSurfaceProxyRef_DEFINED\n#define GrSurfaceProxyRef_DEFINED\n\n#include \"GrTypesPriv.h\"\n\nclass GrSurfaceProxy;\n\nclass GrSurfaceProxyRef : SkNoncopyable {\npublic:\n    virtual ~GrSurfaceProxyRef();\n\n    GrSurfaceProxy* get() const { return fProxy; }\n\n    /** Does this object own a pending read or write on the resource it is wrapping. */\n    bool ownsPendingIO() const { return fPendingIO; }\n\n    /** What type of IO does this represent? This is independent of whether a normal ref or a\n        pending IO is currently held. */\n    GrIOType ioType() const { return fIOType; }\n\n    /** Shortcut for calling setProxy() with NULL. It cannot be called after markingPendingIO\n        is called. */\n    void reset();\n\nprotected:\n    GrSurfaceProxyRef();\n\n    /** ioType expresses what type of IO operations will be marked as\n        pending on the resource when markPendingIO is called. */\n    GrSurfaceProxyRef(sk_sp<GrSurfaceProxy>, GrIOType);\n\n    /** ioType expresses what type of IO operations will be marked as\n        pending on the resource when markPendingIO is called. */\n    void setProxy(sk_sp<GrSurfaceProxy>, GrIOType);\n\nprivate:\n    /** Called by owning GrProgramElement when the program element is first scheduled for\n        execution. It can only be called once. */\n    void markPendingIO() const;\n\n    /** Called when the program element/draw state is no longer owned by GrOpList-client code.\n        This lets the cache know that the drawing code will no longer schedule additional reads or\n        writes to the resource using the program element or draw state. It can only be called once.\n      */\n    void removeRef() const;\n\n    /** Called to indicate that the previous pending IO is complete. Useful when the owning object\n        still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously\n        pending executions have been complete. Can only be called if removeRef() was not previously\n        called. */\n    void pendingIOComplete() const;\n\n    friend class GrResourceIOProcessor;\n    friend class GrOpList;                 // for setProxy\n\n    GrSurfaceProxy* fProxy;\n    mutable bool    fOwnRef;\n    mutable bool    fPendingIO;\n    GrIOType        fIOType;\n\n    typedef SkNoncopyable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrSwizzle.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrSwizzle_DEFINED\n#define GrSwizzle_DEFINED\n\n#include \"GrColor.h\"\n#include \"SkRandom.h\"\n\n/** Represents a rgba swizzle. It can be converted either into a string or a eight bit int.\n    Currently there is no way to specify an arbitrary swizzle, just some static swizzles and an\n    assignment operator. That could be relaxed. */\nclass GrSwizzle {\nprivate:\n    char fSwiz[5];\n    uint8_t fKey;\n\n    static constexpr int CToI(char c) {\n        return ('r' == c) ? (GrColor_SHIFT_R / 8) :\n               ('g' == c) ? (GrColor_SHIFT_G / 8) :\n               ('b' == c) ? (GrColor_SHIFT_B / 8) :\n               ('a' == c) ? (GrColor_SHIFT_A / 8) : -1;\n    }\n\n    static constexpr char IToC(int idx) {\n        return (8 * idx) == GrColor_SHIFT_R ? 'r' :\n               (8 * idx) == GrColor_SHIFT_G ? 'g' :\n               (8 * idx) == GrColor_SHIFT_B ? 'b' :\n               (8 * idx) == GrColor_SHIFT_A ? 'a' : 'x';\n    }\n\n    constexpr GrSwizzle(const char c[4])\n        : fSwiz{c[0], c[1], c[2], c[3], 0}\n        , fKey((CToI(c[0]) << 0) | (CToI(c[1]) << 2) | (CToI(c[2]) << 4) | (CToI(c[3]) << 6)) {}\n\n    GR_STATIC_ASSERT(sizeof(char[4]) == sizeof(uint32_t));\n    uint32_t* asUIntPtr() { return SkTCast<uint32_t*>(fSwiz); }\n    uint32_t asUInt() const { return *SkTCast<const uint32_t*>(fSwiz); }\n\npublic:\n    GrSwizzle() { *this = RGBA(); }\n\n    GrSwizzle(const GrSwizzle& that) { *this = that; }\n\n    GrSwizzle& operator=(const GrSwizzle& that) {\n        memcpy(this, &that, sizeof(GrSwizzle));\n        return *this;\n    }\n\n    /** Recreates a GrSwizzle from the output of asKey() */\n    void setFromKey(uint8_t key) {\n        fKey = key;\n        for (int i = 0; i < 4; ++i) {\n            fSwiz[i] = IToC(key & 3);\n            key >>= 2;\n        }\n        SkASSERT(fSwiz[4] == 0);\n    }\n\n    bool operator==(const GrSwizzle& that) const { return this->asUInt() == that.asUInt(); }\n\n    bool operator!=(const GrSwizzle& that) const { return !(*this == that); }\n\n    /** Compact representation of the swizzle suitable for a key. */\n    uint8_t asKey() const { return fKey; }\n\n    /** 4 char null terminated string consisting only of chars 'r', 'g', 'b', 'a'. */\n    const char* c_str() const { return fSwiz; }\n\n    /** Applies this swizzle to the input color and returns the swizzled color. */\n    GrColor applyTo(GrColor color) const {\n        int idx;\n        uint32_t key = fKey;\n        // Index of the input color that should be mapped to output r.\n        idx = (key & 3);\n        uint32_t outR = (color >> idx * 8)  & 0xFF;\n        key >>= 2;\n        idx = (key & 3);\n        uint32_t outG = (color >> idx * 8)  & 0xFF;\n        key >>= 2;\n        idx = (key & 3);\n        uint32_t outB = (color >> idx * 8)  & 0xFF;\n        key >>= 2;\n        idx = (key & 3);\n        uint32_t outA = (color >> idx * 8)  & 0xFF;\n        return GrColorPackRGBA(outR, outG, outB, outA);\n    }\n\n    /** Applies this swizzle to the input color and returns the swizzled color. */\n    GrColor4f applyTo(const GrColor4f& color) const {\n        int idx;\n        uint32_t key = fKey;\n        // Index of the input color that should be mapped to output r.\n        idx = (key & 3);\n        float outR = color.fRGBA[idx];\n        key >>= 2;\n        idx = (key & 3);\n        float outG = color.fRGBA[idx];\n        key >>= 2;\n        idx = (key & 3);\n        float outB = color.fRGBA[idx];\n        key >>= 2;\n        idx = (key & 3);\n        float outA = color.fRGBA[idx];\n        return GrColor4f(outR, outG, outB, outA);\n    }\n\n    static GrSwizzle RGBA() { return GrSwizzle(\"rgba\"); }\n    static GrSwizzle AAAA() { return GrSwizzle(\"aaaa\"); }\n    static GrSwizzle RRRR() { return GrSwizzle(\"rrrr\"); }\n    static GrSwizzle RRRA() { return GrSwizzle(\"rrra\"); }\n    static GrSwizzle BGRA() { return GrSwizzle(\"bgra\"); }\n\n    static GrSwizzle CreateRandom(SkRandom* random) {\n        switch (random->nextU() % 4) {\n            case 0:\n                return RGBA();\n            case 1:\n                return BGRA();\n            case 2:\n                return RRRR();\n            case 3:\n                return AAAA();\n            default:\n                SK_ABORT(\"Mod is broken?!?\");\n                return RGBA();\n        }\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrTextureProxy.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrTextureProxy_DEFINED\n#define GrTextureProxy_DEFINED\n\n#include \"GrSamplerState.h\"\n#include \"GrSurfaceProxy.h\"\n\nclass GrCaps;\nclass GrDeferredProxyUploader;\nclass GrProxyProvider;\nclass GrResourceProvider;\nclass GrTextureOpList;\nclass GrTextureProxyPriv;\n\n// This class delays the acquisition of textures until they are actually required\nclass GrTextureProxy : virtual public GrSurfaceProxy {\npublic:\n    GrTextureProxy* asTextureProxy() override { return this; }\n    const GrTextureProxy* asTextureProxy() const override { return this; }\n\n    // Actually instantiate the backing texture, if necessary\n    bool instantiate(GrResourceProvider*) override;\n\n    GrSamplerState::Filter highestFilterMode() const;\n\n    // If we are instantiated and have a target, return the mip state of that target. Otherwise\n    // returns the proxy's mip state from creation time. This is useful for lazy proxies which may\n    // claim to not need mips at creation time, but the instantiation happens to give us a mipped\n    // target. In that case we should use that for our benefit to avoid possible copies/mip\n    // generation later.\n    GrMipMapped mipMapped() const;\n\n    /**\n     * Return the texture proxy's unique key. It will be invalid if the proxy doesn't have one.\n     */\n    const GrUniqueKey& getUniqueKey() const {\n#ifdef SK_DEBUG\n        if (fTarget && fUniqueKey.isValid()) {\n            SkASSERT(fTarget->getUniqueKey().isValid());\n            // It is possible for a non-keyed proxy to have a uniquely keyed resource assigned to\n            // it. This just means that a future user of the resource will be filling it with unique\n            // data. However, if the proxy has a unique key its attached resource should also\n            // have that key.\n            SkASSERT(fUniqueKey == fTarget->getUniqueKey());\n        }\n#endif\n\n        return fUniqueKey;\n    }\n\n    /**\n     * Internal-only helper class used for manipulations of the resource by the cache.\n     */\n    class CacheAccess;\n    inline CacheAccess cacheAccess();\n    inline const CacheAccess cacheAccess() const;\n\n    // Provides access to special purpose functions.\n    GrTextureProxyPriv texPriv();\n    const GrTextureProxyPriv texPriv() const;\n\nprotected:\n    // DDL TODO: rm the GrSurfaceProxy friending\n    friend class GrSurfaceProxy; // for ctors\n    friend class GrProxyProvider; // for ctors\n    friend class GrTextureProxyPriv;\n\n    // Deferred version - when constructed with data the origin is always kTopLeft.\n    GrTextureProxy(const GrSurfaceDesc& srcDesc, GrMipMapped, SkBackingFit, SkBudgeted,\n                   const void* srcData, size_t srcRowBytes, GrInternalSurfaceFlags);\n\n    // Deferred version - no data.\n    GrTextureProxy(const GrSurfaceDesc& srcDesc, GrSurfaceOrigin, GrMipMapped, SkBackingFit,\n                   SkBudgeted, GrInternalSurfaceFlags);\n\n    // Lazy-callback version\n    // There are two main use cases for lazily-instantiated proxies:\n    //   basic knowledge - width, height, config, origin are known\n    //   minimal knowledge - only config is known.\n    //\n    // The basic knowledge version is used for DDL where we know the type of proxy we are going to\n    // use, but we don't have access to the GPU yet to instantiate it.\n    //\n    // The minimal knowledge version is used for CCPR where we are generating an atlas but we do not\n    // know the final size until flush time.\n    GrTextureProxy(LazyInstantiateCallback&&, LazyInstantiationType, const GrSurfaceDesc& desc,\n                   GrSurfaceOrigin, GrMipMapped, SkBackingFit, SkBudgeted,\n                   GrInternalSurfaceFlags);\n\n    // Wrapped version\n    GrTextureProxy(sk_sp<GrSurface>, GrSurfaceOrigin);\n\n    ~GrTextureProxy() override;\n\n    sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;\n\n    void setDoesNotSupportMipMaps() {\n        fSurfaceFlags |= GrInternalSurfaceFlags::kDoesNotSupportMipMaps;\n    }\n    bool doesNotSupportMipMaps() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kDoesNotSupportMipMaps;\n    }\n\n    void setIsGLTextureRectangleOrExternal() {\n        fSurfaceFlags |= GrInternalSurfaceFlags::kIsGLTextureRectangleOrExternal;\n        // If we are a GL rectangle or external texture, it also means that we do not support\n        // generating mip maps.\n        this->setDoesNotSupportMipMaps();\n    }\n    bool isGLTextureRectangleOrExternal() const {\n        return fSurfaceFlags & GrInternalSurfaceFlags::kIsGLTextureRectangleOrExternal;\n    }\n\nprivate:\n    GrMipMapped      fMipMapped;\n\n    GrUniqueKey      fUniqueKey;\n    GrProxyProvider* fProxyProvider; // only set when fUniqueKey is valid\n\n    // Only used for proxies whose contents are being prepared on a worker thread. This object\n    // stores the texture data, allowing the proxy to remain uninstantiated until flush. At that\n    // point, the proxy is instantiated, and this data is used to perform an ASAP upload.\n    std::unique_ptr<GrDeferredProxyUploader> fDeferredUploader;\n\n    size_t onUninstantiatedGpuMemorySize() const override;\n\n    // Methods made available via GrTextureProxy::CacheAccess\n    void setUniqueKey(GrProxyProvider*, const GrUniqueKey&);\n    void clearUniqueKey();\n\n    SkDEBUGCODE(void onValidateSurface(const GrSurface*) override;)\n\n    // For wrapped proxies the GrTexture pointer is stored in GrIORefProxy.\n    // For deferred proxies that pointer will be filled in when we need to instantiate\n    // the deferred resource\n\n    typedef GrSurfaceProxy INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrTypesPriv.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrTypesPriv_DEFINED\n#define GrTypesPriv_DEFINED\n\n#include <chrono>\n#include \"GrSharedEnums.h\"\n#include \"GrTypes.h\"\n#include \"SkImageInfo.h\"\n#include \"SkImageInfoPriv.h\"\n#include \"SkRefCnt.h\"\n#include \"SkWeakRefCnt.h\"\n\nclass GrCaps;\n\n// The old libstdc++ uses the draft name \"monotonic_clock\" rather than \"steady_clock\". This might\n// not actually be monotonic, depending on how libstdc++ was built. However, this is only currently\n// used for idle resource purging so it shouldn't cause a correctness problem.\n#if defined(__GLIBCXX__) && (__GLIBCXX__ < 20130000)\nusing GrStdSteadyClock = std::chrono::monotonic_clock;\n#else\nusing GrStdSteadyClock = std::chrono::steady_clock;\n#endif\n\n/**\n * Pixel configurations. This type conflates texture formats, CPU pixel formats, and\n * premultipliedness. We are moving away from it towards SkColorType and backend API (GL, Vulkan)\n * texture formats in the pulbic API. Right now this mostly refers to texture formats as we're\n * migrating.\n */\nenum GrPixelConfig {\n    kUnknown_GrPixelConfig,\n    kAlpha_8_GrPixelConfig,\n    kGray_8_GrPixelConfig,\n    kRGB_565_GrPixelConfig,\n    kRGBA_4444_GrPixelConfig,\n    kRGBA_8888_GrPixelConfig,\n    kRGB_888_GrPixelConfig,\n    kBGRA_8888_GrPixelConfig,\n    kSRGBA_8888_GrPixelConfig,\n    kSBGRA_8888_GrPixelConfig,\n    kRGBA_1010102_GrPixelConfig,\n    kRGBA_float_GrPixelConfig,\n    kRG_float_GrPixelConfig,\n    kAlpha_half_GrPixelConfig,\n    kRGBA_half_GrPixelConfig,\n\n    /** For internal usage. */\n    kPrivateConfig1_GrPixelConfig,\n    kPrivateConfig2_GrPixelConfig,\n    kPrivateConfig3_GrPixelConfig,\n    kPrivateConfig4_GrPixelConfig,\n    kPrivateConfig5_GrPixelConfig,\n\n    kLast_GrPixelConfig = kPrivateConfig5_GrPixelConfig\n};\nstatic const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;\n\n// Aliases for pixel configs that match skia's byte order.\n#ifndef SK_CPU_LENDIAN\n#error \"Skia gpu currently assumes little endian\"\n#endif\n#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)\nstatic const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;\n#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)\nstatic const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig;\n#else\n    #error \"SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format.\"\n#endif\n\n/**\n * Geometric primitives used for drawing.\n */\nenum class GrPrimitiveType {\n    kTriangles,\n    kTriangleStrip,\n    kPoints,\n    kLines,          // 1 pix wide only\n    kLineStrip,      // 1 pix wide only\n    kLinesAdjacency  // requires geometry shader support.\n};\nstatic constexpr int kNumGrPrimitiveTypes = (int)GrPrimitiveType::kLinesAdjacency + 1;\n\nstatic constexpr bool GrIsPrimTypeLines(GrPrimitiveType type) {\n    return GrPrimitiveType::kLines == type ||\n           GrPrimitiveType::kLineStrip == type ||\n           GrPrimitiveType::kLinesAdjacency == type;\n}\n\nstatic constexpr bool GrIsPrimTypeTris(GrPrimitiveType type) {\n    return GrPrimitiveType::kTriangles == type || GrPrimitiveType::kTriangleStrip == type;\n}\n\nstatic constexpr bool GrPrimTypeRequiresGeometryShaderSupport(GrPrimitiveType type) {\n    return GrPrimitiveType::kLinesAdjacency == type;\n}\n\n/**\n *  Formats for masks, used by the font cache. Important that these are 0-based.\n */\nenum GrMaskFormat {\n    kA8_GrMaskFormat,    //!< 1-byte per pixel\n    kA565_GrMaskFormat,  //!< 2-bytes per pixel, RGB represent 3-channel LCD coverage\n    kARGB_GrMaskFormat,  //!< 4-bytes per pixel, color format\n\n    kLast_GrMaskFormat = kARGB_GrMaskFormat\n};\nstatic const int kMaskFormatCount = kLast_GrMaskFormat + 1;\n\n/**\n *  Return the number of bytes-per-pixel for the specified mask format.\n */\nstatic inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {\n    SkASSERT(format < kMaskFormatCount);\n    // kA8   (0) -> 1\n    // kA565 (1) -> 2\n    // kARGB (2) -> 4\n    static const int sBytesPerPixel[] = {1, 2, 4};\n    static_assert(SK_ARRAY_COUNT(sBytesPerPixel) == kMaskFormatCount, \"array_size_mismatch\");\n    static_assert(kA8_GrMaskFormat == 0, \"enum_order_dependency\");\n    static_assert(kA565_GrMaskFormat == 1, \"enum_order_dependency\");\n    static_assert(kARGB_GrMaskFormat == 2, \"enum_order_dependency\");\n\n    return sBytesPerPixel[(int)format];\n}\n\n/**\n * Optional bitfield flags that can be set on GrSurfaceDesc (below).\n */\nenum GrSurfaceFlags {\n    kNone_GrSurfaceFlags = 0x0,\n    /**\n     * Creates a texture that can be rendered to as a GrRenderTarget. Use\n     * GrTexture::asRenderTarget() to access.\n     */\n    kRenderTarget_GrSurfaceFlag = 0x1,\n    /**\n     * Clears to zero on creation. It will cause creation failure if initial data is supplied to the\n     * texture. This only affects the base level if the texture is created with MIP levels.\n     */\n    kPerformInitialClear_GrSurfaceFlag = 0x2\n};\nGR_MAKE_BITFIELD_OPS(GrSurfaceFlags)\n\ntypedef GrSurfaceFlags GrSurfaceDescFlags;\n\n/**\n * Describes a surface to be created.\n */\nstruct GrSurfaceDesc {\n    GrSurfaceDesc()\n            : fFlags(kNone_GrSurfaceFlags)\n            , fWidth(0)\n            , fHeight(0)\n            , fConfig(kUnknown_GrPixelConfig)\n            , fSampleCnt(1) {}\n\n    GrSurfaceDescFlags     fFlags;  //!< bitfield of TextureFlags\n    int                    fWidth;  //!< Width of the texture\n    int                    fHeight; //!< Height of the texture\n\n    /**\n     * Format of source data of the texture. Not guaranteed to be the same as\n     * internal format used by 3D API.\n     */\n    GrPixelConfig          fConfig;\n\n    /**\n     * The number of samples per pixel. Zero is treated equivalently to 1. This only\n     * applies if the kRenderTarget_GrSurfaceFlag is set. The actual number\n     * of samples may not exactly match the request. The request will be rounded\n     * up to the next supported sample count. A value larger than the largest\n     * supported sample count will fail.\n     */\n    int                    fSampleCnt;\n};\n\n/** Ownership rules for external GPU resources imported into Skia. */\nenum GrWrapOwnership {\n    /** Skia will assume the client will keep the resource alive and Skia will not free it. */\n    kBorrow_GrWrapOwnership,\n\n    /** Skia will assume ownership of the resource and free it. */\n    kAdopt_GrWrapOwnership,\n};\n\n/**\n * Clips are composed from these objects.\n */\nenum GrClipType {\n    kRect_ClipType,\n    kPath_ClipType\n};\n\nstruct GrMipLevel {\n    const void* fPixels;\n    size_t fRowBytes;\n};\n\n/**\n * This enum is used to specify the load operation to be used when an opList/GrGpuCommandBuffer\n * begins execution.\n */\nenum class GrLoadOp {\n    kLoad,\n    kClear,\n    kDiscard,\n};\n\n/**\n * This enum is used to specify the store operation to be used when an opList/GrGpuCommandBuffer\n * ends execution.\n */\nenum class GrStoreOp {\n    kStore,\n    kDiscard,\n};\n\n/**\n * Used to control antialiasing in draw calls.\n */\nenum class GrAA : bool {\n    kNo = false,\n    kYes = true\n};\n\n/** This enum indicates the type of antialiasing to be performed. */\nenum class GrAAType : unsigned {\n    /** No antialiasing */\n    kNone,\n    /** Use fragment shader code to compute a fractional pixel coverage. */\n    kCoverage,\n    /** Use normal MSAA. */\n    kMSAA,\n    /**\n     * Use \"mixed samples\" MSAA such that the stencil buffer is multisampled but the color buffer is\n     * not.\n     */\n    kMixedSamples\n};\n\nstatic inline bool GrAATypeIsHW(GrAAType type) {\n    switch (type) {\n        case GrAAType::kNone:\n            return false;\n        case GrAAType::kCoverage:\n            return false;\n        case GrAAType::kMSAA:\n            return true;\n        case GrAAType::kMixedSamples:\n            return true;\n    }\n    SK_ABORT(\"Unknown AA Type\");\n    return false;\n}\n\n/** The type of full scene antialiasing supported by a render target. */\nenum class GrFSAAType {\n    /** No FSAA */\n    kNone,\n    /** Regular MSAA where each attachment has the same sample count. */\n    kUnifiedMSAA,\n    /** One color sample, N stencil samples. */\n    kMixedSamples,\n};\n\n/**\n * Not all drawing code paths support using mixed samples when available and instead use\n * coverage-based aa.\n */\nenum class GrAllowMixedSamples : bool { kNo = false, kYes = true };\n\nGrAAType GrChooseAAType(GrAA, GrFSAAType, GrAllowMixedSamples, const GrCaps&);\n\n/**\n * Some pixel configs are inherently clamped to [0,1], while others can hold values outside of that\n * range. This is important for blending - the latter category may require manual clamping.\n */\nenum class GrPixelConfigIsClamped : bool {\n    kNo = false,   // F16 or F32\n    kYes = true,  // Any UNORM type\n};\n\n/**\n * Types of shader-language-specific boxed variables we can create. (Currently only GrGLShaderVars,\n * but should be applicable to other shader languages.)\n */\nenum GrSLType {\n    kVoid_GrSLType,\n    kBool_GrSLType,\n    kShort_GrSLType,\n    kShort2_GrSLType,\n    kShort3_GrSLType,\n    kShort4_GrSLType,\n    kUShort_GrSLType,\n    kUShort2_GrSLType,\n    kUShort3_GrSLType,\n    kUShort4_GrSLType,\n    kFloat_GrSLType,\n    kFloat2_GrSLType,\n    kFloat3_GrSLType,\n    kFloat4_GrSLType,\n    kFloat2x2_GrSLType,\n    kFloat3x3_GrSLType,\n    kFloat4x4_GrSLType,\n    kHalf_GrSLType,\n    kHalf2_GrSLType,\n    kHalf3_GrSLType,\n    kHalf4_GrSLType,\n    kHalf2x2_GrSLType,\n    kHalf3x3_GrSLType,\n    kHalf4x4_GrSLType,\n    kInt_GrSLType,\n    kInt2_GrSLType,\n    kInt3_GrSLType,\n    kInt4_GrSLType,\n    kUint_GrSLType,\n    kUint2_GrSLType,\n    kTexture2DSampler_GrSLType,\n    kTextureExternalSampler_GrSLType,\n    kTexture2DRectSampler_GrSLType,\n    kBufferSampler_GrSLType,\n    kTexture2D_GrSLType,\n    kSampler_GrSLType,\n};\n\nenum GrShaderType {\n    kVertex_GrShaderType,\n    kGeometry_GrShaderType,\n    kFragment_GrShaderType,\n\n    kLastkFragment_GrShaderType = kFragment_GrShaderType\n};\nstatic const int kGrShaderTypeCount = kLastkFragment_GrShaderType + 1;\n\nenum GrShaderFlags {\n    kNone_GrShaderFlags = 0,\n    kVertex_GrShaderFlag = 1 << kVertex_GrShaderType,\n    kGeometry_GrShaderFlag = 1 << kGeometry_GrShaderType,\n    kFragment_GrShaderFlag = 1 << kFragment_GrShaderType\n};\nGR_MAKE_BITFIELD_OPS(GrShaderFlags);\n\n/**\n * Precisions of shader language variables. Not all shading languages support precisions or actually\n * vary the internal precision based on the qualifiers. These currently only apply to float types (\n * including float vectors and matrices).\n */\nenum GrSLPrecision {\n    kLow_GrSLPrecision,\n    kMedium_GrSLPrecision,\n    kHigh_GrSLPrecision,\n\n    // Default precision is a special tag that means \"whatever the default for the program/type\n    // combination is\". In other words, it maps to the empty string in shader code. There are some\n    // scenarios where kDefault is not allowed (as the default precision for a program, or for\n    // varyings, for example).\n    kDefault_GrSLPrecision,\n\n    // We only consider the \"real\" precisions here\n    kLast_GrSLPrecision = kHigh_GrSLPrecision,\n};\n\nstatic const int kGrSLPrecisionCount = kLast_GrSLPrecision + 1;\n\n/** Is the shading language type float (including vectors/matrices)? */\nstatic inline bool GrSLTypeIsFloatType(GrSLType type) {\n    switch (type) {\n        case kFloat_GrSLType:\n        case kFloat2_GrSLType:\n        case kFloat3_GrSLType:\n        case kFloat4_GrSLType:\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf_GrSLType:\n        case kHalf2_GrSLType:\n        case kHalf3_GrSLType:\n        case kHalf4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n            return true;\n\n        case kVoid_GrSLType:\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n        case kBufferSampler_GrSLType:\n        case kBool_GrSLType:\n        case kShort_GrSLType:\n        case kShort2_GrSLType:\n        case kShort3_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort_GrSLType:\n        case kUShort2_GrSLType:\n        case kUShort3_GrSLType:\n        case kUShort4_GrSLType:\n        case kInt_GrSLType:\n        case kInt2_GrSLType:\n        case kInt3_GrSLType:\n        case kInt4_GrSLType:\n        case kUint_GrSLType:\n        case kUint2_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return false;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return false;\n}\n\n/** If the type represents a single value or vector return the vector length, else -1. */\nstatic inline int GrSLTypeVecLength(GrSLType type) {\n    switch (type) {\n        case kFloat_GrSLType:\n        case kHalf_GrSLType:\n        case kBool_GrSLType:\n        case kShort_GrSLType:\n        case kUShort_GrSLType:\n        case kInt_GrSLType:\n        case kUint_GrSLType:\n            return 1;\n\n        case kFloat2_GrSLType:\n        case kHalf2_GrSLType:\n        case kShort2_GrSLType:\n        case kUShort2_GrSLType:\n        case kInt2_GrSLType:\n        case kUint2_GrSLType:\n            return 2;\n\n        case kFloat3_GrSLType:\n        case kHalf3_GrSLType:\n        case kShort3_GrSLType:\n        case kUShort3_GrSLType:\n        case kInt3_GrSLType:\n            return 3;\n\n        case kFloat4_GrSLType:\n        case kHalf4_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort4_GrSLType:\n        case kInt4_GrSLType:\n            return 4;\n\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n        case kVoid_GrSLType:\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n        case kBufferSampler_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return -1;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return -1;\n}\n\nstatic inline bool GrSLTypeIs2DCombinedSamplerType(GrSLType type) {\n    switch (type) {\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n            return true;\n\n        case kVoid_GrSLType:\n        case kFloat_GrSLType:\n        case kFloat2_GrSLType:\n        case kFloat3_GrSLType:\n        case kFloat4_GrSLType:\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf_GrSLType:\n        case kHalf2_GrSLType:\n        case kHalf3_GrSLType:\n        case kHalf4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n        case kInt_GrSLType:\n        case kInt2_GrSLType:\n        case kInt3_GrSLType:\n        case kInt4_GrSLType:\n        case kUint_GrSLType:\n        case kUint2_GrSLType:\n        case kBufferSampler_GrSLType:\n        case kBool_GrSLType:\n        case kShort_GrSLType:\n        case kShort2_GrSLType:\n        case kShort3_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort_GrSLType:\n        case kUShort2_GrSLType:\n        case kUShort3_GrSLType:\n        case kUShort4_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return false;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return false;\n}\n\nstatic inline bool GrSLTypeIsCombinedSamplerType(GrSLType type) {\n    switch (type) {\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n        case kBufferSampler_GrSLType:\n            return true;\n\n        case kVoid_GrSLType:\n        case kFloat_GrSLType:\n        case kFloat2_GrSLType:\n        case kFloat3_GrSLType:\n        case kFloat4_GrSLType:\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf_GrSLType:\n        case kHalf2_GrSLType:\n        case kHalf3_GrSLType:\n        case kHalf4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n        case kInt_GrSLType:\n        case kInt2_GrSLType:\n        case kInt3_GrSLType:\n        case kInt4_GrSLType:\n        case kUint_GrSLType:\n        case kUint2_GrSLType:\n        case kBool_GrSLType:\n        case kShort_GrSLType:\n        case kShort2_GrSLType:\n        case kShort3_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort_GrSLType:\n        case kUShort2_GrSLType:\n        case kUShort3_GrSLType:\n        case kUShort4_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return false;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return false;\n}\n\nstatic inline bool GrSLTypeAcceptsPrecision(GrSLType type) {\n    switch (type) {\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n        case kBufferSampler_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return true;\n\n        case kVoid_GrSLType:\n        case kBool_GrSLType:\n        case kShort_GrSLType:\n        case kShort2_GrSLType:\n        case kShort3_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort_GrSLType:\n        case kUShort2_GrSLType:\n        case kUShort3_GrSLType:\n        case kUShort4_GrSLType:\n        case kFloat_GrSLType:\n        case kFloat2_GrSLType:\n        case kFloat3_GrSLType:\n        case kFloat4_GrSLType:\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf_GrSLType:\n        case kHalf2_GrSLType:\n        case kHalf3_GrSLType:\n        case kHalf4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n        case kInt_GrSLType:\n        case kInt2_GrSLType:\n        case kInt3_GrSLType:\n        case kInt4_GrSLType:\n        case kUint_GrSLType:\n        case kUint2_GrSLType:\n            return false;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return false;\n}\n\n// temporarily accepting (but ignoring) precision modifiers on the new types; this will be killed\n// in a future CL\nstatic inline bool GrSLTypeTemporarilyAcceptsPrecision(GrSLType type) {\n    switch (type) {\n        case kShort_GrSLType:\n        case kUShort_GrSLType:\n        case kFloat_GrSLType:\n        case kFloat2_GrSLType:\n        case kFloat3_GrSLType:\n        case kFloat4_GrSLType:\n        case kFloat2x2_GrSLType:\n        case kFloat3x3_GrSLType:\n        case kFloat4x4_GrSLType:\n        case kHalf_GrSLType:\n        case kHalf2_GrSLType:\n        case kHalf3_GrSLType:\n        case kHalf4_GrSLType:\n        case kHalf2x2_GrSLType:\n        case kHalf3x3_GrSLType:\n        case kHalf4x4_GrSLType:\n        case kInt_GrSLType:\n        case kInt2_GrSLType:\n        case kInt3_GrSLType:\n        case kInt4_GrSLType:\n        case kUint_GrSLType:\n        case kUint2_GrSLType:\n        case kTexture2DSampler_GrSLType:\n        case kTextureExternalSampler_GrSLType:\n        case kTexture2DRectSampler_GrSLType:\n        case kBufferSampler_GrSLType:\n        case kTexture2D_GrSLType:\n        case kSampler_GrSLType:\n            return true;\n\n        case kVoid_GrSLType:\n        case kBool_GrSLType:\n        case kShort2_GrSLType:\n        case kShort3_GrSLType:\n        case kShort4_GrSLType:\n        case kUShort2_GrSLType:\n        case kUShort3_GrSLType:\n        case kUShort4_GrSLType:\n            return false;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return false;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\n/**\n * Types used to describe format of vertices in arrays.\n */\nenum GrVertexAttribType {\n    kFloat_GrVertexAttribType = 0,\n    kFloat2_GrVertexAttribType,\n    kFloat3_GrVertexAttribType,\n    kFloat4_GrVertexAttribType,\n    kHalf_GrVertexAttribType,\n    kHalf2_GrVertexAttribType,\n    kHalf3_GrVertexAttribType,\n    kHalf4_GrVertexAttribType,\n\n    kInt2_GrVertexAttribType,   // vector of 2 32-bit ints\n    kInt3_GrVertexAttribType,   // vector of 3 32-bit ints\n    kInt4_GrVertexAttribType,   // vector of 4 32-bit ints\n\n    kUByte_norm_GrVertexAttribType,  // unsigned byte, e.g. coverage, 0 -> 0.0f, 255 -> 1.0f.\n    kUByte4_norm_GrVertexAttribType, // vector of 4 unsigned bytes, e.g. colors, 0 -> 0.0f,\n                                     // 255 -> 1.0f.\n\n    kShort2_GrVertexAttribType,       // vector of 2 16-bit shorts.\n    kUShort2_GrVertexAttribType,      // vector of 2 unsigned shorts. 0 -> 0, 65535 -> 65535.\n    kUShort2_norm_GrVertexAttribType, // vector of 2 unsigned shorts. 0 -> 0.0f, 65535 -> 1.0f.\n\n    kInt_GrVertexAttribType,\n    kUint_GrVertexAttribType,\n\n    kLast_GrVertexAttribType = kUint_GrVertexAttribType\n};\nstatic const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;\n\n/**\n * Returns the size of the attrib type in bytes.\n */\nstatic inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {\n    switch (type) {\n        case kFloat_GrVertexAttribType:\n            return sizeof(float);\n        case kFloat2_GrVertexAttribType:\n            return 2 * sizeof(float);\n        case kFloat3_GrVertexAttribType:\n            return 3 * sizeof(float);\n        case kFloat4_GrVertexAttribType:\n            return 4 * sizeof(float);\n        case kHalf_GrVertexAttribType:\n            return sizeof(float);\n        case kHalf2_GrVertexAttribType:\n            return 2 * sizeof(float);\n        case kHalf3_GrVertexAttribType:\n            return 3 * sizeof(float);\n        case kHalf4_GrVertexAttribType:\n            return 4 * sizeof(float);\n        case kInt2_GrVertexAttribType:\n            return 2 * sizeof(int32_t);\n        case kInt3_GrVertexAttribType:\n            return 3 * sizeof(int32_t);\n        case kInt4_GrVertexAttribType:\n            return 4 * sizeof(int32_t);\n        case kUByte_norm_GrVertexAttribType:\n            return 1 * sizeof(char);\n        case kUByte4_norm_GrVertexAttribType:\n            return 4 * sizeof(char);\n        case kShort2_GrVertexAttribType:\n            return 2 * sizeof(int16_t);\n        case kUShort2_GrVertexAttribType: // fall through\n        case kUShort2_norm_GrVertexAttribType:\n            return 2 * sizeof(uint16_t);\n        case kInt_GrVertexAttribType:\n            return sizeof(int32_t);\n        case kUint_GrVertexAttribType:\n            return sizeof(uint32_t);\n    }\n    SK_ABORT(\"Unexpected attribute type\");\n    return 0;\n}\n\n/**\n * converts a GrVertexAttribType to a GrSLType\n */\nstatic inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) {\n    switch (type) {\n        case kShort2_GrVertexAttribType:\n            return kShort2_GrSLType;\n        case kUShort2_GrVertexAttribType:\n            return kUShort2_GrSLType;\n        case kUShort2_norm_GrVertexAttribType:\n            return kFloat2_GrSLType;\n        case kUByte_norm_GrVertexAttribType:   // fall through\n        case kFloat_GrVertexAttribType:\n            return kFloat_GrSLType;\n        case kFloat2_GrVertexAttribType:\n            return kFloat2_GrSLType;\n        case kFloat3_GrVertexAttribType:\n            return kFloat3_GrSLType;\n        case kFloat4_GrVertexAttribType:\n            return kFloat4_GrSLType;\n        case kHalf_GrVertexAttribType:\n            return kHalf_GrSLType;\n        case kHalf2_GrVertexAttribType:\n            return kHalf2_GrSLType;\n        case kHalf3_GrVertexAttribType:\n            return kHalf3_GrSLType;\n        case kHalf4_GrVertexAttribType:\n        case kUByte4_norm_GrVertexAttribType:\n            return kHalf4_GrSLType;\n        case kInt2_GrVertexAttribType:\n            return kInt2_GrSLType;\n        case kInt3_GrVertexAttribType:\n            return kInt3_GrSLType;\n        case kInt4_GrVertexAttribType:\n            return kInt4_GrSLType;\n        case kInt_GrVertexAttribType:\n            return kInt_GrSLType;\n        case kUint_GrVertexAttribType:\n            return kUint_GrSLType;\n    }\n    SK_ABORT(\"Unsupported type conversion\");\n    return kVoid_GrSLType;\n}\n\n//////////////////////////////////////////////////////////////////////////////\n\nstatic const int kGrClipEdgeTypeCnt = (int) GrClipEdgeType::kLast + 1;\n\nstatic inline bool GrProcessorEdgeTypeIsFill(const GrClipEdgeType edgeType) {\n    return (GrClipEdgeType::kFillAA == edgeType || GrClipEdgeType::kFillBW == edgeType);\n}\n\nstatic inline bool GrProcessorEdgeTypeIsInverseFill(const GrClipEdgeType edgeType) {\n    return (GrClipEdgeType::kInverseFillAA == edgeType ||\n            GrClipEdgeType::kInverseFillBW == edgeType);\n}\n\nstatic inline bool GrProcessorEdgeTypeIsAA(const GrClipEdgeType edgeType) {\n    return (GrClipEdgeType::kFillBW != edgeType &&\n            GrClipEdgeType::kInverseFillBW != edgeType);\n}\n\nstatic inline GrClipEdgeType GrInvertProcessorEdgeType(const GrClipEdgeType edgeType) {\n    switch (edgeType) {\n        case GrClipEdgeType::kFillBW:\n            return GrClipEdgeType::kInverseFillBW;\n        case GrClipEdgeType::kFillAA:\n            return GrClipEdgeType::kInverseFillAA;\n        case GrClipEdgeType::kInverseFillBW:\n            return GrClipEdgeType::kFillBW;\n        case GrClipEdgeType::kInverseFillAA:\n            return GrClipEdgeType::kFillAA;\n        case GrClipEdgeType::kHairlineAA:\n            SK_ABORT(\"Hairline fill isn't invertible.\");\n    }\n    return GrClipEdgeType::kFillAA;  // suppress warning.\n}\n\n/**\n * Indicates the type of pending IO operations that can be recorded for gpu resources.\n */\nenum GrIOType {\n    kRead_GrIOType,\n    kWrite_GrIOType,\n    kRW_GrIOType\n};\n\n/**\n * Indicates the type of data that a GPU buffer will be used for.\n */\nenum GrBufferType {\n    kVertex_GrBufferType,\n    kIndex_GrBufferType,\n    kTexel_GrBufferType,\n    kDrawIndirect_GrBufferType,\n    kXferCpuToGpu_GrBufferType,\n    kXferGpuToCpu_GrBufferType,\n\n    kLast_GrBufferType = kXferGpuToCpu_GrBufferType\n};\nstatic const int kGrBufferTypeCount = kLast_GrBufferType + 1;\n\nstatic inline bool GrBufferTypeIsVertexOrIndex(GrBufferType type) {\n    SkASSERT(type >= 0 && type < kGrBufferTypeCount);\n    return type <= kIndex_GrBufferType;\n\n    GR_STATIC_ASSERT(0 == kVertex_GrBufferType);\n    GR_STATIC_ASSERT(1 == kIndex_GrBufferType);\n}\n\n/**\n * Provides a performance hint regarding the frequency at which a data store will be accessed.\n */\nenum GrAccessPattern {\n    /** Data store will be respecified repeatedly and used many times. */\n    kDynamic_GrAccessPattern,\n    /** Data store will be specified once and used many times. (Thus disqualified from caching.) */\n    kStatic_GrAccessPattern,\n    /** Data store will be specified once and used at most a few times. (Also can't be cached.) */\n    kStream_GrAccessPattern,\n\n    kLast_GrAccessPattern = kStream_GrAccessPattern\n};\n\n// Flags shared between the GrSurface & GrSurfaceProxy class hierarchies\nenum class GrInternalSurfaceFlags {\n    kNone                           = 0,\n\n    // Surface-level\n    kNoPendingIO                    = 1 << 0,\n\n    kSurfaceMask                    = kNoPendingIO,\n\n    // Texture-only flags\n\n    // This flag is set when the internal texture target doesn't support mipmaps (e.g.,\n    // external and rectangle textures). Note that Ganesh does not internally\n    // create resources with this limitation - this flag will only appear on resources passed\n    // into Ganesh.\n    kDoesNotSupportMipMaps          = 1 << 1,\n\n    // This flag is for GL only. It says that the GL texture we will use has a target which is\n    // either GL_TEXTURE_RECTANGLE or GL_GL_TEXTURE_EXTERNAL. We use this information to make\n    // decisions about various rendering capabilites (e.g. is clamp the only supported wrap mode).\n    // Note: Ganesh does not internally create these types of textures so they will only occur on\n    // resources passed into Ganesh.\n    kIsGLTextureRectangleOrExternal = 1 << 2,\n\n    kTextureMask                    = kDoesNotSupportMipMaps | kIsGLTextureRectangleOrExternal,\n\n    // RT-only\n\n    // For internal resources:\n    //    this is enabled whenever MSAA is enabled and GrCaps reports mixed samples are supported\n    // For wrapped resources:\n    //    this is disabled for FBO0\n    //    but, otherwise, is enabled whenever MSAA is enabled and GrCaps reports mixed samples\n    //        are supported\n    kMixedSampled                   = 1 << 3,\n\n    // For internal resources:\n    //    this is enabled whenever GrCaps reports window rect support\n    // For wrapped resources1\n    //    this is disabled for FBO0\n    //    but, otherwise, is enabled whenever GrCaps reports window rect support\n    kWindowRectsSupport             = 1 << 4,\n\n    // This flag is for use with GL only. It tells us that the internal render target wraps FBO 0.\n    kGLRTFBOIDIs0                   = 1 << 5,\n\n    kRenderTargetMask               = kMixedSampled | kWindowRectsSupport | kGLRTFBOIDIs0,\n};\nGR_MAKE_BITFIELD_CLASS_OPS(GrInternalSurfaceFlags)\n\n#ifdef SK_DEBUG\n// Takes a pointer to a GrCaps, and will suppress prints if required\n#define GrCapsDebugf(caps, ...)      \\\n    if (!(caps)->suppressPrints()) { \\\n        SkDebugf(__VA_ARGS__);       \\\n    }\n#else\n#define GrCapsDebugf(caps, ...)\n#endif\n\n/**\n * Specifies if the holder owns the backend, OpenGL or Vulkan, object.\n */\nenum class GrBackendObjectOwnership : bool {\n    /** Holder does not destroy the backend object. */\n    kBorrowed = false,\n    /** Holder destroys the backend object. */\n    kOwned = true\n};\n\ntemplate <typename T>\nT* const* unique_ptr_address_as_pointer_address(std::unique_ptr<T> const* up) {\n    static_assert(sizeof(T*) == sizeof(std::unique_ptr<T>), \"unique_ptr not expected size.\");\n    return reinterpret_cast<T* const*>(up);\n}\n\n/*\n * Object for CPU-GPU synchronization\n */\ntypedef uint64_t GrFence;\n\n/**\n * Used to include or exclude specific GPU path renderers for testing purposes.\n */\nenum class GpuPathRenderers {\n    kNone              = 0, // Always use sofware masks and/or GrDefaultPathRenderer.\n    kDashLine          = 1 << 0,\n    kStencilAndCover   = 1 << 1,\n    kAAConvex          = 1 << 2,\n    kAALinearizing     = 1 << 3,\n    kSmall             = 1 << 4,\n    kCoverageCounting  = 1 << 5,\n    kTessellating      = 1 << 6,\n\n    kAll               = (kTessellating | (kTessellating - 1)),\n    kDefault           = kAll\n};\n\n/**\n * Used to describe the current state of Mips on a GrTexture\n */\nenum class  GrMipMapsStatus {\n    kNotAllocated, // Mips have not been allocated\n    kDirty,        // Mips are allocated but the full mip tree does not have valid data\n    kValid,        // All levels fully allocated and have valid data in them\n};\n\nGR_MAKE_BITFIELD_CLASS_OPS(GpuPathRenderers)\n\n/**\n * We want to extend the GrPixelConfig enum to add cases for dealing with alpha_8 which is\n * internally either alpha8 or red8. Also for Gray_8 which can be luminance_8 or red_8.\n */\nstatic constexpr GrPixelConfig kAlpha_8_as_Alpha_GrPixelConfig = kPrivateConfig1_GrPixelConfig;\nstatic constexpr GrPixelConfig kAlpha_8_as_Red_GrPixelConfig = kPrivateConfig2_GrPixelConfig;\nstatic constexpr GrPixelConfig kAlpha_half_as_Red_GrPixelConfig = kPrivateConfig3_GrPixelConfig;\nstatic constexpr GrPixelConfig kGray_8_as_Lum_GrPixelConfig = kPrivateConfig4_GrPixelConfig;\nstatic constexpr GrPixelConfig kGray_8_as_Red_GrPixelConfig = kPrivateConfig5_GrPixelConfig;\n\n/**\n * Refers to the encoding of a GPU buffer as it will be interpreted by the GPU when sampling and\n * blending.\n */\nenum class GrSRGBEncoded : bool { kNo = false, kYes = true };\n\n/**\n * Describes whether pixel data encoding should be converted to/from linear/sRGB encoding.\n */\nenum class GrSRGBConversion {\n    kNone,\n    kSRGBToLinear,\n    kLinearToSRGB,\n};\n\n/**\n * Utility functions for GrPixelConfig\n */\n\n// Returns whether the config's color channels are sRGB encoded.\nstatic inline GrSRGBEncoded GrPixelConfigIsSRGBEncoded(GrPixelConfig config) {\n    switch (config) {\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n            return GrSRGBEncoded::kYes;\n        case kUnknown_GrPixelConfig:\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n            return GrSRGBEncoded::kNo;\n    }\n    SK_ABORT(\"Invalid pixel config\");\n    return GrSRGBEncoded::kNo;\n}\n\nstatic inline bool GrPixelConfigIsSRGB(GrPixelConfig config) {\n    return GrSRGBEncoded::kYes == GrPixelConfigIsSRGBEncoded(config);\n}\n// Takes a config and returns the equivalent config with the R and B order\n// swapped if such a config exists. Otherwise, kUnknown_GrPixelConfig\nstatic inline GrPixelConfig GrPixelConfigSwapRAndB(GrPixelConfig config) {\n    switch (config) {\n        case kBGRA_8888_GrPixelConfig:\n            return kRGBA_8888_GrPixelConfig;\n        case kRGBA_8888_GrPixelConfig:\n            return kBGRA_8888_GrPixelConfig;\n        case kSBGRA_8888_GrPixelConfig:\n            return kSRGBA_8888_GrPixelConfig;\n        case kSRGBA_8888_GrPixelConfig:\n            return kSBGRA_8888_GrPixelConfig;\n        case kUnknown_GrPixelConfig:\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n            return kUnknown_GrPixelConfig;\n    }\n    SK_ABORT(\"Invalid pixel config\");\n    return kUnknown_GrPixelConfig;\n}\n\nstatic inline size_t GrBytesPerPixel(GrPixelConfig config) {\n    switch (config) {\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n            return 1;\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n            return 2;\n        case kRGBA_8888_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:  // Assuming GPUs store this 4-byte aligned.\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n            return 4;\n        case kRGBA_half_GrPixelConfig:\n            return 8;\n        case kRGBA_float_GrPixelConfig:\n            return 16;\n        case kRG_float_GrPixelConfig:\n            return 8;\n        case kUnknown_GrPixelConfig:\n            return 0;\n    }\n    SK_ABORT(\"Invalid pixel config\");\n    return 0;\n}\n\nstatic inline bool GrPixelConfigIsOpaque(GrPixelConfig config) {\n    switch (config) {\n        case kRGB_565_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n            return true;\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n        case kRGBA_float_GrPixelConfig:\n        case kUnknown_GrPixelConfig:\n            return false;\n    }\n    SK_ABORT(\"Invalid pixel config\");\n    return false;\n}\n\nstatic inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {\n    switch (config) {\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n            return true;\n        case kUnknown_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n            return false;\n    }\n    SK_ABORT(\"Invalid pixel config.\");\n    return false;\n}\n\nstatic inline bool GrPixelConfigIsFloatingPoint(GrPixelConfig config) {\n    switch (config) {\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n            return true;\n        case kUnknown_GrPixelConfig:\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n            return false;\n    }\n    SK_ABORT(\"Invalid pixel config\");\n    return false;\n}\n\nstatic inline bool GrPixelConfigIsUnorm(GrPixelConfig config) {\n    switch (config) {\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n            return true;\n        case kUnknown_GrPixelConfig:\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n            return false;\n    }\n    SK_ABORT(\"Invalid pixel config.\");\n    return false;\n}\n\n/**\n * Precision qualifier that should be used with a sampler.\n */\nstatic inline GrSLPrecision GrSLSamplerPrecision(GrPixelConfig config) {\n    switch (config) {\n        case kUnknown_GrPixelConfig:\n        case kAlpha_8_GrPixelConfig:\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n        case kAlpha_8_as_Red_GrPixelConfig:\n        case kGray_8_GrPixelConfig:\n        case kGray_8_as_Lum_GrPixelConfig:\n        case kGray_8_as_Red_GrPixelConfig:\n        case kRGB_565_GrPixelConfig:\n        case kRGBA_4444_GrPixelConfig:\n        case kRGBA_8888_GrPixelConfig:\n        case kRGB_888_GrPixelConfig:\n        case kBGRA_8888_GrPixelConfig:\n        case kSRGBA_8888_GrPixelConfig:\n        case kSBGRA_8888_GrPixelConfig:\n            return kLow_GrSLPrecision;\n        case kRGBA_float_GrPixelConfig:\n        case kRG_float_GrPixelConfig:\n            return kHigh_GrSLPrecision;\n        case kAlpha_half_GrPixelConfig:\n        case kAlpha_half_as_Red_GrPixelConfig:\n        case kRGBA_half_GrPixelConfig:\n        case kRGBA_1010102_GrPixelConfig:\n            return kMedium_GrSLPrecision;\n    }\n    SK_ABORT(\"Unexpected type\");\n    return kHigh_GrSLPrecision;\n}\n\nstatic inline GrPixelConfigIsClamped GrGetPixelConfigIsClamped(GrPixelConfig config) {\n    return GrPixelConfigIsFloatingPoint(config) ? GrPixelConfigIsClamped::kNo\n                                                : GrPixelConfigIsClamped::kYes;\n}\n\n/**\n * Like SkColorType this describes a layout of pixel data in CPU memory. It specifies the channels,\n * their type, and width. This exists so that the GPU backend can have private types that have no\n * analog in the public facing SkColorType enum and omit types not implemented in the GPU backend.\n * It does not refer to a texture format and the mapping to texture formats may be many-to-many.\n * It does not specify the sRGB encding of the stored values.\n */\nenum class GrColorType {\n    kUnknown,\n    kAlpha_8,\n    kRGB_565,\n    kABGR_4444,  // This name differs from SkColorType. kARGB_4444_SkColorType is misnamed.\n    kRGBA_8888,\n    kRGB_888x,\n    kBGRA_8888,\n    kRGBA_1010102,\n    kGray_8,\n    kAlpha_F16,\n    kRGBA_F16,\n    kRG_F32,\n    kRGBA_F32,\n};\n\nstatic inline SkColorType GrColorTypeToSkColorType(GrColorType ct) {\n    switch (ct) {\n        case GrColorType::kUnknown:      return kUnknown_SkColorType;\n        case GrColorType::kAlpha_8:      return kAlpha_8_SkColorType;\n        case GrColorType::kRGB_565:      return kRGB_565_SkColorType;\n        case GrColorType::kABGR_4444:    return kARGB_4444_SkColorType;\n        case GrColorType::kRGBA_8888:    return kRGBA_8888_SkColorType;\n        case GrColorType::kRGB_888x:     return kRGB_888x_SkColorType;\n        case GrColorType::kBGRA_8888:    return kBGRA_8888_SkColorType;\n        case GrColorType::kRGBA_1010102: return kRGBA_1010102_SkColorType;\n        case GrColorType::kGray_8:       return kGray_8_SkColorType;\n        case GrColorType::kAlpha_F16:    return kUnknown_SkColorType;\n        case GrColorType::kRGBA_F16:     return kRGBA_F16_SkColorType;\n        case GrColorType::kRG_F32:       return kUnknown_SkColorType;\n        case GrColorType::kRGBA_F32:     return kUnknown_SkColorType;\n    }\n    SK_ABORT(\"Invalid GrColorType\");\n    return kUnknown_SkColorType;\n}\n\nstatic inline GrColorType SkColorTypeToGrColorType(SkColorType ct) {\n    switch (ct) {\n        case kUnknown_SkColorType:      return GrColorType::kUnknown;\n        case kAlpha_8_SkColorType:      return GrColorType::kAlpha_8;\n        case kRGB_565_SkColorType:      return GrColorType::kRGB_565;\n        case kARGB_4444_SkColorType:    return GrColorType::kABGR_4444;\n        case kRGBA_8888_SkColorType:    return GrColorType::kRGBA_8888;\n        case kRGB_888x_SkColorType:     return GrColorType::kRGB_888x;\n        case kBGRA_8888_SkColorType:    return GrColorType::kBGRA_8888;\n        case kGray_8_SkColorType:       return GrColorType::kGray_8;\n        case kRGBA_F16_SkColorType:     return GrColorType::kRGBA_F16;\n        case kRGBA_1010102_SkColorType: return GrColorType::kRGBA_1010102;\n        case kRGB_101010x_SkColorType:  return GrColorType::kUnknown;\n    }\n    SK_ABORT(\"Invalid SkColorType\");\n    return GrColorType::kUnknown;\n}\n\nstatic inline uint32_t GrColorTypeComponentFlags(GrColorType ct) {\n    switch (ct) {\n        case GrColorType::kUnknown:      return 0;\n        case GrColorType::kAlpha_8:      return kAlpha_SkColorTypeComponentFlag;\n        case GrColorType::kRGB_565:      return kRGB_SkColorTypeComponentFlags;\n        case GrColorType::kABGR_4444:    return kRGBA_SkColorTypeComponentFlags;\n        case GrColorType::kRGBA_8888:    return kRGBA_SkColorTypeComponentFlags;\n        case GrColorType::kRGB_888x:     return kRGB_SkColorTypeComponentFlags;\n        case GrColorType::kBGRA_8888:    return kRGBA_SkColorTypeComponentFlags;\n        case GrColorType::kRGBA_1010102: return kRGBA_SkColorTypeComponentFlags;\n        case GrColorType::kGray_8:       return kGray_SkColorTypeComponentFlag;\n        case GrColorType::kAlpha_F16:    return kAlpha_SkColorTypeComponentFlag;\n        case GrColorType::kRGBA_F16:     return kRGBA_SkColorTypeComponentFlags;\n        case GrColorType::kRG_F32:       return kRed_SkColorTypeComponentFlag |\n                                                kGreen_SkColorTypeComponentFlag;\n        case GrColorType::kRGBA_F32:     return kRGBA_SkColorTypeComponentFlags;\n    }\n    SK_ABORT(\"Invalid GrColorType\");\n    return kUnknown_SkColorType;\n}\n\nstatic inline bool GrColorTypeIsAlphaOnly(GrColorType ct) {\n    return kAlpha_SkColorTypeComponentFlag == GrColorTypeComponentFlags(ct);\n}\n\nstatic inline bool GrColorTypeHasAlpha(GrColorType ct) {\n    return kAlpha_SkColorTypeComponentFlag & GrColorTypeComponentFlags(ct);\n}\n\nstatic inline int GrColorTypeBytesPerPixel(GrColorType ct) {\n    switch (ct) {\n        case GrColorType::kUnknown:      return 0;\n        case GrColorType::kAlpha_8:      return 1;\n        case GrColorType::kRGB_565:      return 2;\n        case GrColorType::kABGR_4444:    return 2;\n        case GrColorType::kRGBA_8888:    return 4;\n        case GrColorType::kRGB_888x:     return 4;\n        case GrColorType::kBGRA_8888:    return 4;\n        case GrColorType::kRGBA_1010102: return 4;\n        case GrColorType::kGray_8:       return 1;\n        case GrColorType::kAlpha_F16:    return 2;\n        case GrColorType::kRGBA_F16:     return 8;\n        case GrColorType::kRG_F32:       return 8;\n        case GrColorType::kRGBA_F32:     return 16;\n    }\n    SK_ABORT(\"Invalid GrColorType\");\n    return 0;\n}\n\nstatic inline GrColorType GrPixelConfigToColorTypeAndEncoding(GrPixelConfig config,\n                                                              GrSRGBEncoded* srgbEncoded) {\n    SkASSERT(srgbEncoded);\n    switch (config) {\n        case kUnknown_GrPixelConfig:\n            return GrColorType::kUnknown;\n        case kAlpha_8_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kAlpha_8;\n        case kGray_8_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kGray_8;\n        case kRGB_565_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGB_565;\n        case kRGBA_4444_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kABGR_4444;\n        case kRGBA_8888_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGBA_8888;\n        case kRGB_888_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGB_888x;\n        case kBGRA_8888_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kBGRA_8888;\n        case kSRGBA_8888_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kYes;\n            return GrColorType::kRGBA_8888;\n        case kSBGRA_8888_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kYes;\n            return GrColorType::kBGRA_8888;\n        case kRGBA_1010102_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGBA_1010102;\n        case kRGBA_float_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGBA_F32;\n        case kRG_float_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRG_F32;\n        case kAlpha_half_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kAlpha_F16;\n        case kRGBA_half_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kRGBA_F16;\n        case kAlpha_8_as_Alpha_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kAlpha_8;\n        case kAlpha_8_as_Red_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kAlpha_8;\n        case kAlpha_half_as_Red_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kAlpha_F16;\n        case kGray_8_as_Lum_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kGray_8;\n        case kGray_8_as_Red_GrPixelConfig:\n            *srgbEncoded = GrSRGBEncoded::kNo;\n            return GrColorType::kGray_8;\n    }\n    SK_ABORT(\"Invalid GrPixelConfig\");\n    return GrColorType::kUnknown;\n}\n\nstatic inline GrColorType GrPixelConfigToColorType(GrPixelConfig config) {\n    GrSRGBEncoded bogusEncoded;\n    return GrPixelConfigToColorTypeAndEncoding(config, &bogusEncoded);\n}\n\nstatic inline GrPixelConfig GrColorTypeToPixelConfig(GrColorType config,\n                                                     GrSRGBEncoded srgbEncoded) {\n    switch (config) {\n        case GrColorType::kUnknown:\n            return kUnknown_GrPixelConfig;\n        case GrColorType::kAlpha_8:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kAlpha_8_GrPixelConfig;\n\n        case GrColorType::kGray_8:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kGray_8_GrPixelConfig;\n\n        case GrColorType::kRGB_565:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGB_565_GrPixelConfig;\n\n        case GrColorType::kABGR_4444:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGBA_4444_GrPixelConfig;\n\n        case GrColorType::kRGBA_8888:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kSRGBA_8888_GrPixelConfig\n                                                        : kRGBA_8888_GrPixelConfig;\n\n        case GrColorType::kRGB_888x:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGB_888_GrPixelConfig;\n\n        case GrColorType::kBGRA_8888:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kSBGRA_8888_GrPixelConfig\n                                                        : kBGRA_8888_GrPixelConfig;\n\n        case GrColorType::kRGBA_1010102:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGBA_1010102_GrPixelConfig;\n\n        case GrColorType::kRGBA_F32:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGBA_float_GrPixelConfig;\n\n        case GrColorType::kRG_F32:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRG_float_GrPixelConfig;\n\n        case GrColorType::kAlpha_F16:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kAlpha_half_GrPixelConfig;\n\n        case GrColorType::kRGBA_F16:\n            return (GrSRGBEncoded::kYes == srgbEncoded) ? kUnknown_GrPixelConfig\n                                                        : kRGBA_half_GrPixelConfig;\n    }\n    SK_ABORT(\"Invalid GrColorType\");\n    return kUnknown_GrPixelConfig;\n}\n\nclass GrReleaseProcHelper : public SkWeakRefCnt {\npublic:\n    // These match the definitions in SkImage, from whence they came\n    typedef void* ReleaseCtx;\n    typedef void (*ReleaseProc)(ReleaseCtx);\n\n    GrReleaseProcHelper(ReleaseProc proc, ReleaseCtx ctx) : fReleaseProc(proc), fReleaseCtx(ctx) {}\n    ~GrReleaseProcHelper() override {}\n\n    void weak_dispose() const override {\n        fReleaseProc(fReleaseCtx);\n    }\n\nprivate:\n    ReleaseProc fReleaseProc;\n    ReleaseCtx  fReleaseCtx;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/GrVkTypesPriv.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef GrVkTypesPriv_DEFINED\n#define GrVkTypesPriv_DEFINED\n\n#include \"vk/GrVkTypes.h\"\n#include \"SkRefCnt.h\"\n\nclass GrVkImageLayout;\n\n// This struct is to used to store the the actual information about the vulkan backend image on the\n// GrBackendTexture and GrBackendRenderTarget. When a client calls getVkImageInfo on a\n// GrBackendTexture/RenderTarget, we use the GrVkBackendSurfaceInfo to create a snapshot\n// GrVkImgeInfo object. Internally, this uses a ref count GrVkImageLayout object to track the\n// current VkImageLayout which can be shared with an internal GrVkImage so that layout updates can\n// be seen by all users of the image.\nstruct GrVkBackendSurfaceInfo {\n    GrVkBackendSurfaceInfo(GrVkImageInfo info, GrVkImageLayout* layout)\n            : fImageInfo(info), fLayout(layout) {}\n\n    void cleanup();\n\n    GrVkBackendSurfaceInfo& operator=(const GrVkBackendSurfaceInfo&) = delete;\n\n    // Assigns the passed in GrVkBackendSurfaceInfo to this object. if isValid is true we will also\n    // attempt to unref the old fLayout on this object.\n    void assign(const GrVkBackendSurfaceInfo&, bool isValid);\n\n    void setImageLayout(VkImageLayout layout);\n\n    sk_sp<GrVkImageLayout> getGrVkImageLayout() const;\n\n    GrVkImageInfo snapImageInfo() const;\n\n#if GR_TEST_UTILS\n    bool operator==(const GrVkBackendSurfaceInfo& that) const;\n#endif\n\nprivate:\n    GrVkImageInfo    fImageInfo;\n    GrVkImageLayout* fLayout;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkArenaAlloc.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkArenaAlloc_DEFINED\n#define SkArenaAlloc_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkTFitsIn.h\"\n#include \"SkTypes.h\"\n#include <cstddef>\n#include <new>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n// SkArenaAlloc allocates object and destroys the allocated objects when destroyed. It's designed\n// to minimize the number of underlying block allocations. SkArenaAlloc allocates first out of an\n// (optional) user-provided block of memory, and when that's exhausted it allocates on the heap,\n// starting with an allocation of extraSize bytes.  If your data (plus a small overhead) fits in\n// the user-provided block, SkArenaAlloc never uses the heap, and if it fits in extraSize bytes,\n// it'll use the heap only once.  If you pass extraSize = 0, it allocates blocks for each call to\n// make<T>.\n//\n// Examples:\n//\n//   char block[mostCasesSize];\n//   SkArenaAlloc arena(block, almostAllCasesSize);\n//\n// If mostCasesSize is too large for the stack, you can use the following pattern.\n//\n//   std::unique_ptr<char[]> block{new char[mostCasesSize]};\n//   SkArenaAlloc arena(block.get(), mostCasesSize, almostAllCasesSize);\n//\n// If the program only sometimes allocates memory, use the following.\n//\n//   SkArenaAlloc arena(nullptr, 0, almostAllCasesSize);\n//\n// The storage does not necessarily need to be on the stack. Embedding the storage in a class also\n// works.\n//\n//   class Foo {\n//       char storage[mostCasesSize];\n//       SkArenaAlloc arena (storage, almostAllCasesSize);\n//   };\n//\n// In addition, the system is optimized to handle POD data including arrays of PODs (where\n// POD is really data with no destructors). For POD data it has zero overhead per item, and a\n// typical block overhead of 8 bytes. For non-POD objects there is a per item overhead of 4 bytes.\n// For arrays of non-POD objects there is a per array overhead of typically 8 bytes. There is an\n// addition overhead when switching from POD data to non-POD data of typically 8 bytes.\n//\n// You can track memory use by adding SkArenaAlloc::kTrack as the last parameter to any constructor.\n//\n//   char storage[someNumber];\n//   SkArenaAlloc alloc{storage, SkArenaAlloc::kTrack};\n//\n// This will print out a line for every destructor or reset call that has the total memory\n// allocated, the total slop (the unused portion of a block), and the slop of the last block.\n//\n// If additional blocks are needed they are increased exponentially. This strategy bounds the\n// recursion of the RunDtorsOnBlock to be limited to O(log size-of-memory). Block size grow using\n// the Fibonacci sequence which means that for 2^32 memory there are 48 allocations, and for 2^48\n// there are 71 allocations.\nclass SkArenaAlloc {\npublic:\n    enum Tracking {kDontTrack, kTrack};\n    SkArenaAlloc(char* block, size_t size, size_t, Tracking tracking = kDontTrack);\n\n    SkArenaAlloc(size_t extraSize, Tracking tracking = kDontTrack)\n        : SkArenaAlloc(nullptr, 0, extraSize, tracking)\n    {}\n\n    ~SkArenaAlloc();\n\n    template <typename T, typename... Args>\n    T* make(Args&&... args) {\n        uint32_t size      = SkTo<uint32_t>(sizeof(T));\n        uint32_t alignment = SkTo<uint32_t>(alignof(T));\n        char* objStart;\n        if (skstd::is_trivially_destructible<T>::value) {\n            objStart = this->allocObject(size, alignment);\n            fCursor = objStart + size;\n        } else {\n            objStart = this->allocObjectWithFooter(size + sizeof(Footer), alignment);\n            // Can never be UB because max value is alignof(T).\n            uint32_t padding = SkTo<uint32_t>(objStart - fCursor);\n\n            // Advance to end of object to install footer.\n            fCursor = objStart + size;\n            FooterAction* releaser = [](char* objEnd) {\n                char* objStart = objEnd - (sizeof(T) + sizeof(Footer));\n                ((T*)objStart)->~T();\n                return objStart;\n            };\n            this->installFooter(releaser, padding);\n        }\n\n        // This must be last to make objects with nested use of this allocator work.\n        return new(objStart) T(std::forward<Args>(args)...);\n    }\n\n    template <typename T, typename... Args>\n    sk_sp<T> makeSkSp(Args&&... args) {\n        SkASSERT(SkTFitsIn<uint32_t>(sizeof(T)));\n\n        // The arena takes a ref for itself to account for the destructor. The sk_sp count can't\n        // become zero or the sk_sp will try to call free on the pointer.\n        return sk_sp<T>(SkRef(this->make<T>(std::forward<Args>(args)...)));\n    }\n\n    template <typename T>\n    T* makeArrayDefault(size_t count) {\n        uint32_t safeCount = SkTo<uint32_t>(count);\n        T* array = (T*)this->commonArrayAlloc<T>(safeCount);\n\n        // If T is primitive then no initialization takes place.\n        for (size_t i = 0; i < safeCount; i++) {\n            new (&array[i]) T;\n        }\n        return array;\n    }\n\n    template <typename T>\n    T* makeArray(size_t count) {\n        uint32_t safeCount = SkTo<uint32_t>(count);\n        T* array = (T*)this->commonArrayAlloc<T>(safeCount);\n\n        // If T is primitive then the memory is initialized. For example, an array of chars will\n        // be zeroed.\n        for (size_t i = 0; i < safeCount; i++) {\n            new (&array[i]) T();\n        }\n        return array;\n    }\n\n    // Only use makeBytesAlignedTo if none of the typed variants are impractical to use.\n    void* makeBytesAlignedTo(size_t size, size_t align) {\n        auto objStart = this->allocObject(SkTo<uint32_t>(size), SkTo<uint32_t>(align));\n        fCursor = objStart + size;\n        return objStart;\n    }\n\n    // Destroy all allocated objects, free any heap allocations.\n    void reset();\n\nprivate:\n    using Footer = int64_t;\n    using FooterAction = char* (char*);\n\n    static char* SkipPod(char* footerEnd);\n    static void RunDtorsOnBlock(char* footerEnd);\n    static char* NextBlock(char* footerEnd);\n\n    void installFooter(FooterAction* releaser, uint32_t padding);\n    void installUint32Footer(FooterAction* action, uint32_t value, uint32_t padding);\n    void installPtrFooter(FooterAction* action, char* ptr, uint32_t padding);\n\n    void ensureSpace(uint32_t size, uint32_t alignment);\n\n    char* allocObject(uint32_t size, uint32_t alignment) {\n        uintptr_t mask = alignment - 1;\n        uintptr_t alignedOffset = (~reinterpret_cast<uintptr_t>(fCursor) + 1) & mask;\n        uintptr_t totalSize = size + alignedOffset;\n        if (totalSize < size) {\n            SK_ABORT(\"The total size of allocation overflowed uintptr_t.\");\n        }\n        if (totalSize > static_cast<uintptr_t>(fEnd - fCursor)) {\n            this->ensureSpace(size, alignment);\n            alignedOffset = (~reinterpret_cast<uintptr_t>(fCursor) + 1) & mask;\n        }\n        return fCursor + alignedOffset;\n    }\n\n    char* allocObjectWithFooter(uint32_t sizeIncludingFooter, uint32_t alignment);\n\n    template <typename T>\n    char* commonArrayAlloc(uint32_t count) {\n        char* objStart;\n        SkASSERT_RELEASE(count <= std::numeric_limits<uint32_t>::max() / sizeof(T));\n        uint32_t arraySize = SkTo<uint32_t>(count * sizeof(T));\n        uint32_t alignment = SkTo<uint32_t>(alignof(T));\n\n        if (skstd::is_trivially_destructible<T>::value) {\n            objStart = this->allocObject(arraySize, alignment);\n            fCursor = objStart + arraySize;\n        } else {\n            constexpr uint32_t overhead = sizeof(Footer) + sizeof(uint32_t);\n            SkASSERT_RELEASE(arraySize <= std::numeric_limits<uint32_t>::max() - overhead);\n            uint32_t totalSize = arraySize + overhead;\n            objStart = this->allocObjectWithFooter(totalSize, alignment);\n\n            // Can never be UB because max value is alignof(T).\n            uint32_t padding = SkTo<uint32_t>(objStart - fCursor);\n\n            // Advance to end of array to install footer.?\n            fCursor = objStart + arraySize;\n            this->installUint32Footer(\n                [](char* footerEnd) {\n                    char* objEnd = footerEnd - (sizeof(Footer) + sizeof(uint32_t));\n                    uint32_t count;\n                    memmove(&count, objEnd, sizeof(uint32_t));\n                    char* objStart = objEnd - count * sizeof(T);\n                    T* array = (T*) objStart;\n                    for (uint32_t i = 0; i < count; i++) {\n                        array[i].~T();\n                    }\n                    return objStart;\n                },\n                SkTo<uint32_t>(count),\n                padding);\n        }\n\n        return objStart;\n    }\n\n    char*          fDtorCursor;\n    char*          fCursor;\n    char*          fEnd;\n    char* const    fFirstBlock;\n    const uint32_t fFirstSize;\n    const uint32_t fExtraSize;\n\n    // Track some useful stats. Track stats if fTotalSlop is >= 0;\n    uint32_t       fTotalAlloc { 0};\n    int32_t        fTotalSlop  {-1};\n\n    // Use the Fibonacci sequence as the growth factor for block size. The size of the block\n    // allocated is fFib0 * fExtraSize. Using 2 ^ n * fExtraSize had too much slop for Android.\n    uint32_t       fFib0 {1}, fFib1 {1};\n};\n\n// Helper for defining allocators with inline/reserved storage.\n// For argument declarations, stick to the base type (SkArenaAlloc).\ntemplate <size_t InlineStorageSize>\nclass SkSTArenaAlloc : public SkArenaAlloc {\npublic:\n    explicit SkSTArenaAlloc(size_t extraSize = InlineStorageSize, Tracking tracking = kDontTrack)\n        : INHERITED(fInlineStorage, InlineStorageSize, extraSize, tracking) {}\n\nprivate:\n    char fInlineStorage[InlineStorageSize];\n\n    using INHERITED = SkArenaAlloc;\n};\n\n#endif  // SkArenaAlloc_DEFINED\n"
  },
  {
    "path": "include/private/SkAtomics.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkAtomics_DEFINED\n#define SkAtomics_DEFINED\n\n// This file is not part of the public Skia API.\n#include \"SkTypes.h\"\n#include <atomic>\n\n// ~~~~~~~~ APIs ~~~~~~~~~\n\nenum sk_memory_order {\n    sk_memory_order_relaxed,\n    sk_memory_order_consume,\n    sk_memory_order_acquire,\n    sk_memory_order_release,\n    sk_memory_order_acq_rel,\n    sk_memory_order_seq_cst,\n};\n\ntemplate <typename T>\nT sk_atomic_load(const T*, sk_memory_order = sk_memory_order_seq_cst);\n\ntemplate <typename T>\nvoid sk_atomic_store(T*, T, sk_memory_order = sk_memory_order_seq_cst);\n\ntemplate <typename T>\nT sk_atomic_fetch_add(T*, T, sk_memory_order = sk_memory_order_seq_cst);\n\ntemplate <typename T>\nT sk_atomic_fetch_sub(T*, T, sk_memory_order = sk_memory_order_seq_cst);\n\ntemplate <typename T>\nbool sk_atomic_compare_exchange(T*, T* expected, T desired,\n                                sk_memory_order success = sk_memory_order_seq_cst,\n                                sk_memory_order failure = sk_memory_order_seq_cst);\n\ntemplate <typename T>\nT sk_atomic_exchange(T*, T, sk_memory_order = sk_memory_order_seq_cst);\n\n// A little wrapper class for small T (think, builtins: int, float, void*) to\n// ensure they're always used atomically.  This is our stand-in for std::atomic<T>.\n// !!! Please _really_ know what you're doing if you change default_memory_order. !!!\ntemplate <typename T, sk_memory_order default_memory_order = sk_memory_order_seq_cst>\nclass SkAtomic : SkNoncopyable {\npublic:\n    SkAtomic() {}\n    explicit SkAtomic(const T& val) : fVal(val) {}\n\n    // It is essential we return by value rather than by const&.  fVal may change at any time.\n    T load(sk_memory_order mo = default_memory_order) const {\n        return sk_atomic_load(&fVal, mo);\n    }\n\n    void store(const T& val, sk_memory_order mo = default_memory_order) {\n        sk_atomic_store(&fVal, val, mo);\n    }\n\n    // Alias for .load(default_memory_order).\n    operator T() const {\n        return this->load();\n    }\n\n    // Alias for .store(v, default_memory_order).\n    T operator=(const T& v) {\n        this->store(v);\n        return v;\n    }\n\n    T fetch_add(const T& val, sk_memory_order mo = default_memory_order) {\n        return sk_atomic_fetch_add(&fVal, val, mo);\n    }\n\n    T fetch_sub(const T& val, sk_memory_order mo = default_memory_order) {\n        return sk_atomic_fetch_sub(&fVal, val, mo);\n    }\n\n    bool compare_exchange(T* expected, const T& desired,\n                          sk_memory_order success = default_memory_order,\n                          sk_memory_order failure = default_memory_order) {\n        return sk_atomic_compare_exchange(&fVal, expected, desired, success, failure);\n    }\nprivate:\n    T fVal;\n};\n\n// ~~~~~~~~ Implementations ~~~~~~~~~\n\ntemplate <typename T>\nT sk_atomic_load(const T* ptr, sk_memory_order mo) {\n    SkASSERT(mo == sk_memory_order_relaxed ||\n             mo == sk_memory_order_seq_cst ||\n             mo == sk_memory_order_acquire ||\n             mo == sk_memory_order_consume);\n    const std::atomic<T>* ap = reinterpret_cast<const std::atomic<T>*>(ptr);\n    return std::atomic_load_explicit(ap, (std::memory_order)mo);\n}\n\ntemplate <typename T>\nvoid sk_atomic_store(T* ptr, T val, sk_memory_order mo) {\n    SkASSERT(mo == sk_memory_order_relaxed ||\n             mo == sk_memory_order_seq_cst ||\n             mo == sk_memory_order_release);\n    std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);\n    return std::atomic_store_explicit(ap, val, (std::memory_order)mo);\n}\n\ntemplate <typename T>\nT sk_atomic_fetch_add(T* ptr, T val, sk_memory_order mo) {\n    // All values of mo are valid.\n    std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);\n    return std::atomic_fetch_add_explicit(ap, val, (std::memory_order)mo);\n}\n\ntemplate <typename T>\nT sk_atomic_fetch_sub(T* ptr, T val, sk_memory_order mo) {\n    // All values of mo are valid.\n    std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);\n    return std::atomic_fetch_sub_explicit(ap, val, (std::memory_order)mo);\n}\n\ntemplate <typename T>\nbool sk_atomic_compare_exchange(T* ptr, T* expected, T desired,\n                                sk_memory_order success,\n                                sk_memory_order failure) {\n    // All values of success are valid.\n    SkASSERT(failure == sk_memory_order_relaxed ||\n             failure == sk_memory_order_seq_cst ||\n             failure == sk_memory_order_acquire ||\n             failure == sk_memory_order_consume);\n    SkASSERT(failure <= success);\n    std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);\n    return std::atomic_compare_exchange_strong_explicit(ap, expected, desired,\n                                                        (std::memory_order)success,\n                                                        (std::memory_order)failure);\n}\n\ntemplate <typename T>\nT sk_atomic_exchange(T* ptr, T val, sk_memory_order mo) {\n    // All values of mo are valid.\n    std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);\n    return std::atomic_exchange_explicit(ap, val, (std::memory_order)mo);\n}\n\n// ~~~~~~~~ Legacy APIs ~~~~~~~~~\n\n// From here down we have shims for our old atomics API, to be weaned off of.\n// We use the default sequentially-consistent memory order to make things simple\n// and to match the practical reality of our old _sync and _win implementations.\n\ninline int32_t sk_atomic_inc(int32_t* ptr) { return sk_atomic_fetch_add(ptr, +1); }\ninline int32_t sk_atomic_dec(int32_t* ptr) { return sk_atomic_fetch_add(ptr, -1); }\n\n#endif//SkAtomics_DEFINED\n"
  },
  {
    "path": "include/private/SkBitmaskEnum.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkEnumOperators_DEFINED\n#define SkEnumOperators_DEFINED\n\n#include \"SkTLogic.h\"\n\nnamespace skstd {\ntemplate <typename T> struct is_bitmask_enum : std::false_type {};\n}\n\ntemplate <typename E> SK_WHEN(skstd::is_bitmask_enum<E>::value, E) operator|(E l, E r) {\n    using U = skstd::underlying_type_t<E>;\n    return static_cast<E>(static_cast<U>(l) | static_cast<U>(r));\n}\n\ntemplate <typename E> SK_WHEN(skstd::is_bitmask_enum<E>::value, E&) operator|=(E& l, E r) {\n    return l = l | r;\n}\n\ntemplate <typename E> SK_WHEN(skstd::is_bitmask_enum<E>::value, E) operator&(E l, E r) {\n    using U = skstd::underlying_type_t<E>;\n    return static_cast<E>(static_cast<U>(l) & static_cast<U>(r));\n}\n\ntemplate <typename E> SK_WHEN(skstd::is_bitmask_enum<E>::value, E&) operator&=(E& l, E r) {\n    return l = l & r;\n}\n\n#endif  // SkEnumOperators_DEFINED\n"
  },
  {
    "path": "include/private/SkChecksum.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkChecksum_DEFINED\n#define SkChecksum_DEFINED\n\n#include \"SkString.h\"\n#include \"SkTLogic.h\"\n#include \"SkTypes.h\"\n\n// #include \"SkOpts.h\"\n// It's sort of pesky to be able to include SkOpts.h here, so we'll just re-declare what we need.\nnamespace SkOpts {\n    extern uint32_t (*hash_fn)(const void*, size_t, uint32_t);\n}\n\nclass SkChecksum : SkNoncopyable {\npublic:\n    /**\n     * uint32_t -> uint32_t hash, useful for when you're about to trucate this hash but you\n     * suspect its low bits aren't well mixed.\n     *\n     * This is the Murmur3 finalizer.\n     */\n    static uint32_t Mix(uint32_t hash) {\n        hash ^= hash >> 16;\n        hash *= 0x85ebca6b;\n        hash ^= hash >> 13;\n        hash *= 0xc2b2ae35;\n        hash ^= hash >> 16;\n        return hash;\n    }\n\n    /**\n     * uint32_t -> uint32_t hash, useful for when you're about to trucate this hash but you\n     * suspect its low bits aren't well mixed.\n     *\n     *  This version is 2-lines cheaper than Mix, but seems to be sufficient for the font cache.\n     */\n    static uint32_t CheapMix(uint32_t hash) {\n        hash ^= hash >> 16;\n        hash *= 0x85ebca6b;\n        hash ^= hash >> 16;\n        return hash;\n    }\n};\n\n// SkGoodHash should usually be your first choice in hashing data.\n// It should be both reasonably fast and high quality.\nstruct SkGoodHash {\n    template <typename K>\n    SK_WHEN(sizeof(K) == 4, uint32_t) operator()(const K& k) const {\n        return SkChecksum::Mix(*(const uint32_t*)&k);\n    }\n\n    template <typename K>\n    SK_WHEN(sizeof(K) != 4, uint32_t) operator()(const K& k) const {\n        return SkOpts::hash_fn(&k, sizeof(K), 0);\n    }\n\n    uint32_t operator()(const SkString& k) const {\n        return SkOpts::hash_fn(k.c_str(), k.size(), 0);\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkDeferredDisplayList.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkDeferredDisplayList_DEFINED\n#define SkDeferredDisplayList_DEFINED\n\n#include \"SkSurfaceCharacterization.h\"\n\n#if SK_SUPPORT_GPU\n#include <map>\n#include \"GrCCPerOpListPaths.h\"\n#include \"GrOpList.h\"\n#endif\n\nclass SkSurface;\n\n/*\n * This class contains pre-processed gpu operations that can be replayed into\n * an SkSurface via draw(SkDeferredDisplayList*).\n *\n * TODO: we probably need to expose this class so users can query it for memory usage.\n */\nclass SK_API SkDeferredDisplayList {\npublic:\n\n#if SK_SUPPORT_GPU\n    // This object is the source from which the lazy proxy backing the DDL will pull its backing\n    // texture when the DDL is replayed. It has to be separately ref counted bc the lazy proxy\n    // can outlive the DDL.\n    class LazyProxyData : public SkRefCnt {\n    public:\n        // Upon being replayed - this field will be filled in (by the DrawingManager) with the proxy\n        // backing the destination SkSurface. Note that, since there is no good place to clear it\n        // it can become a dangling pointer.\n        GrRenderTargetProxy*     fReplayDest = nullptr;\n    };\n#else\n    class LazyProxyData : public SkRefCnt {};\n#endif\n\n    SkDeferredDisplayList(const SkSurfaceCharacterization& characterization,\n                          sk_sp<LazyProxyData>);\n    ~SkDeferredDisplayList();\n\n    const SkSurfaceCharacterization& characterization() const {\n        return fCharacterization;\n    }\n\nprivate:\n    friend class GrDrawingManager; // for access to 'fOpLists' and 'fLazyProxyData'\n    friend class SkDeferredDisplayListRecorder; // for access to 'fLazyProxyData'\n\n    const SkSurfaceCharacterization fCharacterization;\n\n#if SK_SUPPORT_GPU\n    // This needs to match the same type in GrCoverageCountingPathRenderer.h\n    using PendingPathsMap = std::map<uint32_t, sk_sp<GrCCPerOpListPaths>>;\n\n    SkTArray<sk_sp<GrOpList>>    fOpLists;\n    PendingPathsMap              fPendingPaths;  // This is the path data from CCPR.\n#endif\n    sk_sp<LazyProxyData>         fLazyProxyData;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkEncodedInfo.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEncodedInfo_DEFINED\n#define SkEncodedInfo_DEFINED\n\n#include \"SkImageInfo.h\"\n\nclass SkColorSpace;\n\nstruct SkEncodedInfo {\npublic:\n\n    enum Alpha {\n        kOpaque_Alpha,\n        kUnpremul_Alpha,\n\n        // Each pixel is either fully opaque or fully transparent.\n        // There is no difference between requesting kPremul or kUnpremul.\n        kBinary_Alpha,\n    };\n\n    /*\n     * We strive to make the number of components per pixel obvious through\n     * our naming conventions.\n     * Ex: kRGB has 3 components.  kRGBA has 4 components.\n     *\n     * This sometimes results in redundant Alpha and Color information.\n     * Ex: kRGB images must also be kOpaque.\n     */\n    enum Color {\n        // PNG, WBMP\n        kGray_Color,\n\n        // PNG\n        kGrayAlpha_Color,\n\n        // PNG, GIF, BMP\n        kPalette_Color,\n\n        // PNG, RAW\n        kRGB_Color,\n        kRGBA_Color,\n\n        // BMP\n        kBGR_Color,\n        kBGRX_Color,\n        kBGRA_Color,\n\n        // JPEG, WEBP\n        kYUV_Color,\n\n        // WEBP\n        kYUVA_Color,\n\n        // JPEG\n        // Photoshop actually writes inverted CMYK data into JPEGs, where zero\n        // represents 100% ink coverage.  For this reason, we treat CMYK JPEGs\n        // as having inverted CMYK.  libjpeg-turbo warns that this may break\n        // other applications, but the CMYK JPEGs we see on the web expect to\n        // be treated as inverted CMYK.\n        kInvertedCMYK_Color,\n        kYCCK_Color,\n    };\n\n    static SkEncodedInfo Make(Color color, Alpha alpha, int bitsPerComponent) {\n        SkASSERT(1 == bitsPerComponent ||\n                 2 == bitsPerComponent ||\n                 4 == bitsPerComponent ||\n                 8 == bitsPerComponent ||\n                 16 == bitsPerComponent);\n\n        switch (color) {\n            case kGray_Color:\n                SkASSERT(kOpaque_Alpha == alpha);\n                break;\n            case kGrayAlpha_Color:\n                SkASSERT(kOpaque_Alpha != alpha);\n                break;\n            case kPalette_Color:\n                SkASSERT(16 != bitsPerComponent);\n                break;\n            case kRGB_Color:\n            case kBGR_Color:\n            case kBGRX_Color:\n                SkASSERT(kOpaque_Alpha == alpha);\n                SkASSERT(bitsPerComponent >= 8);\n                break;\n            case kYUV_Color:\n            case kInvertedCMYK_Color:\n            case kYCCK_Color:\n                SkASSERT(kOpaque_Alpha == alpha);\n                SkASSERT(8 == bitsPerComponent);\n                break;\n            case kRGBA_Color:\n                SkASSERT(kOpaque_Alpha != alpha);\n                SkASSERT(bitsPerComponent >= 8);\n                break;\n            case kBGRA_Color:\n            case kYUVA_Color:\n                SkASSERT(kOpaque_Alpha != alpha);\n                SkASSERT(8 == bitsPerComponent);\n                break;\n            default:\n                SkASSERT(false);\n                break;\n        }\n\n        return SkEncodedInfo(color, alpha, bitsPerComponent);\n    }\n\n    /*\n     * Returns an SkImageInfo with Skia color and alpha types that are the\n     * closest possible match to the encoded info.\n     */\n    SkImageInfo makeImageInfo(int width, int height, sk_sp<SkColorSpace> colorSpace) const {\n        auto ct = kGray_Color == fColor ? kGray_8_SkColorType   :\n                                          kN32_SkColorType      ;\n        auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType\n                                             : kUnpremul_SkAlphaType;\n        return SkImageInfo::Make(width, height, ct, alpha, std::move(colorSpace));\n    }\n\n    Color color() const { return fColor; }\n    Alpha alpha() const { return fAlpha; }\n    bool opaque() const { return fAlpha == kOpaque_Alpha; }\n\n    uint8_t bitsPerComponent() const { return fBitsPerComponent; }\n\n    uint8_t bitsPerPixel() const {\n        switch (fColor) {\n            case kGray_Color:\n                return fBitsPerComponent;\n            case kGrayAlpha_Color:\n                return 2 * fBitsPerComponent;\n            case kPalette_Color:\n                return fBitsPerComponent;\n            case kRGB_Color:\n            case kBGR_Color:\n            case kYUV_Color:\n                return 3 * fBitsPerComponent;\n            case kRGBA_Color:\n            case kBGRA_Color:\n            case kBGRX_Color:\n            case kYUVA_Color:\n            case kInvertedCMYK_Color:\n            case kYCCK_Color:\n                return 4 * fBitsPerComponent;\n            default:\n                SkASSERT(false);\n                return 0;\n        }\n    }\n\nprivate:\n\n    SkEncodedInfo(Color color, Alpha alpha, uint8_t bitsPerComponent)\n        : fColor(color)\n        , fAlpha(alpha)\n        , fBitsPerComponent(bitsPerComponent)\n    {}\n\n    Color   fColor;\n    Alpha   fAlpha;\n    uint8_t fBitsPerComponent;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkFixed.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFixed_DEFINED\n#define SkFixed_DEFINED\n\n#include \"SkScalar.h\"\n#include \"SkSafe_math.h\"\n\n#include \"SkTypes.h\"\n\n/** \\file SkFixed.h\n\n    Types and macros for 16.16 fixed point\n*/\n\n/** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point\n*/\ntypedef int32_t             SkFixed;\n#define SK_Fixed1           (1 << 16)\n#define SK_FixedHalf        (1 << 15)\n#define SK_FixedMax         (0x7FFFFFFF)\n#define SK_FixedMin         (-SK_FixedMax)\n#define SK_FixedPI          (0x3243F)\n#define SK_FixedSqrt2       (92682)\n#define SK_FixedTanPIOver8  (0x6A0A)\n#define SK_FixedRoot2Over2  (0xB505)\n\n// NOTE: SkFixedToFloat is exact. SkFloatToFixed seems to lack a rounding step. For all fixed-point\n// values, this version is as accurate as possible for (fixed -> float -> fixed). Rounding reduces\n// accuracy if the intermediate floats are in the range that only holds integers (adding 0.5f to an\n// odd integer then snaps to nearest even). Using double for the rounding math gives maximum\n// accuracy for (float -> fixed -> float), but that's usually overkill.\n#define SkFixedToFloat(x)   ((x) * 1.52587890625e-5f)\n#define SkFloatToFixed(x)   sk_float_saturate2int((x) * SK_Fixed1)\n\n#ifdef SK_DEBUG\n    static inline SkFixed SkFloatToFixed_Check(float x) {\n        int64_t n64 = (int64_t)(x * SK_Fixed1);\n        SkFixed n32 = (SkFixed)n64;\n        SkASSERT(n64 == n32);\n        return n32;\n    }\n#else\n    #define SkFloatToFixed_Check(x) SkFloatToFixed(x)\n#endif\n\n#define SkFixedToDouble(x)  ((x) * 1.52587890625e-5)\n#define SkDoubleToFixed(x)  ((SkFixed)((x) * SK_Fixed1))\n\n/** Converts an integer to a SkFixed, asserting that the result does not overflow\n    a 32 bit signed integer\n*/\n#ifdef SK_DEBUG\n    inline SkFixed SkIntToFixed(int n)\n    {\n        SkASSERT(n >= -32768 && n <= 32767);\n        // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before\n        // shifting.\n        return (unsigned)n << 16;\n    }\n#else\n    // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before\n    // shifting. Then we force the cast to SkFixed to ensure that the answer is signed (like the\n    // debug version).\n    #define SkIntToFixed(n)     (SkFixed)((unsigned)(n) << 16)\n#endif\n\n#define SkFixedRoundToInt(x)    (((x) + SK_FixedHalf) >> 16)\n#define SkFixedCeilToInt(x)     (((x) + SK_Fixed1 - 1) >> 16)\n#define SkFixedFloorToInt(x)    ((x) >> 16)\n\nstatic inline SkFixed SkFixedRoundToFixed(SkFixed x) {\n    return (x + SK_FixedHalf) & 0xFFFF0000;\n}\nstatic inline SkFixed SkFixedCeilToFixed(SkFixed x) {\n    return (x + SK_Fixed1 - 1) & 0xFFFF0000;\n}\nstatic inline SkFixed SkFixedFloorToFixed(SkFixed x) {\n    return x & 0xFFFF0000;\n}\n\n#define SkFixedAbs(x)       SkAbs32(x)\n#define SkFixedAve(a, b)    (((a) + (b)) >> 1)\n\n// The divide may exceed 32 bits. Clamp to a signed 32 bit result.\n#define SkFixedDiv(numer, denom) \\\n    SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)(numer), 16) / (denom)), SK_MinS32, SK_MaxS32))\n\nstatic inline SkFixed SkFixedMul(SkFixed a, SkFixed b) {\n    return (SkFixed)((int64_t)a * b >> 16);\n}\n\n///////////////////////////////////////////////////////////////////////////////\n// Platform-specific alternatives to our portable versions.\n\n// The VCVT float-to-fixed instruction is part of the VFPv3 instruction set.\n#if defined(__ARM_VFPV3__)\n    /* This guy does not handle NaN or other obscurities, but is faster than\n       than (int)(x*65536).  When built on Android with -Os, needs forcing\n       to inline or we lose the speed benefit.\n    */\n    SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x)\n    {\n        int32_t y;\n        asm(\"vcvt.s32.f32 %0, %0, #16\": \"+w\"(x));\n        memcpy(&y, &x, sizeof(y));\n        return y;\n    }\n    #undef SkFloatToFixed\n    #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)\n#endif\n\n///////////////////////////////////////////////////////////////////////////////\n\n#define SkFixedToScalar(x)          SkFixedToFloat(x)\n#define SkScalarToFixed(x)          SkFloatToFixed(x)\n\n///////////////////////////////////////////////////////////////////////////////\n\ntypedef int64_t SkFixed3232;   // 32.32\n\n#define SkFixed3232Max            SK_MaxS64\n#define SkFixed3232Min            (-SkFixed3232Max)\n\n#define SkIntToFixed3232(x)       (SkLeftShift((SkFixed3232)(x), 32))\n#define SkFixed3232ToInt(x)       ((int)((x) >> 32))\n#define SkFixedToFixed3232(x)     (SkLeftShift((SkFixed3232)(x), 16))\n#define SkFixed3232ToFixed(x)     ((SkFixed)((x) >> 16))\n#define SkFloatToFixed3232(x)     sk_float_saturate2int64((x) * (65536.0f * 65536.0f))\n#define SkFixed3232ToFloat(x)     (x * (1 / (65536.0f * 65536.0f)))\n\n#define SkScalarToFixed3232(x)    SkFloatToFixed3232(x)\n\n#endif\n"
  },
  {
    "path": "include/private/SkFloatBits.h",
    "content": "/*\n * Copyright 2008 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkFloatBits_DEFINED\n#define SkFloatBits_DEFINED\n\n#include \"SkTypes.h\"\n#include \"SkSafe_math.h\"\n#include <float.h>\n\n/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement\n    int. This also converts -0 (0x80000000) to 0. Doing this to a float allows\n    it to be compared using normal C operators (<, <=, etc.)\n*/\nstatic inline int32_t SkSignBitTo2sCompliment(int32_t x) {\n    if (x < 0) {\n        x &= 0x7FFFFFFF;\n        x = -x;\n    }\n    return x;\n}\n\n/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).\n    This undoes the result of SkSignBitTo2sCompliment().\n */\nstatic inline int32_t Sk2sComplimentToSignBit(int32_t x) {\n    int sign = x >> 31;\n    // make x positive\n    x = (x ^ sign) - sign;\n    // set the sign bit as needed\n    x |= SkLeftShift(sign, 31);\n    return x;\n}\n\nunion SkFloatIntUnion {\n    float   fFloat;\n    int32_t fSignBitInt;\n};\n\n// Helper to see a float as its bit pattern (w/o aliasing warnings)\nstatic inline int32_t SkFloat2Bits(float x) {\n    SkFloatIntUnion data;\n    data.fFloat = x;\n    return data.fSignBitInt;\n}\n\n// Helper to see a bit pattern as a float (w/o aliasing warnings)\nstatic inline float SkBits2Float(int32_t floatAsBits) {\n    SkFloatIntUnion data;\n    data.fSignBitInt = floatAsBits;\n    return data.fFloat;\n}\n\nconstexpr int32_t gFloatBits_exponent_mask = 0x7F800000;\nconstexpr int32_t gFloatBits_matissa_mask  = 0x007FFFFF;\n\nstatic inline bool SkFloatBits_IsFinite(int32_t bits) {\n    return (bits & gFloatBits_exponent_mask) != gFloatBits_exponent_mask;\n}\n\nstatic inline bool SkFloatBits_IsInf(int32_t bits) {\n    return ((bits & gFloatBits_exponent_mask) == gFloatBits_exponent_mask) &&\n            (bits & gFloatBits_matissa_mask) == 0;\n}\n\n/** Return the float as a 2s compliment int. Just to be used to compare floats\n    to each other or against positive float-bit-constants (like 0). This does\n    not return the int equivalent of the float, just something cheaper for\n    compares-only.\n */\nstatic inline int32_t SkFloatAs2sCompliment(float x) {\n    return SkSignBitTo2sCompliment(SkFloat2Bits(x));\n}\n\n/** Return the 2s compliment int as a float. This undos the result of\n    SkFloatAs2sCompliment\n */\nstatic inline float Sk2sComplimentAsFloat(int32_t x) {\n    return SkBits2Float(Sk2sComplimentToSignBit(x));\n}\n\n//  Scalar wrappers for float-bit routines\n\n#define SkScalarAs2sCompliment(x)    SkFloatAs2sCompliment(x)\n\n#endif\n"
  },
  {
    "path": "include/private/SkFloatingPoint.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFloatingPoint_DEFINED\n#define SkFloatingPoint_DEFINED\n\n#include \"../private/SkFloatBits.h\"\n#include \"SkTypes.h\"\n#include \"SkSafe_math.h\"\n#include <float.h>\n#include <math.h>\n\n#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1\n    #include <xmmintrin.h>\n#elif defined(SK_ARM_HAS_NEON)\n    #include <arm_neon.h>\n#endif\n\n// For _POSIX_VERSION\n#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))\n#include <unistd.h>\n#endif\n\n// C++98 cmath std::pow seems to be the earliest portable way to get float pow.\n// However, on Linux including cmath undefines isfinite.\n// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14608\nstatic inline float sk_float_pow(float base, float exp) {\n    return powf(base, exp);\n}\n\n#define sk_float_sqrt(x)        sqrtf(x)\n#define sk_float_sin(x)         sinf(x)\n#define sk_float_cos(x)         cosf(x)\n#define sk_float_tan(x)         tanf(x)\n#define sk_float_floor(x)       floorf(x)\n#define sk_float_ceil(x)        ceilf(x)\n#define sk_float_trunc(x)       truncf(x)\n#ifdef SK_BUILD_FOR_MAC\n#    define sk_float_acos(x)    static_cast<float>(acos(x))\n#    define sk_float_asin(x)    static_cast<float>(asin(x))\n#else\n#    define sk_float_acos(x)    acosf(x)\n#    define sk_float_asin(x)    asinf(x)\n#endif\n#define sk_float_atan2(y,x)     atan2f(y,x)\n#define sk_float_abs(x)         fabsf(x)\n#define sk_float_copysign(x, y) copysignf(x, y)\n#define sk_float_mod(x,y)       fmodf(x,y)\n#define sk_float_exp(x)         expf(x)\n#define sk_float_log(x)         logf(x)\n\n#define sk_float_round(x) sk_float_floor((x) + 0.5f)\n\n// can't find log2f on android, but maybe that just a tool bug?\n#ifdef SK_BUILD_FOR_ANDROID\n    static inline float sk_float_log2(float x) {\n        const double inv_ln_2 = 1.44269504088896;\n        return (float)(log(x) * inv_ln_2);\n    }\n#else\n    #define sk_float_log2(x)        log2f(x)\n#endif\n\nstatic inline bool sk_float_isfinite(float x) {\n    return SkFloatBits_IsFinite(SkFloat2Bits(x));\n}\n\nstatic inline bool sk_float_isinf(float x) {\n    return SkFloatBits_IsInf(SkFloat2Bits(x));\n}\n\nstatic inline bool sk_float_isnan(float x) {\n    return !(x == x);\n}\n\n#define sk_double_isnan(a)          sk_float_isnan(a)\n\n#define SK_MaxS32FitsInFloat    2147483520\n#define SK_MinS32FitsInFloat    -SK_MaxS32FitsInFloat\n\n#define SK_MaxS64FitsInFloat    (SK_MaxS64 >> (63-24) << (63-24))   // 0x7fffff8000000000\n#define SK_MinS64FitsInFloat    -SK_MaxS64FitsInFloat\n\n/**\n *  Return the closest int for the given float. Returns SK_MaxS32FitsInFloat for NaN.\n */\nstatic inline int sk_float_saturate2int(float x) {\n    x = SkTMin<float>(x, SK_MaxS32FitsInFloat);\n    x = SkTMax<float>(x, SK_MinS32FitsInFloat);\n    return (int)x;\n}\n\n/**\n *  Return the closest int for the given double. Returns SK_MaxS32 for NaN.\n */\nstatic inline int sk_double_saturate2int(double x) {\n    x = SkTMin<double>(x, SK_MaxS32);\n    x = SkTMax<double>(x, SK_MinS32);\n    return (int)x;\n}\n\n/**\n *  Return the closest int64_t for the given float. Returns SK_MaxS64FitsInFloat for NaN.\n */\nstatic inline int64_t sk_float_saturate2int64(float x) {\n    x = SkTMin<float>(x, SK_MaxS64FitsInFloat);\n    x = SkTMax<float>(x, SK_MinS64FitsInFloat);\n    return (int64_t)x;\n}\n\n#define sk_float_floor2int(x)   sk_float_saturate2int(sk_float_floor(x))\n#define sk_float_round2int(x)   sk_float_saturate2int(sk_float_floor((x) + 0.5f))\n#define sk_float_ceil2int(x)    sk_float_saturate2int(sk_float_ceil(x))\n\n#define sk_float_floor2int_no_saturate(x)   (int)sk_float_floor(x)\n#define sk_float_round2int_no_saturate(x)   (int)sk_float_floor((x) + 0.5f)\n#define sk_float_ceil2int_no_saturate(x)    (int)sk_float_ceil(x)\n\n#define sk_double_floor(x)          floor(x)\n#define sk_double_round(x)          floor((x) + 0.5)\n#define sk_double_ceil(x)           ceil(x)\n#define sk_double_floor2int(x)      (int)floor(x)\n#define sk_double_round2int(x)      (int)floor((x) + 0.5)\n#define sk_double_ceil2int(x)       (int)ceil(x)\n\n// Cast double to float, ignoring any warning about too-large finite values being cast to float.\n// Clang thinks this is undefined, but it's actually implementation defined to return either\n// the largest float or infinity (one of the two bracketing representable floats).  Good enough!\n#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007\n__attribute__((no_sanitize(\"float-cast-overflow\")))\n#endif\nstatic inline float sk_double_to_float(double x) {\n    return static_cast<float>(x);\n}\n\n#define SK_FloatNaN                 NAN\n#define SK_FloatInfinity            (+INFINITY)\n#define SK_FloatNegativeInfinity    (-INFINITY)\n\nstatic inline float sk_float_rsqrt_portable(float x) {\n    // Get initial estimate.\n    int i;\n    memcpy(&i, &x, 4);\n    i = 0x5F1FFFF9 - (i>>1);\n    float estimate;\n    memcpy(&estimate, &i, 4);\n\n    // One step of Newton's method to refine.\n    const float estimate_sq = estimate*estimate;\n    estimate *= 0.703952253f*(2.38924456f-x*estimate_sq);\n    return estimate;\n}\n\n// Fast, approximate inverse square root.\n// Compare to name-brand \"1.0f / sk_float_sqrt(x)\".  Should be around 10x faster on SSE, 2x on NEON.\nstatic inline float sk_float_rsqrt(float x) {\n// We want all this inlined, so we'll inline SIMD and just take the hit when we don't know we've got\n// it at compile time.  This is going to be too fast to productively hide behind a function pointer.\n//\n// We do one step of Newton's method to refine the estimates in the NEON and portable paths.  No\n// refinement is faster, but very innacurate.  Two steps is more accurate, but slower than 1/sqrt.\n//\n// Optimized constants in the portable path courtesy of http://rrrola.wz.cz/inv_sqrt.html\n#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1\n    return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x)));\n#elif defined(SK_ARM_HAS_NEON)\n    // Get initial estimate.\n    const float32x2_t xx = vdup_n_f32(x);  // Clever readers will note we're doing everything 2x.\n    float32x2_t estimate = vrsqrte_f32(xx);\n\n    // One step of Newton's method to refine.\n    const float32x2_t estimate_sq = vmul_f32(estimate, estimate);\n    estimate = vmul_f32(estimate, vrsqrts_f32(xx, estimate_sq));\n    return vget_lane_f32(estimate, 0);  // 1 will work fine too; the answer's in both places.\n#else\n    return sk_float_rsqrt_portable(x);\n#endif\n}\n\n// This is the number of significant digits we can print in a string such that when we read that\n// string back we get the floating point number we expect.  The minimum value C requires is 6, but\n// most compilers support 9\n#ifdef FLT_DECIMAL_DIG\n#define SK_FLT_DECIMAL_DIG FLT_DECIMAL_DIG\n#else\n#define SK_FLT_DECIMAL_DIG 9\n#endif\n\n// IEEE defines how float divide behaves for non-finite values and zero-denoms, but C does not\n// so we have a helper that suppresses the possible undefined-behavior warnings.\n\n#ifdef __clang__\n__attribute__((no_sanitize(\"float-divide-by-zero\")))\n#endif\nstatic inline float sk_ieee_float_divide(float numer, float denom) {\n    return numer / denom;\n}\n\n#ifdef __clang__\n__attribute__((no_sanitize(\"float-divide-by-zero\")))\n#endif\nstatic inline double sk_ieee_double_divide(double numer, double denom) {\n    return numer / denom;\n}\n\n#endif\n"
  },
  {
    "path": "include/private/SkFloatingPoint.h.orig",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFloatingPoint_DEFINED\n#define SkFloatingPoint_DEFINED\n\n#include \"../private/SkFloatBits.h\"\n#include \"SkTypes.h\"\n#include \"SkSafe_math.h\"\n#include <float.h>\n#include <math.h>\n\n#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1\n    #include <xmmintrin.h>\n#elif defined(SK_ARM_HAS_NEON)\n    #include <arm_neon.h>\n#endif\n\n// For _POSIX_VERSION\n#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))\n#include <unistd.h>\n#endif\n\n// C++98 cmath std::pow seems to be the earliest portable way to get float pow.\n// However, on Linux including cmath undefines isfinite.\n// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14608\nstatic inline float sk_float_pow(float base, float exp) {\n    return powf(base, exp);\n}\n\n#define sk_float_sqrt(x)        sqrtf(x)\n#define sk_float_sin(x)         sinf(x)\n#define sk_float_cos(x)         cosf(x)\n#define sk_float_tan(x)         tanf(x)\n#define sk_float_floor(x)       floorf(x)\n#define sk_float_ceil(x)        ceilf(x)\n#define sk_float_trunc(x)       truncf(x)\n#ifdef SK_BUILD_FOR_MAC\n#    define sk_float_acos(x)    static_cast<float>(acos(x))\n#    define sk_float_asin(x)    static_cast<float>(asin(x))\n#else\n#    define sk_float_acos(x)    acosf(x)\n#    define sk_float_asin(x)    asinf(x)\n#endif\n#define sk_float_atan2(y,x)     atan2f(y,x)\n#define sk_float_abs(x)         fabsf(x)\n#define sk_float_copysign(x, y) copysignf(x, y)\n#define sk_float_mod(x,y)       fmodf(x,y)\n#define sk_float_exp(x)         expf(x)\n#define sk_float_log(x)         logf(x)\n\n#define sk_float_round(x) sk_float_floor((x) + 0.5f)\n\n// can't find log2f on android, but maybe that just a tool bug?\n#ifdef SK_BUILD_FOR_ANDROID\n    static inline float sk_float_log2(float x) {\n        const double inv_ln_2 = 1.44269504088896;\n        return (float)(log(x) * inv_ln_2);\n    }\n#else\n    #define sk_float_log2(x)        log2f(x)\n#endif\n\nstatic inline bool sk_float_isfinite(float x) {\n    return SkFloatBits_IsFinite(SkFloat2Bits(x));\n}\n\nstatic inline bool sk_float_isinf(float x) {\n    return SkFloatBits_IsInf(SkFloat2Bits(x));\n}\n\nstatic inline bool sk_float_isnan(float x) {\n    return !(x == x);\n}\n\n#define sk_double_isnan(a)          sk_float_isnan(a)\n\n#define SK_MaxS32FitsInFloat    2147483520\n#define SK_MinS32FitsInFloat    -SK_MaxS32FitsInFloat\n\n#define SK_MaxS64FitsInFloat    (SK_MaxS64 >> (63-24) << (63-24))   // 0x7fffff8000000000\n#define SK_MinS64FitsInFloat    -SK_MaxS64FitsInFloat\n\n/**\n *  Return the closest int for the given float. Returns SK_MaxS32FitsInFloat for NaN.\n */\nstatic inline int sk_float_saturate2int(float x) {\n    x = SkTMin<float>(x, SK_MaxS32FitsInFloat);\n    x = SkTMax<float>(x, SK_MinS32FitsInFloat);\n    return (int)x;\n}\n\n/**\n *  Return the closest int for the given double. Returns SK_MaxS32 for NaN.\n */\nstatic inline int sk_double_saturate2int(double x) {\n    x = SkTMin<double>(x, SK_MaxS32);\n    x = SkTMax<double>(x, SK_MinS32);\n    return (int)x;\n}\n\n/**\n *  Return the closest int64_t for the given float. Returns SK_MaxS64FitsInFloat for NaN.\n */\nstatic inline int64_t sk_float_saturate2int64(float x) {\n    x = SkTMin<float>(x, SK_MaxS64FitsInFloat);\n    x = SkTMax<float>(x, SK_MinS64FitsInFloat);\n    return (int64_t)x;\n}\n\n#define sk_float_floor2int(x)   sk_float_saturate2int(sk_float_floor(x))\n#define sk_float_round2int(x)   sk_float_saturate2int(sk_float_floor((x) + 0.5f))\n#define sk_float_ceil2int(x)    sk_float_saturate2int(sk_float_ceil(x))\n\n#define sk_float_floor2int_no_saturate(x)   (int)sk_float_floor(x)\n#define sk_float_round2int_no_saturate(x)   (int)sk_float_floor((x) + 0.5f)\n#define sk_float_ceil2int_no_saturate(x)    (int)sk_float_ceil(x)\n\n#define sk_double_floor(x)          floor(x)\n#define sk_double_round(x)          floor((x) + 0.5)\n#define sk_double_ceil(x)           ceil(x)\n#define sk_double_floor2int(x)      (int)floor(x)\n#define sk_double_round2int(x)      (int)floor((x) + 0.5)\n#define sk_double_ceil2int(x)       (int)ceil(x)\n\n// Cast double to float, ignoring any warning about too-large finite values being cast to float.\n// Clang thinks this is undefined, but it's actually implementation defined to return either\n// the largest float or infinity (one of the two bracketing representable floats).  Good enough!\n#if defined(__clang__) && (__clang_major__ * 1000 + __clang_minor__) >= 3007\n__attribute__((no_sanitize(\"float-cast-overflow\")))\n#endif\nstatic inline float sk_double_to_float(double x) {\n    return static_cast<float>(x);\n}\n\n#define SK_FloatNaN                 NAN\n#define SK_FloatInfinity            (+INFINITY)\n#define SK_FloatNegativeInfinity    (-INFINITY)\n\nstatic inline float sk_float_rsqrt_portable(float x) {\n    // Get initial estimate.\n    int i;\n    memcpy(&i, &x, 4);\n    i = 0x5F1FFFF9 - (i>>1);\n    float estimate;\n    memcpy(&estimate, &i, 4);\n\n    // One step of Newton's method to refine.\n    const float estimate_sq = estimate*estimate;\n    estimate *= 0.703952253f*(2.38924456f-x*estimate_sq);\n    return estimate;\n}\n\n// Fast, approximate inverse square root.\n// Compare to name-brand \"1.0f / sk_float_sqrt(x)\".  Should be around 10x faster on SSE, 2x on NEON.\nstatic inline float sk_float_rsqrt(float x) {\n// We want all this inlined, so we'll inline SIMD and just take the hit when we don't know we've got\n// it at compile time.  This is going to be too fast to productively hide behind a function pointer.\n//\n// We do one step of Newton's method to refine the estimates in the NEON and portable paths.  No\n// refinement is faster, but very innacurate.  Two steps is more accurate, but slower than 1/sqrt.\n//\n// Optimized constants in the portable path courtesy of http://rrrola.wz.cz/inv_sqrt.html\n#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1\n    return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x)));\n#elif defined(SK_ARM_HAS_NEON)\n    // Get initial estimate.\n    const float32x2_t xx = vdup_n_f32(x);  // Clever readers will note we're doing everything 2x.\n    float32x2_t estimate = vrsqrte_f32(xx);\n\n    // One step of Newton's method to refine.\n    const float32x2_t estimate_sq = vmul_f32(estimate, estimate);\n    estimate = vmul_f32(estimate, vrsqrts_f32(xx, estimate_sq));\n    return vget_lane_f32(estimate, 0);  // 1 will work fine too; the answer's in both places.\n#else\n    return sk_float_rsqrt_portable(x);\n#endif\n}\n\n// This is the number of significant digits we can print in a string such that when we read that\n// string back we get the floating point number we expect.  The minimum value C requires is 6, but\n// most compilers support 9\n#ifdef FLT_DECIMAL_DIG\n#define SK_FLT_DECIMAL_DIG FLT_DECIMAL_DIG\n#else\n#define SK_FLT_DECIMAL_DIG 9\n#endif\n\n// IEEE defines how float divide behaves for non-finite values and zero-denoms, but C does not\n// so we have a helper that suppresses the possible undefined-behavior warnings.\n\n#ifdef __clang__\n__attribute__((no_sanitize(\"float-divide-by-zero\")))\n#endif\nstatic inline float sk_ieee_float_divide(float numer, float denom) {\n    return numer / denom;\n}\n\n#ifdef __clang__\n__attribute__((no_sanitize(\"float-divide-by-zero\")))\n#endif\nstatic inline double sk_ieee_double_divide(double numer, double denom) {\n    return numer / denom;\n}\n\n#endif\n"
  },
  {
    "path": "include/private/SkFloatingPoint.h.rej",
    "content": "--- include/private/SkFloatingPoint.h\t(date 1525107880000)\n+++ include/private/SkFloatingPoint.h\t(date 1528196380000)\n@@ -136,8 +136,9 @@\n     return static_cast<float>(x);\n }\n \n-static const uint32_t kIEEENotANumber = 0x7fffffff;\n-#define SK_FloatNaN                 (*SkTCast<const float*>(&kIEEENotANumber))\n+//https://bugs.chromium.org/p/skia/issues/detail?id=61999\n+#define SK_FloatNaN  NAN // C++11 standard\n+\n #define SK_FloatInfinity            (+(float)INFINITY)\n #define SK_FloatNegativeInfinity    (-(float)INFINITY)\n \n"
  },
  {
    "path": "include/private/SkImageInfoPriv.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkImageInfoPriv_DEFINED\n#define SkImageInfoPriv_DEFINED\n\n#include \"SkImageInfo.h\"\n\nenum SkColorTypeComponentFlag {\n    kRed_SkColorTypeComponentFlag    = 0x1,\n    kGreen_SkColorTypeComponentFlag  = 0x2,\n    kBlue_SkColorTypeComponentFlag   = 0x4,\n    kAlpha_SkColorTypeComponentFlag  = 0x8,\n    kGray_SkColorTypeComponentFlag   = 0x10,\n    kRGB_SkColorTypeComponentFlags   = kRed_SkColorTypeComponentFlag |\n                                       kGreen_SkColorTypeComponentFlag |\n                                       kBlue_SkColorTypeComponentFlag,\n    kRGBA_SkColorTypeComponentFlags  = kRGB_SkColorTypeComponentFlags |\n                                       kAlpha_SkColorTypeComponentFlag,\n};\n\nstatic inline uint32_t SkColorTypeComponentFlags(SkColorType ct) {\n    switch (ct) {\n        case kUnknown_SkColorType:      return 0;\n        case kAlpha_8_SkColorType:      return kAlpha_SkColorTypeComponentFlag;\n        case kRGB_565_SkColorType:      return kRGB_SkColorTypeComponentFlags;\n        case kARGB_4444_SkColorType:    return kRGBA_SkColorTypeComponentFlags;\n        case kRGBA_8888_SkColorType:    return kRGBA_SkColorTypeComponentFlags;\n        case kRGB_888x_SkColorType:     return kRGB_SkColorTypeComponentFlags;\n        case kBGRA_8888_SkColorType:    return kRGBA_SkColorTypeComponentFlags;\n        case kRGBA_1010102_SkColorType: return kRGBA_SkColorTypeComponentFlags;\n        case kRGB_101010x_SkColorType:  return kRGB_SkColorTypeComponentFlags;\n        case kGray_8_SkColorType:       return kGray_SkColorTypeComponentFlag;\n        case kRGBA_F16_SkColorType:     return kRGBA_SkColorTypeComponentFlags;\n    }\n    return 0;\n}\n\nstatic inline bool SkColorTypeIsAlphaOnly(SkColorType ct) {\n    return kAlpha_SkColorTypeComponentFlag == SkColorTypeComponentFlags(ct);\n}\n\nstatic inline bool SkAlphaTypeIsValid(unsigned value) {\n    return value <= kLastEnum_SkAlphaType;\n}\n\nstatic inline bool SkColorTypeIsGray(SkColorType ct) {\n    auto flags = SkColorTypeComponentFlags(ct);\n    // Currently assuming that a color type has only gray or does not have gray.\n    SkASSERT(!(kGray_SkColorTypeComponentFlag & flags) || kGray_SkColorTypeComponentFlag == flags);\n    return kGray_SkColorTypeComponentFlag == flags;\n}\n\nstatic int SkColorTypeShiftPerPixel(SkColorType ct) {\n    switch (ct) {\n        case kUnknown_SkColorType:      return 0;\n        case kAlpha_8_SkColorType:      return 0;\n        case kRGB_565_SkColorType:      return 1;\n        case kARGB_4444_SkColorType:    return 1;\n        case kRGBA_8888_SkColorType:    return 2;\n        case kRGB_888x_SkColorType:     return 2;\n        case kBGRA_8888_SkColorType:    return 2;\n        case kRGBA_1010102_SkColorType: return 2;\n        case kRGB_101010x_SkColorType:  return 2;\n        case kGray_8_SkColorType:       return 0;\n        case kRGBA_F16_SkColorType:     return 3;\n    }\n    return 0;\n}\n\nstatic inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {\n    return width * SkColorTypeBytesPerPixel(ct);\n}\n\nstatic inline bool SkColorTypeIsValid(unsigned value) {\n    return value <= kLastEnum_SkColorType;\n}\n\nstatic inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) {\n    if (kUnknown_SkColorType == ct) {\n        return 0;\n    }\n    return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct));\n}\n\n/**\n *  Returns true if |info| contains a valid combination of width, height, colorType, and alphaType.\n */\nstatic inline bool SkImageInfoIsValid(const SkImageInfo& info) {\n    if (info.width() <= 0 || info.height() <= 0) {\n        return false;\n    }\n\n    const int kMaxDimension = SK_MaxS32 >> 2;\n    if (info.width() > kMaxDimension || info.height() > kMaxDimension) {\n        return false;\n    }\n\n    if (kUnknown_SkColorType == info.colorType() || kUnknown_SkAlphaType == info.alphaType()) {\n        return false;\n    }\n\n    if (kOpaque_SkAlphaType != info.alphaType() &&\n       (kRGB_565_SkColorType == info.colorType() || kGray_8_SkColorType == info.colorType())) {\n        return false;\n    }\n\n    return true;\n}\n\n/**\n *  Returns true if Skia has defined a pixel conversion from the |src| to the |dst|.\n *  Returns false otherwise.  Some discussion of false cases:\n *      We do not convert to kGray8 when the |src| is not kGray8 in the same color space.\n *      We may add this feature - it just requires some work to convert to luminance while\n *      handling color spaces correctly.  Currently no one is asking for this.\n *      We will not convert from kAlpha8 when the |dst| is not kAlpha8.  This would require\n *      inventing color information.\n *      We will not convert to kOpaque when the |src| is not kOpaque.  This could be\n *      implemented to set all the alpha values to 1, but there is still some ambiguity -\n *      should we use kPremul or kUnpremul color values with the opaque alphas?  Or should\n *      we just use whatever the |src| alpha is?  In the future, we could choose to clearly\n *      define this, but currently no one is asking for this feature.\n *      We will not convert to a particular color space if |src| is nullptr.  The color space\n *      conversion is not well-defined.\n */\nstatic inline bool SkImageInfoValidConversion(const SkImageInfo& dst, const SkImageInfo& src) {\n    if (!SkImageInfoIsValid(dst) || !SkImageInfoIsValid(src)) {\n        return false;\n    }\n\n    if (SkColorTypeIsGray(dst.colorType())) {\n        if (!SkColorTypeIsGray(src.colorType())) {\n            return false;\n        }\n\n        if (dst.colorSpace() && !SkColorSpace::Equals(dst.colorSpace(), src.colorSpace())) {\n            return false;\n        }\n    }\n\n    if (!SkColorTypeIsAlphaOnly(dst.colorType()) && SkColorTypeIsAlphaOnly(src.colorType())) {\n        return false;\n    }\n\n    if (kOpaque_SkAlphaType == dst.alphaType() && kOpaque_SkAlphaType != src.alphaType()) {\n        return false;\n    }\n\n    if (dst.colorSpace() && !src.colorSpace()) {\n        return false;\n    }\n\n    return true;\n}\n#endif  // SkImageInfoPriv_DEFINED\n"
  },
  {
    "path": "include/private/SkLeanWindows.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkLeanWindows_DEFINED\n#define SkLeanWindows_DEFINED\n\n#include \"SkTypes.h\"\n\n#ifdef SK_BUILD_FOR_WIN\n#  ifndef WIN32_LEAN_AND_MEAN\n#    define WIN32_LEAN_AND_MEAN\n#    define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED\n#  endif\n#  ifndef NOMINMAX\n#    define NOMINMAX\n#    define NOMINMAX_WAS_LOCALLY_DEFINED\n#  endif\n#\n#  include <windows.h>\n#\n#  ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED\n#    undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED\n#    undef WIN32_LEAN_AND_MEAN\n#  endif\n#  ifdef NOMINMAX_WAS_LOCALLY_DEFINED\n#    undef NOMINMAX_WAS_LOCALLY_DEFINED\n#    undef NOMINMAX\n#  endif\n#endif\n\n#endif  // SkLeanWindows_DEFINED\n"
  },
  {
    "path": "include/private/SkMalloc.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMalloc_DEFINED\n#define SkMalloc_DEFINED\n\n#include <cstddef>\n#include <cstring>\n\n#include \"SkTypes.h\"\n\n/*\n    memory wrappers to be implemented by the porting layer (platform)\n*/\n\n\n/** Free memory returned by sk_malloc(). It is safe to pass null. */\nSK_API extern void sk_free(void*);\n\n/**\n *  Called internally if we run out of memory. The platform implementation must\n *  not return, but should either throw an exception or otherwise exit.\n */\nSK_API extern void sk_out_of_memory(void);\n\nenum {\n    /**\n     *  If this bit is set, the returned buffer must be zero-initialized. If this bit is not set\n     *  the buffer can be uninitialized.\n     */\n    SK_MALLOC_ZERO_INITIALIZE   = 1 << 0,\n\n    /**\n     *  If this bit is set, the implementation must throw/crash/quit if the request cannot\n     *  be fulfilled. If this bit is not set, then it should return nullptr on failure.\n     */\n    SK_MALLOC_THROW             = 1 << 1,\n};\n/**\n *  Return a block of memory (at least 4-byte aligned) of at least the specified size.\n *  If the requested memory cannot be returned, either return nullptr or throw/exit, depending\n *  on the SK_MALLOC_THROW bit. If the allocation succeeds, the memory will be zero-initialized\n *  if the SK_MALLOC_ZERO_INITIALIZE bit was set.\n *\n *  To free the memory, call sk_free()\n */\nSK_API extern void* sk_malloc_flags(size_t size, unsigned flags);\n\n/** Same as standard realloc(), but this one never returns null on failure. It will throw\n *  an exception if it fails.\n */\nSK_API extern void* sk_realloc_throw(void* buffer, size_t size);\n\nstatic inline void* sk_malloc_throw(size_t size) {\n    return sk_malloc_flags(size, SK_MALLOC_THROW);\n}\n\nstatic inline void* sk_calloc_throw(size_t size) {\n    return sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_ZERO_INITIALIZE);\n}\n\nstatic inline void* sk_calloc_canfail(size_t size) {\n#if defined(IS_FUZZING_WITH_LIBFUZZER)\n    // The Libfuzzer environment is very susceptible to OOM, so to avoid those\n    // just pretend we can't allocate more than 200kb.\n    if (size > 200000) {\n        return nullptr;\n    }\n#endif\n    return sk_malloc_flags(size, SK_MALLOC_ZERO_INITIALIZE);\n}\n\n// Performs a safe multiply count * elemSize, checking for overflow\nSK_API extern void* sk_calloc_throw(size_t count, size_t elemSize);\nSK_API extern void* sk_malloc_throw(size_t count, size_t elemSize);\nSK_API extern void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize);\n\n/**\n *  These variants return nullptr on failure\n */\nstatic inline void* sk_malloc_canfail(size_t size) {\n#if defined(IS_FUZZING_WITH_LIBFUZZER)\n    // The Libfuzzer environment is very susceptible to OOM, so to avoid those\n    // just pretend we can't allocate more than 200kb.\n    if (size > 200000) {\n        return nullptr;\n    }\n#endif\n    return sk_malloc_flags(size, 0);\n}\nSK_API extern void* sk_malloc_canfail(size_t count, size_t elemSize);\n\n// bzero is safer than memset, but we can't rely on it, so... sk_bzero()\nstatic inline void sk_bzero(void* buffer, size_t size) {\n    // Please c.f. sk_careful_memcpy.  It's undefined behavior to call memset(null, 0, 0).\n    if (size) {\n        memset(buffer, 0, size);\n    }\n}\n\n/**\n *  sk_careful_memcpy() is just like memcpy(), but guards against undefined behavior.\n *\n * It is undefined behavior to call memcpy() with null dst or src, even if len is 0.\n * If an optimizer is \"smart\" enough, it can exploit this to do unexpected things.\n *     memcpy(dst, src, 0);\n *     if (src) {\n *         printf(\"%x\\n\", *src);\n *     }\n * In this code the compiler can assume src is not null and omit the if (src) {...} check,\n * unconditionally running the printf, crashing the program if src really is null.\n * Of the compilers we pay attention to only GCC performs this optimization in practice.\n */\nstatic inline void* sk_careful_memcpy(void* dst, const void* src, size_t len) {\n    // When we pass >0 len we had better already be passing valid pointers.\n    // So we just need to skip calling memcpy when len == 0.\n    if (len) {\n        memcpy(dst,src,len);\n    }\n    return dst;\n}\n\n#endif  // SkMalloc_DEFINED\n"
  },
  {
    "path": "include/private/SkMessageBus.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMessageBus_DEFINED\n#define SkMessageBus_DEFINED\n\n#include \"SkMutex.h\"\n#include \"SkOnce.h\"\n#include \"SkTArray.h\"\n#include \"SkTDArray.h\"\n#include \"SkTypes.h\"\n\ntemplate <typename Message>\nclass SkMessageBus : SkNoncopyable {\npublic:\n    // Post a message to be received by Inboxes for this Message type.  Threadsafe.\n    // If id is SK_InvalidUniqueID then it will be sent to all inboxes.\n    // Otherwise it will be sent to the inbox with that id.\n    static void Post(const Message& m, uint32_t destID = SK_InvalidUniqueID);\n\n    class Inbox {\n    public:\n        Inbox(uint32_t uniqueID = SK_InvalidUniqueID);\n        ~Inbox();\n\n        // Overwrite out with all the messages we've received since the last call.  Threadsafe.\n        void poll(SkTArray<Message>* out);\n\n    private:\n        SkTArray<Message>  fMessages;\n        SkMutex            fMessagesMutex;\n        uint32_t           fUniqueID;\n\n        friend class SkMessageBus;\n        void receive(const Message& m);  // SkMessageBus is a friend only to call this.\n    };\n\nprivate:\n    SkMessageBus();\n    static SkMessageBus* Get();\n\n    SkTDArray<Inbox*> fInboxes;\n    SkMutex           fInboxesMutex;\n};\n\n// This must go in a single .cpp file, not some .h, or we risk creating more than one global\n// SkMessageBus per type when using shared libraries.  NOTE: at most one per file will compile.\n#define DECLARE_SKMESSAGEBUS_MESSAGE(Message)                      \\\n    template <>                                                    \\\n    SkMessageBus<Message>* SkMessageBus<Message>::Get() {          \\\n        static SkOnce once;                                        \\\n        static SkMessageBus<Message>* bus;                         \\\n        once([] { bus = new SkMessageBus<Message>(); });           \\\n        return bus;                                                \\\n    }\n\n//   ----------------------- Implementation of SkMessageBus::Inbox -----------------------\n\ntemplate<typename Message>\nSkMessageBus<Message>::Inbox::Inbox(uint32_t uniqueID) : fUniqueID(uniqueID) {\n    // Register ourselves with the corresponding message bus.\n    SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();\n    SkAutoMutexAcquire lock(bus->fInboxesMutex);\n    bus->fInboxes.push(this);\n}\n\ntemplate<typename Message>\nSkMessageBus<Message>::Inbox::~Inbox() {\n    // Remove ourselves from the corresponding message bus.\n    SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();\n    SkAutoMutexAcquire lock(bus->fInboxesMutex);\n    // This is a cheaper fInboxes.remove(fInboxes.find(this)) when order doesn't matter.\n    for (int i = 0; i < bus->fInboxes.count(); i++) {\n        if (this == bus->fInboxes[i]) {\n            bus->fInboxes.removeShuffle(i);\n            break;\n        }\n    }\n}\n\ntemplate<typename Message>\nvoid SkMessageBus<Message>::Inbox::receive(const Message& m) {\n    SkAutoMutexAcquire lock(fMessagesMutex);\n    fMessages.push_back(m);\n}\n\ntemplate<typename Message>\nvoid SkMessageBus<Message>::Inbox::poll(SkTArray<Message>* messages) {\n    SkASSERT(messages);\n    messages->reset();\n    SkAutoMutexAcquire lock(fMessagesMutex);\n    fMessages.swap(messages);\n}\n\n//   ----------------------- Implementation of SkMessageBus -----------------------\n\ntemplate <typename Message>\nSkMessageBus<Message>::SkMessageBus() {}\n\ntemplate <typename Message>\n/*static*/ void SkMessageBus<Message>::Post(const Message& m, uint32_t destID) {\n    SkMessageBus<Message>* bus = SkMessageBus<Message>::Get();\n    SkAutoMutexAcquire lock(bus->fInboxesMutex);\n    for (int i = 0; i < bus->fInboxes.count(); i++) {\n        if (SK_InvalidUniqueID == destID || bus->fInboxes[i]->fUniqueID == destID) {\n            bus->fInboxes[i]->receive(m);\n        }\n    }\n}\n\n#endif  // SkMessageBus_DEFINED\n"
  },
  {
    "path": "include/private/SkMutex.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkMutex_DEFINED\n#define SkMutex_DEFINED\n\n#include \"../private/SkSemaphore.h\"\n#include \"../private/SkThreadID.h\"\n#include \"SkTypes.h\"\n\n#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name;\n\nclass SkBaseMutex {\npublic:\n    constexpr SkBaseMutex() = default;\n\n    void acquire() {\n        fSemaphore.wait();\n        SkDEBUGCODE(fOwner = SkGetThreadID();)\n    }\n\n    void release() {\n        this->assertHeld();\n        SkDEBUGCODE(fOwner = kIllegalThreadID;)\n        fSemaphore.signal();\n    }\n\n    void assertHeld() {\n        SkASSERT(fOwner == SkGetThreadID());\n    }\n\nprotected:\n    SkBaseSemaphore fSemaphore{1};\n    SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)\n};\n\nclass SkMutex : public SkBaseMutex {\npublic:\n    using SkBaseMutex::SkBaseMutex;\n    ~SkMutex() { fSemaphore.cleanup(); }\n};\n\nclass SkAutoMutexAcquire {\npublic:\n    template <typename T>\n    SkAutoMutexAcquire(T* mutex) : fMutex(mutex) {\n        if (mutex) {\n            mutex->acquire();\n        }\n        fRelease = [](void* mutex) { ((T*)mutex)->release(); };\n    }\n\n    template <typename T>\n    SkAutoMutexAcquire(T& mutex) : SkAutoMutexAcquire(&mutex) {}\n\n    ~SkAutoMutexAcquire() { this->release(); }\n\n    void release() {\n        if (fMutex) {\n            fRelease(fMutex);\n        }\n        fMutex = nullptr;\n    }\n\nprivate:\n    void*  fMutex;\n    void (*fRelease)(void*);\n};\n#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)\n\n// SkAutoExclusive is a lighter weight version of SkAutoMutexAcquire.\n// It assumes that there is a valid mutex, obviating the null check.\nclass SkAutoExclusive {\npublic:\n    template <typename T>\n    SkAutoExclusive(T& mutex) : fMutex(&mutex) {\n        mutex.acquire();\n\n        fRelease = [](void* mutex) { ((T*)mutex)->release(); };\n    }\n    ~SkAutoExclusive() { fRelease(fMutex); }\n\nprivate:\n    void* fMutex;\n    void (*fRelease)(void*);\n};\n#define SkAutoExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoExclusive)\n\n#endif//SkMutex_DEFINED\n"
  },
  {
    "path": "include/private/SkOnce.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkOnce_DEFINED\n#define SkOnce_DEFINED\n\n#include <atomic>\n#include <utility>\n#include \"SkTypes.h\"\n\n// SkOnce provides call-once guarantees for Skia, much like std::once_flag/std::call_once().\n//\n// There should be no particularly error-prone gotcha use cases when using SkOnce.\n// It works correctly as a class member, a local, a global, a function-scoped static, whatever.\n\nclass SkOnce {\npublic:\n    constexpr SkOnce() = default;\n\n    template <typename Fn, typename... Args>\n    void operator()(Fn&& fn, Args&&... args) {\n        auto state = fState.load(std::memory_order_acquire);\n\n        if (state == Done) {\n            return;\n        }\n\n        // If it looks like no one has started calling fn(), try to claim that job.\n        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,\n                                                                  std::memory_order_relaxed,\n                                                                  std::memory_order_relaxed)) {\n            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.\n            fn(std::forward<Args>(args)...);\n            return fState.store(Done, std::memory_order_release);\n        }\n\n        // Some other thread is calling fn().\n        // We'll just spin here acquiring until it releases Done into fState.\n        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }\n    }\n\nprivate:\n    enum State : uint8_t { NotStarted, Claimed, Done};\n    std::atomic<uint8_t> fState{NotStarted};\n};\n\n#endif  // SkOnce_DEFINED\n"
  },
  {
    "path": "include/private/SkPathRef.h",
    "content": "\n/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPathRef_DEFINED\n#define SkPathRef_DEFINED\n\n#include \"../private/SkAtomics.h\"\n#include \"../private/SkTDArray.h\"\n#include \"SkMatrix.h\"\n#include \"SkPoint.h\"\n#include \"SkRRect.h\"\n#include \"SkRect.h\"\n#include \"SkRefCnt.h\"\n#include \"SkTemplates.h\"\n\nclass SkRBuffer;\nclass SkWBuffer;\n\n/**\n * Holds the path verbs and points. It is versioned by a generation ID. None of its public methods\n * modify the contents. To modify or append to the verbs/points wrap the SkPathRef in an\n * SkPathRef::Editor object. Installing the editor resets the generation ID. It also performs\n * copy-on-write if the SkPathRef is shared by multiple SkPaths. The caller passes the Editor's\n * constructor a pointer to a sk_sp<SkPathRef>, which may be updated to point to a new SkPathRef\n * after the editor's constructor returns.\n *\n * The points and verbs are stored in a single allocation. The points are at the begining of the\n * allocation while the verbs are stored at end of the allocation, in reverse order. Thus the points\n * and verbs both grow into the middle of the allocation until the meet. To access verb i in the\n * verb array use ref.verbs()[~i] (because verbs() returns a pointer just beyond the first\n * logical verb or the last verb in memory).\n */\n\nclass SK_API SkPathRef final : public SkNVRefCnt<SkPathRef> {\npublic:\n    class Editor {\n    public:\n        Editor(sk_sp<SkPathRef>* pathRef,\n               int incReserveVerbs = 0,\n               int incReservePoints = 0);\n\n        ~Editor() { SkDEBUGCODE(sk_atomic_dec(&fPathRef->fEditorsAttached);) }\n\n        /**\n         * Returns the array of points.\n         */\n        SkPoint* points() { return fPathRef->getPoints(); }\n        const SkPoint* points() const { return fPathRef->points(); }\n\n        /**\n         * Gets the ith point. Shortcut for this->points() + i\n         */\n        SkPoint* atPoint(int i) {\n            SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);\n            return this->points() + i;\n        }\n        const SkPoint* atPoint(int i) const {\n            SkASSERT((unsigned) i < (unsigned) fPathRef->fPointCnt);\n            return this->points() + i;\n        }\n\n        /**\n         * Adds the verb and allocates space for the number of points indicated by the verb. The\n         * return value is a pointer to where the points for the verb should be written.\n         * 'weight' is only used if 'verb' is kConic_Verb\n         */\n        SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight = 0) {\n            SkDEBUGCODE(fPathRef->validate();)\n            return fPathRef->growForVerb(verb, weight);\n        }\n\n        /**\n         * Allocates space for multiple instances of a particular verb and the\n         * requisite points & weights.\n         * The return pointer points at the first new point (indexed normally [<i>]).\n         * If 'verb' is kConic_Verb, 'weights' will return a pointer to the\n         * space for the conic weights (indexed normally).\n         */\n        SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb,\n                                     int numVbs,\n                                     SkScalar** weights = nullptr) {\n            return fPathRef->growForRepeatedVerb(verb, numVbs, weights);\n        }\n\n        /**\n         * Resets the path ref to a new verb and point count. The new verbs and points are\n         * uninitialized.\n         */\n        void resetToSize(int newVerbCnt, int newPointCnt, int newConicCount) {\n            fPathRef->resetToSize(newVerbCnt, newPointCnt, newConicCount);\n        }\n\n        /**\n         * Gets the path ref that is wrapped in the Editor.\n         */\n        SkPathRef* pathRef() { return fPathRef; }\n\n        void setIsOval(bool isOval, bool isCCW, unsigned start) {\n            fPathRef->setIsOval(isOval, isCCW, start);\n        }\n\n        void setIsRRect(bool isRRect, bool isCCW, unsigned start) {\n            fPathRef->setIsRRect(isRRect, isCCW, start);\n        }\n\n        void setBounds(const SkRect& rect) { fPathRef->setBounds(rect); }\n\n    private:\n        SkPathRef* fPathRef;\n    };\n\n    class SK_API Iter {\n    public:\n        Iter();\n        Iter(const SkPathRef&);\n\n        void setPathRef(const SkPathRef&);\n\n        /** Return the next verb in this iteration of the path. When all\n            segments have been visited, return kDone_Verb.\n\n            If any point in the path is non-finite, return kDone_Verb immediately.\n\n            @param  pts The points representing the current verb and/or segment\n                        This must not be NULL.\n            @return The verb for the current segment\n        */\n        uint8_t next(SkPoint pts[4]);\n        uint8_t peek() const;\n\n        SkScalar conicWeight() const { return *fConicWeights; }\n\n    private:\n        const SkPoint*  fPts;\n        const uint8_t*  fVerbs;\n        const uint8_t*  fVerbStop;\n        const SkScalar* fConicWeights;\n    };\n\npublic:\n    /**\n     * Gets a path ref with no verbs or points.\n     */\n    static SkPathRef* CreateEmpty();\n\n    /**\n     *  Returns true if all of the points in this path are finite, meaning there\n     *  are no infinities and no NaNs.\n     */\n    bool isFinite() const {\n        if (fBoundsIsDirty) {\n            this->computeBounds();\n        }\n        return SkToBool(fIsFinite);\n    }\n\n    /**\n     *  Returns a mask, where each bit corresponding to a SegmentMask is\n     *  set if the path contains 1 or more segments of that type.\n     *  Returns 0 for an empty path (no segments).\n     */\n    uint32_t getSegmentMasks() const { return fSegmentMask; }\n\n    /** Returns true if the path is an oval.\n     *\n     * @param rect      returns the bounding rect of this oval. It's a circle\n     *                  if the height and width are the same.\n     * @param isCCW     is the oval CCW (or CW if false).\n     * @param start     indicates where the contour starts on the oval (see\n     *                  SkPath::addOval for intepretation of the index).\n     *\n     * @return true if this path is an oval.\n     *              Tracking whether a path is an oval is considered an\n     *              optimization for performance and so some paths that are in\n     *              fact ovals can report false.\n     */\n    bool isOval(SkRect* rect, bool* isCCW, unsigned* start) const {\n        if (fIsOval) {\n            if (rect) {\n                *rect = this->getBounds();\n            }\n            if (isCCW) {\n                *isCCW = SkToBool(fRRectOrOvalIsCCW);\n            }\n            if (start) {\n                *start = fRRectOrOvalStartIdx;\n            }\n        }\n\n        return SkToBool(fIsOval);\n    }\n\n    bool isRRect(SkRRect* rrect, bool* isCCW, unsigned* start) const {\n        if (fIsRRect) {\n            if (rrect) {\n                *rrect = this->getRRect();\n            }\n            if (isCCW) {\n                *isCCW = SkToBool(fRRectOrOvalIsCCW);\n            }\n            if (start) {\n                *start = fRRectOrOvalStartIdx;\n            }\n        }\n        return SkToBool(fIsRRect);\n    }\n\n\n    bool hasComputedBounds() const {\n        return !fBoundsIsDirty;\n    }\n\n    /** Returns the bounds of the path's points. If the path contains 0 or 1\n        points, the bounds is set to (0,0,0,0), and isEmpty() will return true.\n        Note: this bounds may be larger than the actual shape, since curves\n        do not extend as far as their control points.\n    */\n    const SkRect& getBounds() const {\n        if (fBoundsIsDirty) {\n            this->computeBounds();\n        }\n        return fBounds;\n    }\n\n    SkRRect getRRect() const;\n\n    /**\n     * Transforms a path ref by a matrix, allocating a new one only if necessary.\n     */\n    static void CreateTransformedCopy(sk_sp<SkPathRef>* dst,\n                                      const SkPathRef& src,\n                                      const SkMatrix& matrix);\n\n    static SkPathRef* CreateFromBuffer(SkRBuffer* buffer);\n\n    /**\n     * Rollsback a path ref to zero verbs and points with the assumption that the path ref will be\n     * repopulated with approximately the same number of verbs and points. A new path ref is created\n     * only if necessary.\n     */\n    static void Rewind(sk_sp<SkPathRef>* pathRef);\n\n    ~SkPathRef();\n    int countPoints() const { return fPointCnt; }\n    int countVerbs() const { return fVerbCnt; }\n    int countWeights() const { return fConicWeights.count(); }\n\n    /**\n     * Returns a pointer one beyond the first logical verb (last verb in memory order).\n     */\n    const uint8_t* verbs() const { return fVerbs; }\n\n    /**\n     * Returns a const pointer to the first verb in memory (which is the last logical verb).\n     */\n    const uint8_t* verbsMemBegin() const { return this->verbs() - fVerbCnt; }\n\n    /**\n     * Returns a const pointer to the first point.\n     */\n    const SkPoint* points() const { return fPoints; }\n\n    /**\n     * Shortcut for this->points() + this->countPoints()\n     */\n    const SkPoint* pointsEnd() const { return this->points() + this->countPoints(); }\n\n    const SkScalar* conicWeights() const { return fConicWeights.begin(); }\n    const SkScalar* conicWeightsEnd() const { return fConicWeights.end(); }\n\n    /**\n     * Convenience methods for getting to a verb or point by index.\n     */\n    uint8_t atVerb(int index) const {\n        SkASSERT((unsigned) index < (unsigned) fVerbCnt);\n        return this->verbs()[~index];\n    }\n    const SkPoint& atPoint(int index) const {\n        SkASSERT((unsigned) index < (unsigned) fPointCnt);\n        return this->points()[index];\n    }\n\n    bool operator== (const SkPathRef& ref) const;\n\n    /**\n     * Writes the path points and verbs to a buffer.\n     */\n    void writeToBuffer(SkWBuffer* buffer) const;\n\n    /**\n     * Gets the number of bytes that would be written in writeBuffer()\n     */\n    uint32_t writeSize() const;\n\n    void interpolate(const SkPathRef& ending, SkScalar weight, SkPathRef* out) const;\n\n    /**\n     * Gets an ID that uniquely identifies the contents of the path ref. If two path refs have the\n     * same ID then they have the same verbs and points. However, two path refs may have the same\n     * contents but different genIDs.\n     */\n    uint32_t genID() const;\n\n    struct GenIDChangeListener {\n        virtual ~GenIDChangeListener() {}\n        virtual void onChange() = 0;\n    };\n\n    void addGenIDChangeListener(GenIDChangeListener* listener);\n\n    bool isValid() const;\n    SkDEBUGCODE(void validate() const { SkASSERT(this->isValid()); } )\n\nprivate:\n    enum SerializationOffsets {\n        kLegacyRRectOrOvalStartIdx_SerializationShift = 28, // requires 3 bits, ignored.\n        kLegacyRRectOrOvalIsCCW_SerializationShift = 27,    // requires 1 bit, ignored.\n        kLegacyIsRRect_SerializationShift = 26,             // requires 1 bit, ignored.\n        kIsFinite_SerializationShift = 25,                  // requires 1 bit\n        kLegacyIsOval_SerializationShift = 24,              // requires 1 bit, ignored.\n        kSegmentMask_SerializationShift = 0                 // requires 4 bits (deprecated)\n    };\n\n    SkPathRef() {\n        fBoundsIsDirty = true;    // this also invalidates fIsFinite\n        fPointCnt = 0;\n        fVerbCnt = 0;\n        fVerbs = nullptr;\n        fPoints = nullptr;\n        fFreeSpace = 0;\n        fGenerationID = kEmptyGenID;\n        fSegmentMask = 0;\n        fIsOval = false;\n        fIsRRect = false;\n        // The next two values don't matter unless fIsOval or fIsRRect are true.\n        fRRectOrOvalIsCCW = false;\n        fRRectOrOvalStartIdx = 0xAC;\n        SkDEBUGCODE(fEditorsAttached = 0;)\n        SkDEBUGCODE(this->validate();)\n    }\n\n    void copy(const SkPathRef& ref, int additionalReserveVerbs, int additionalReservePoints);\n\n    // Doesn't read fSegmentMask, but (re)computes it from the verbs array\n    unsigned computeSegmentMask() const;\n\n    // Return true if the computed bounds are finite.\n    static bool ComputePtBounds(SkRect* bounds, const SkPathRef& ref) {\n        return bounds->setBoundsCheck(ref.points(), ref.countPoints());\n    }\n\n    // called, if dirty, by getBounds()\n    void computeBounds() const {\n        SkDEBUGCODE(this->validate();)\n        // TODO(mtklein): remove fBoundsIsDirty and fIsFinite,\n        // using an inverted rect instead of fBoundsIsDirty and always recalculating fIsFinite.\n        SkASSERT(fBoundsIsDirty);\n\n        fIsFinite = ComputePtBounds(&fBounds, *this);\n        fBoundsIsDirty = false;\n    }\n\n    void setBounds(const SkRect& rect) {\n        SkASSERT(rect.fLeft <= rect.fRight && rect.fTop <= rect.fBottom);\n        fBounds = rect;\n        fBoundsIsDirty = false;\n        fIsFinite = fBounds.isFinite();\n    }\n\n    /** Makes additional room but does not change the counts or change the genID */\n    void incReserve(int additionalVerbs, int additionalPoints) {\n        SkDEBUGCODE(this->validate();)\n        size_t space = additionalVerbs * sizeof(uint8_t) + additionalPoints * sizeof (SkPoint);\n        this->makeSpace(space);\n        SkDEBUGCODE(this->validate();)\n    }\n\n    /** Resets the path ref with verbCount verbs and pointCount points, all uninitialized. Also\n     *  allocates space for reserveVerb additional verbs and reservePoints additional points.*/\n    void resetToSize(int verbCount, int pointCount, int conicCount,\n                     int reserveVerbs = 0, int reservePoints = 0) {\n        SkDEBUGCODE(this->validate();)\n        fBoundsIsDirty = true;      // this also invalidates fIsFinite\n        fGenerationID = 0;\n\n        fSegmentMask = 0;\n        fIsOval = false;\n        fIsRRect = false;\n\n        size_t newSize = sizeof(uint8_t) * verbCount + sizeof(SkPoint) * pointCount;\n        size_t newReserve = sizeof(uint8_t) * reserveVerbs + sizeof(SkPoint) * reservePoints;\n        size_t minSize = newSize + newReserve;\n\n        ptrdiff_t sizeDelta = this->currSize() - minSize;\n\n        if (sizeDelta < 0 || static_cast<size_t>(sizeDelta) >= 3 * minSize) {\n            sk_free(fPoints);\n            fPoints = nullptr;\n            fVerbs = nullptr;\n            fFreeSpace = 0;\n            fVerbCnt = 0;\n            fPointCnt = 0;\n            this->makeSpace(minSize);\n            fVerbCnt = verbCount;\n            fPointCnt = pointCount;\n            fFreeSpace -= newSize;\n        } else {\n            fPointCnt = pointCount;\n            fVerbCnt = verbCount;\n            fFreeSpace = this->currSize() - minSize;\n        }\n        fConicWeights.setCount(conicCount);\n        SkDEBUGCODE(this->validate();)\n    }\n\n    /**\n     * Increases the verb count by numVbs and point count by the required amount.\n     * The new points are uninitialized. All the new verbs are set to the specified\n     * verb. If 'verb' is kConic_Verb, 'weights' will return a pointer to the\n     * uninitialized conic weights.\n     */\n    SkPoint* growForRepeatedVerb(int /*SkPath::Verb*/ verb, int numVbs, SkScalar** weights);\n\n    /**\n     * Increases the verb count 1, records the new verb, and creates room for the requisite number\n     * of additional points. A pointer to the first point is returned. Any new points are\n     * uninitialized.\n     */\n    SkPoint* growForVerb(int /*SkPath::Verb*/ verb, SkScalar weight);\n\n    /**\n     * Ensures that the free space available in the path ref is >= size. The verb and point counts\n     * are not changed.\n     */\n    void makeSpace(size_t size) {\n        SkDEBUGCODE(this->validate();)\n        if (size <= fFreeSpace) {\n            return;\n        }\n        size_t growSize = size - fFreeSpace;\n        size_t oldSize = this->currSize();\n        // round to next multiple of 8 bytes\n        growSize = (growSize + 7) & ~static_cast<size_t>(7);\n        // we always at least double the allocation\n        if (growSize < oldSize) {\n            growSize = oldSize;\n        }\n        if (growSize < kMinSize) {\n            growSize = kMinSize;\n        }\n        constexpr size_t maxSize = std::numeric_limits<size_t>::max();\n        size_t newSize;\n        if (growSize <= maxSize - oldSize) {\n            newSize = oldSize + growSize;\n        } else {\n            SK_ABORT(\"Path too big.\");\n        }\n        // Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO:\n        // encapsulate this.\n        fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize));\n        size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);\n        void* newVerbsDst = SkTAddOffset<void>(fPoints, newSize - oldVerbSize);\n        void* oldVerbsSrc = SkTAddOffset<void>(fPoints, oldSize - oldVerbSize);\n        memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);\n        fVerbs = SkTAddOffset<uint8_t>(fPoints, newSize);\n        fFreeSpace += growSize;\n        SkDEBUGCODE(this->validate();)\n    }\n\n    /**\n     * Private, non-const-ptr version of the public function verbsMemBegin().\n     */\n    uint8_t* verbsMemWritable() {\n        SkDEBUGCODE(this->validate();)\n        return fVerbs - fVerbCnt;\n    }\n\n    /**\n     * Gets the total amount of space allocated for verbs, points, and reserve.\n     */\n    size_t currSize() const {\n        return reinterpret_cast<intptr_t>(fVerbs) - reinterpret_cast<intptr_t>(fPoints);\n    }\n\n    /**\n     * Called the first time someone calls CreateEmpty to actually create the singleton.\n     */\n    friend SkPathRef* sk_create_empty_pathref();\n\n    void setIsOval(bool isOval, bool isCCW, unsigned start) {\n        fIsOval = isOval;\n        fRRectOrOvalIsCCW = isCCW;\n        fRRectOrOvalStartIdx = SkToU8(start);\n    }\n\n    void setIsRRect(bool isRRect, bool isCCW, unsigned start) {\n        fIsRRect = isRRect;\n        fRRectOrOvalIsCCW = isCCW;\n        fRRectOrOvalStartIdx = SkToU8(start);\n    }\n\n    // called only by the editor. Note that this is not a const function.\n    SkPoint* getPoints() {\n        SkDEBUGCODE(this->validate();)\n        fIsOval = false;\n        fIsRRect = false;\n        return fPoints;\n    }\n\n    const SkPoint* getPoints() const {\n        SkDEBUGCODE(this->validate();)\n        return fPoints;\n    }\n\n    void callGenIDChangeListeners();\n\n    enum {\n        kMinSize = 256,\n    };\n\n    mutable SkRect   fBounds;\n\n    SkPoint*            fPoints; // points to begining of the allocation\n    uint8_t*            fVerbs; // points just past the end of the allocation (verbs grow backwards)\n    int                 fVerbCnt;\n    int                 fPointCnt;\n    size_t              fFreeSpace; // redundant but saves computation\n    SkTDArray<SkScalar> fConicWeights;\n\n    enum {\n        kEmptyGenID = 1, // GenID reserved for path ref with zero points and zero verbs.\n    };\n    mutable uint32_t    fGenerationID;\n    SkDEBUGCODE(int32_t fEditorsAttached;) // assert that only one editor in use at any time.\n\n    SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned\n\n    mutable uint8_t  fBoundsIsDirty;\n    mutable SkBool8  fIsFinite;    // only meaningful if bounds are valid\n\n    SkBool8  fIsOval;\n    SkBool8  fIsRRect;\n    // Both the circle and rrect special cases have a notion of direction and starting point\n    // The next two variables store that information for either.\n    SkBool8  fRRectOrOvalIsCCW;\n    uint8_t  fRRectOrOvalStartIdx;\n    uint8_t  fSegmentMask;\n\n    friend class PathRefTest_Private;\n    friend class ForceIsRRect_Private; // unit test isRRect\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkSafe32.h",
    "content": "/*\n * Copyright 2018 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSafe32_DEFINED\n#define SkSafe32_DEFINED\n\n#include \"SkTypes.h\"\n\nstatic constexpr int32_t Sk64_pin_to_s32(int64_t x) {\n    return x < SK_MinS32 ? SK_MinS32 : (x > SK_MaxS32 ? SK_MaxS32 : (int32_t)x);\n}\n\nstatic constexpr int32_t Sk32_sat_add(int32_t a, int32_t b) {\n    return Sk64_pin_to_s32((int64_t)a + (int64_t)b);\n}\n\nstatic constexpr int32_t Sk32_sat_sub(int32_t a, int32_t b) {\n    return Sk64_pin_to_s32((int64_t)a - (int64_t)b);\n}\n\n// To avoid UBSAN complaints about 2's compliment overflows\n//\nstatic constexpr int32_t Sk32_can_overflow_add(int32_t a, int32_t b) {\n    return (int32_t)((uint32_t)a + (uint32_t)b);\n}\nstatic constexpr int32_t Sk32_can_overflow_sub(int32_t a, int32_t b) {\n    return (int32_t)((uint32_t)a - (uint32_t)b);\n}\n\n#endif\n"
  },
  {
    "path": "include/private/SkSafe_math.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSafe_math_DEFINED\n#define SkSafe_math_DEFINED\n\n// This file protects against known bugs in ucrt\\math.h.\n// Namely, that header defines inline methods without marking them static,\n// which makes it very easy to cause ODR violations and ensuing chaos.\n//\n// TODO: other headers?  Here are some potential problem headers:\n// $ grep -R __inline * | grep -v static | cut -f 1 -d: | sort | uniq\n//   corecrt.h\n//   corecrt_stdio_config.h\n//   ctype.h\n//   fenv.h\n//   locale.h\n//   malloc.h\n//   math.h\n//   tchar.h\n//   wchar.h\n// I took a quick look through other headers outside math.h.\n// Nothing looks anywhere near as likely to be used by Skia as math.h.\n\n#if defined(_MSC_VER) && !defined(_INC_MATH)\n    // Our strategy here is to simply inject \"static\" into the headers\n    // where it should have been written, just before __inline.\n    //\n    // Most inline-but-not-static methods in math.h are 32-bit only,\n    // but not all of them (see frexpf, hypothf, ldexpf...).  So to\n    // be safe, 32- and 64-bit builds both get this treatment.\n\n    #define __inline static __inline\n    #include <math.h>\n    #undef __inline\n\n    #if !defined(_INC_MATH)\n        #error Hmm.  Looks like math.h has changed its header guards.\n    #endif\n\n    #define INC_MATH_IS_SAFE_NOW\n\n#else\n    #include <math.h>\n\n#endif\n\n#endif//SkSafe_math_DEFINED\n"
  },
  {
    "path": "include/private/SkSemaphore.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSemaphore_DEFINED\n#define SkSemaphore_DEFINED\n\n#include \"../private/SkOnce.h\"\n#include \"SkTypes.h\"\n#include <atomic>\n\nclass SkBaseSemaphore {\npublic:\n    constexpr SkBaseSemaphore(int count = 0)\n        : fCount(count), fOSSemaphore(nullptr) {}\n\n    // Increment the counter n times.\n    // Generally it's better to call signal(n) instead of signal() n times.\n    void signal(int n = 1);\n\n    // Decrement the counter by 1,\n    // then if the counter is < 0, sleep this thread until the counter is >= 0.\n    void wait();\n\n    // If the counter is positive, decrement it by 1 and return true, otherwise return false.\n    bool try_wait();\n\n    // SkBaseSemaphore has no destructor.  Call this to clean it up.\n    void cleanup();\n\nprivate:\n    // This implementation follows the general strategy of\n    //     'A Lightweight Semaphore with Partial Spinning'\n    // found here\n    //     http://preshing.com/20150316/semaphores-are-surprisingly-versatile/\n    // That article (and entire blog) are very much worth reading.\n    //\n    // We wrap an OS-provided semaphore with a user-space atomic counter that\n    // lets us avoid interacting with the OS semaphore unless strictly required:\n    // moving the count from >=0 to <0 or vice-versa, i.e. sleeping or waking threads.\n    struct OSSemaphore;\n\n    void osSignal(int n);\n    void osWait();\n\n    std::atomic<int> fCount;\n    SkOnce           fOSSemaphoreOnce;\n    OSSemaphore*     fOSSemaphore;\n};\n\nclass SkSemaphore : public SkBaseSemaphore {\npublic:\n    using SkBaseSemaphore::SkBaseSemaphore;\n    ~SkSemaphore() { this->cleanup(); }\n};\n\ninline void SkBaseSemaphore::signal(int n) {\n    int prev = fCount.fetch_add(n, std::memory_order_release);\n\n    // We only want to call the OS semaphore when our logical count crosses\n    // from <0 to >=0 (when we need to wake sleeping threads).\n    //\n    // This is easiest to think about with specific examples of prev and n.\n    // If n == 5 and prev == -3, there are 3 threads sleeping and we signal\n    // SkTMin(-(-3), 5) == 3 times on the OS semaphore, leaving the count at 2.\n    //\n    // If prev >= 0, no threads are waiting, SkTMin(-prev, n) is always <= 0,\n    // so we don't call the OS semaphore, leaving the count at (prev + n).\n    int toSignal = SkTMin(-prev, n);\n    if (toSignal > 0) {\n        this->osSignal(toSignal);\n    }\n}\n\ninline void SkBaseSemaphore::wait() {\n    // Since this fetches the value before the subtract, zero and below means that there are no\n    // resources left, so the thread needs to wait.\n    if (fCount.fetch_sub(1, std::memory_order_acquire) <= 0) {\n        this->osWait();\n    }\n}\n\n#endif//SkSemaphore_DEFINED\n"
  },
  {
    "path": "include/private/SkShadowFlags.h",
    "content": "/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkShadowFlags_DEFINED\n#define SkShadowFlags_DEFINED\n\n// A set of flags shared between the SkAmbientShadowMaskFilter and the SkSpotShadowMaskFilter\nenum SkShadowFlags {\n    kNone_ShadowFlag = 0x00,\n    /** The occluding object is not opaque. Knowing that the occluder is opaque allows\n    * us to cull shadow geometry behind it and improve performance. */\n    kTransparentOccluder_ShadowFlag = 0x01,\n    /** Don't try to use analytic shadows. */\n    kGeometricOnly_ShadowFlag = 0x02,\n    /** mask for all shadow flags */\n    kAll_ShadowFlag = 0x03\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkSpinlock.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSpinlock_DEFINED\n#define SkSpinlock_DEFINED\n\n#include \"SkTypes.h\"\n#include <atomic>\n\nclass SkSpinlock {\npublic:\n    constexpr SkSpinlock() = default;\n\n    void acquire() {\n        // To act as a mutex, we need an acquire barrier when we acquire the lock.\n        if (fLocked.exchange(true, std::memory_order_acquire)) {\n            // Lock was contended.  Fall back to an out-of-line spin loop.\n            this->contendedAcquire();\n        }\n    }\n\n    // Acquire the lock or fail (quickly). Lets the caller decide to do something other than wait.\n    bool tryAcquire() {\n        // To act as a mutex, we need an acquire barrier when we acquire the lock.\n        if (fLocked.exchange(true, std::memory_order_acquire)) {\n            // Lock was contended. Let the caller decide what to do.\n            return false;\n        }\n        return true;\n    }\n\n    void release() {\n        // To act as a mutex, we need a release barrier when we release the lock.\n        fLocked.store(false, std::memory_order_release);\n    }\n\nprivate:\n    SK_API void contendedAcquire();\n\n    std::atomic<bool> fLocked{false};\n};\n\n#endif//SkSpinlock_DEFINED\n"
  },
  {
    "path": "include/private/SkTArray.h",
    "content": "/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTArray_DEFINED\n#define SkTArray_DEFINED\n\n#include \"../private/SkSafe32.h\"\n#include \"../private/SkTLogic.h\"\n#include \"../private/SkTemplates.h\"\n#include \"SkTypes.h\"\n\n#include <new>\n#include <utility>\n\n/** When MEM_MOVE is true T will be bit copied when moved.\n    When MEM_MOVE is false, T will be copy constructed / destructed.\n    In all cases T will be default-initialized on allocation,\n    and its destructor will be called from this object's destructor.\n*/\ntemplate <typename T, bool MEM_MOVE = false> class SkTArray {\npublic:\n    /**\n     * Creates an empty array with no initial storage\n     */\n    SkTArray() { this->init(); }\n\n    /**\n     * Creates an empty array that will preallocate space for reserveCount\n     * elements.\n     */\n    explicit SkTArray(int reserveCount) { this->init(0, reserveCount); }\n\n    /**\n     * Copies one array to another. The new array will be heap allocated.\n     */\n    explicit SkTArray(const SkTArray& that) {\n        this->init(that.fCount);\n        this->copy(that.fItemArray);\n    }\n\n    explicit SkTArray(SkTArray&& that) {\n        // TODO: If 'that' owns its memory why don't we just steal the pointer?\n        this->init(that.fCount);\n        that.move(fMemArray);\n        that.fCount = 0;\n    }\n\n    /**\n     * Creates a SkTArray by copying contents of a standard C array. The new\n     * array will be heap allocated. Be careful not to use this constructor\n     * when you really want the (void*, int) version.\n     */\n    SkTArray(const T* array, int count) {\n        this->init(count);\n        this->copy(array);\n    }\n\n    SkTArray& operator=(const SkTArray& that) {\n        if (this == &that) {\n            return *this;\n        }\n        for (int i = 0; i < fCount; ++i) {\n            fItemArray[i].~T();\n        }\n        fCount = 0;\n        this->checkRealloc(that.count());\n        fCount = that.count();\n        this->copy(that.fItemArray);\n        return *this;\n    }\n    SkTArray& operator=(SkTArray&& that) {\n        if (this == &that) {\n            return *this;\n        }\n        for (int i = 0; i < fCount; ++i) {\n            fItemArray[i].~T();\n        }\n        fCount = 0;\n        this->checkRealloc(that.count());\n        fCount = that.count();\n        that.move(fMemArray);\n        that.fCount = 0;\n        return *this;\n    }\n\n    ~SkTArray() {\n        for (int i = 0; i < fCount; ++i) {\n            fItemArray[i].~T();\n        }\n        if (fOwnMemory) {\n            sk_free(fMemArray);\n        }\n    }\n\n    /**\n     * Resets to count() == 0 and resets any reserve count.\n     */\n    void reset() {\n        this->pop_back_n(fCount);\n        fReserved = false;\n    }\n\n    /**\n     * Resets to count() = n newly constructed T objects and resets any reserve count.\n     */\n    void reset(int n) {\n        SkASSERT(n >= 0);\n        for (int i = 0; i < fCount; ++i) {\n            fItemArray[i].~T();\n        }\n        // Set fCount to 0 before calling checkRealloc so that no elements are moved.\n        fCount = 0;\n        this->checkRealloc(n);\n        fCount = n;\n        for (int i = 0; i < fCount; ++i) {\n            new (fItemArray + i) T;\n        }\n        fReserved = false;\n    }\n\n    /**\n     * Resets to a copy of a C array and resets any reserve count.\n     */\n    void reset(const T* array, int count) {\n        for (int i = 0; i < fCount; ++i) {\n            fItemArray[i].~T();\n        }\n        fCount = 0;\n        this->checkRealloc(count);\n        fCount = count;\n        this->copy(array);\n        fReserved = false;\n    }\n\n    /**\n     * Ensures there is enough reserved space for n additional elements. The is guaranteed at least\n     * until the array size grows above n and subsequently shrinks below n, any version of reset()\n     * is called, or reserve() is called again.\n     */\n    void reserve(int n) {\n        SkASSERT(n >= 0);\n        if (n > 0) {\n            this->checkRealloc(n);\n            fReserved = fOwnMemory;\n        } else {\n            fReserved = false;\n        }\n    }\n\n    void removeShuffle(int n) {\n        SkASSERT(n < fCount);\n        int newCount = fCount - 1;\n        fCount = newCount;\n        fItemArray[n].~T();\n        if (n != newCount) {\n            this->move(n, newCount);\n        }\n    }\n\n    /**\n     * Number of elements in the array.\n     */\n    int count() const { return fCount; }\n\n    /**\n     * Is the array empty.\n     */\n    bool empty() const { return !fCount; }\n\n    /**\n     * Adds 1 new default-initialized T value and returns it by reference. Note\n     * the reference only remains valid until the next call that adds or removes\n     * elements.\n     */\n    T& push_back() {\n        void* newT = this->push_back_raw(1);\n        return *new (newT) T;\n    }\n\n    /**\n     * Version of above that uses a copy constructor to initialize the new item\n     */\n    T& push_back(const T& t) {\n        void* newT = this->push_back_raw(1);\n        return *new (newT) T(t);\n    }\n\n    /**\n     * Version of above that uses a move constructor to initialize the new item\n     */\n    T& push_back(T&& t) {\n        void* newT = this->push_back_raw(1);\n        return *new (newT) T(std::move(t));\n    }\n\n    /**\n     *  Construct a new T at the back of this array.\n     */\n    template<class... Args> T& emplace_back(Args&&... args) {\n        void* newT = this->push_back_raw(1);\n        return *new (newT) T(std::forward<Args>(args)...);\n    }\n\n    /**\n     * Allocates n more default-initialized T values, and returns the address of\n     * the start of that new range. Note: this address is only valid until the\n     * next API call made on the array that might add or remove elements.\n     */\n    T* push_back_n(int n) {\n        SkASSERT(n >= 0);\n        void* newTs = this->push_back_raw(n);\n        for (int i = 0; i < n; ++i) {\n            new (static_cast<char*>(newTs) + i * sizeof(T)) T;\n        }\n        return static_cast<T*>(newTs);\n    }\n\n    /**\n     * Version of above that uses a copy constructor to initialize all n items\n     * to the same T.\n     */\n    T* push_back_n(int n, const T& t) {\n        SkASSERT(n >= 0);\n        void* newTs = this->push_back_raw(n);\n        for (int i = 0; i < n; ++i) {\n            new (static_cast<char*>(newTs) + i * sizeof(T)) T(t);\n        }\n        return static_cast<T*>(newTs);\n    }\n\n    /**\n     * Version of above that uses a copy constructor to initialize the n items\n     * to separate T values.\n     */\n    T* push_back_n(int n, const T t[]) {\n        SkASSERT(n >= 0);\n        this->checkRealloc(n);\n        for (int i = 0; i < n; ++i) {\n            new (fItemArray + fCount + i) T(t[i]);\n        }\n        fCount += n;\n        return fItemArray + fCount - n;\n    }\n\n    /**\n     * Version of above that uses the move constructor to set n items.\n     */\n    T* move_back_n(int n, T* t) {\n        SkASSERT(n >= 0);\n        this->checkRealloc(n);\n        for (int i = 0; i < n; ++i) {\n            new (fItemArray + fCount + i) T(std::move(t[i]));\n        }\n        fCount += n;\n        return fItemArray + fCount - n;\n    }\n\n    /**\n     * Removes the last element. Not safe to call when count() == 0.\n     */\n    void pop_back() {\n        SkASSERT(fCount > 0);\n        --fCount;\n        fItemArray[fCount].~T();\n        this->checkRealloc(0);\n    }\n\n    /**\n     * Removes the last n elements. Not safe to call when count() < n.\n     */\n    void pop_back_n(int n) {\n        SkASSERT(n >= 0);\n        SkASSERT(fCount >= n);\n        fCount -= n;\n        for (int i = 0; i < n; ++i) {\n            fItemArray[fCount + i].~T();\n        }\n        this->checkRealloc(0);\n    }\n\n    /**\n     * Pushes or pops from the back to resize. Pushes will be default\n     * initialized.\n     */\n    void resize_back(int newCount) {\n        SkASSERT(newCount >= 0);\n\n        if (newCount > fCount) {\n            this->push_back_n(newCount - fCount);\n        } else if (newCount < fCount) {\n            this->pop_back_n(fCount - newCount);\n        }\n    }\n\n    /** Swaps the contents of this array with that array. Does a pointer swap if possible,\n        otherwise copies the T values. */\n    void swap(SkTArray* that) {\n        if (this == that) {\n            return;\n        }\n        if (fOwnMemory && that->fOwnMemory) {\n            SkTSwap(fItemArray, that->fItemArray);\n            SkTSwap(fCount, that->fCount);\n            SkTSwap(fAllocCount, that->fAllocCount);\n        } else {\n            // This could be more optimal...\n            SkTArray copy(std::move(*that));\n            *that = std::move(*this);\n            *this = std::move(copy);\n        }\n    }\n\n    T* begin() {\n        return fItemArray;\n    }\n    const T* begin() const {\n        return fItemArray;\n    }\n    T* end() {\n        return fItemArray ? fItemArray + fCount : nullptr;\n    }\n    const T* end() const {\n        return fItemArray ? fItemArray + fCount : nullptr;\n    }\n\n   /**\n     * Get the i^th element.\n     */\n    T& operator[] (int i) {\n        SkASSERT(i < fCount);\n        SkASSERT(i >= 0);\n        return fItemArray[i];\n    }\n\n    const T& operator[] (int i) const {\n        SkASSERT(i < fCount);\n        SkASSERT(i >= 0);\n        return fItemArray[i];\n    }\n\n    /**\n     * equivalent to operator[](0)\n     */\n    T& front() { SkASSERT(fCount > 0); return fItemArray[0];}\n\n    const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}\n\n    /**\n     * equivalent to operator[](count() - 1)\n     */\n    T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}\n\n    const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}\n\n    /**\n     * equivalent to operator[](count()-1-i)\n     */\n    T& fromBack(int i) {\n        SkASSERT(i >= 0);\n        SkASSERT(i < fCount);\n        return fItemArray[fCount - i - 1];\n    }\n\n    const T& fromBack(int i) const {\n        SkASSERT(i >= 0);\n        SkASSERT(i < fCount);\n        return fItemArray[fCount - i - 1];\n    }\n\n    bool operator==(const SkTArray<T, MEM_MOVE>& right) const {\n        int leftCount = this->count();\n        if (leftCount != right.count()) {\n            return false;\n        }\n        for (int index = 0; index < leftCount; ++index) {\n            if (fItemArray[index] != right.fItemArray[index]) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    bool operator!=(const SkTArray<T, MEM_MOVE>& right) const {\n        return !(*this == right);\n    }\n\n    inline int allocCntForTest() const;\n\nprotected:\n    /**\n     * Creates an empty array that will use the passed storage block until it\n     * is insufficiently large to hold the entire array.\n     */\n    template <int N>\n    SkTArray(SkAlignedSTStorage<N,T>* storage) {\n        this->initWithPreallocatedStorage(0, storage->get(), N);\n    }\n\n    /**\n     * Copy another array, using preallocated storage if preAllocCount >=\n     * array.count(). Otherwise storage will only be used when array shrinks\n     * to fit.\n     */\n    template <int N>\n    SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {\n        this->initWithPreallocatedStorage(array.fCount, storage->get(), N);\n        this->copy(array.fItemArray);\n    }\n\n    /**\n     * Move another array, using preallocated storage if preAllocCount >=\n     * array.count(). Otherwise storage will only be used when array shrinks\n     * to fit.\n     */\n    template <int N>\n    SkTArray(SkTArray&& array, SkAlignedSTStorage<N,T>* storage) {\n        this->initWithPreallocatedStorage(array.fCount, storage->get(), N);\n        array.move(fMemArray);\n        array.fCount = 0;\n    }\n\n    /**\n     * Copy a C array, using preallocated storage if preAllocCount >=\n     * count. Otherwise storage will only be used when array shrinks\n     * to fit.\n     */\n    template <int N>\n    SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {\n        this->initWithPreallocatedStorage(count, storage->get(), N);\n        this->copy(array);\n    }\n\nprivate:\n    void init(int count = 0, int reserveCount = 0) {\n        SkASSERT(count >= 0);\n        SkASSERT(reserveCount >= 0);\n        fCount = count;\n        if (!count && !reserveCount) {\n            fAllocCount = 0;\n            fMemArray = nullptr;\n            fOwnMemory = true;\n            fReserved = false;\n        } else {\n            fAllocCount = SkTMax(count, SkTMax(kMinHeapAllocCount, reserveCount));\n            fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));\n            fOwnMemory = true;\n            fReserved = reserveCount > 0;\n        }\n    }\n\n    void initWithPreallocatedStorage(int count, void* preallocStorage, int preallocCount) {\n        SkASSERT(count >= 0);\n        SkASSERT(preallocCount > 0);\n        SkASSERT(preallocStorage);\n        fCount = count;\n        fMemArray = nullptr;\n        fReserved = false;\n        if (count > preallocCount) {\n            fAllocCount = SkTMax(count, kMinHeapAllocCount);\n            fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));\n            fOwnMemory = true;\n        } else {\n            fAllocCount = preallocCount;\n            fMemArray = preallocStorage;\n            fOwnMemory = false;\n        }\n    }\n\n    /** In the following move and copy methods, 'dst' is assumed to be uninitialized raw storage.\n     *  In the following move methods, 'src' is destroyed leaving behind uninitialized raw storage.\n     */\n    void copy(const T* src) {\n        // Some types may be trivially copyable, in which case we *could* use memcopy; but\n        // MEM_MOVE == true implies that the type is trivially movable, and not necessarily\n        // trivially copyable (think sk_sp<>).  So short of adding another template arg, we\n        // must be conservative and use copy construction.\n        for (int i = 0; i < fCount; ++i) {\n            new (fItemArray + i) T(src[i]);\n        }\n    }\n\n    template <bool E = MEM_MOVE> SK_WHEN(E, void) move(int dst, int src) {\n        memcpy(&fItemArray[dst], &fItemArray[src], sizeof(T));\n    }\n    template <bool E = MEM_MOVE> SK_WHEN(E, void) move(void* dst) {\n        sk_careful_memcpy(dst, fMemArray, fCount * sizeof(T));\n    }\n\n    template <bool E = MEM_MOVE> SK_WHEN(!E, void) move(int dst, int src) {\n        new (&fItemArray[dst]) T(std::move(fItemArray[src]));\n        fItemArray[src].~T();\n    }\n    template <bool E = MEM_MOVE> SK_WHEN(!E, void) move(void* dst) {\n        for (int i = 0; i < fCount; ++i) {\n            new (static_cast<char*>(dst) + sizeof(T) * i) T(std::move(fItemArray[i]));\n            fItemArray[i].~T();\n        }\n    }\n\n    static constexpr int kMinHeapAllocCount = 8;\n\n    // Helper function that makes space for n objects, adjusts the count, but does not initialize\n    // the new objects.\n    void* push_back_raw(int n) {\n        this->checkRealloc(n);\n        void* ptr = fItemArray + fCount;\n        fCount += n;\n        return ptr;\n    }\n\n    void checkRealloc(int delta) {\n        SkASSERT(fCount >= 0);\n        SkASSERT(fAllocCount >= 0);\n        SkASSERT(-delta <= fCount);\n\n        // Move into 64bit math temporarily, to avoid local overflows\n        int64_t newCount = fCount + delta;\n\n        // We allow fAllocCount to be in the range [newCount, 3*newCount]. We also never shrink\n        // when we're currently using preallocated memory, would allocate less than\n        // kMinHeapAllocCount, or a reserve count was specified that has yet to be exceeded.\n        bool mustGrow = newCount > fAllocCount;\n        bool shouldShrink = fAllocCount > 3 * newCount && fOwnMemory && !fReserved;\n        if (!mustGrow && !shouldShrink) {\n            return;\n        }\n\n\n        // Whether we're growing or shrinking, we leave at least 50% extra space for future growth.\n        int64_t newAllocCount = newCount + ((newCount + 1) >> 1);\n        // Align the new allocation count to kMinHeapAllocCount.\n        static_assert(SkIsPow2(kMinHeapAllocCount), \"min alloc count not power of two.\");\n        newAllocCount = (newAllocCount + (kMinHeapAllocCount - 1)) & ~(kMinHeapAllocCount - 1);\n        // At small sizes the old and new alloc count can both be kMinHeapAllocCount.\n        if (newAllocCount == fAllocCount) {\n            return;\n        }\n\n        fAllocCount = Sk64_pin_to_s32(newAllocCount);\n        SkASSERT(fAllocCount >= newCount);\n        void* newMemArray = sk_malloc_throw(fAllocCount, sizeof(T));\n        this->move(newMemArray);\n        if (fOwnMemory) {\n            sk_free(fMemArray);\n\n        }\n        fMemArray = newMemArray;\n        fOwnMemory = true;\n        fReserved = false;\n    }\n\n    union {\n        T*       fItemArray;\n        void*    fMemArray;\n    };\n    int fCount;\n    int fAllocCount;\n    bool fOwnMemory : 1;\n    bool fReserved : 1;\n};\n\ntemplate<typename T, bool MEM_MOVE> constexpr int SkTArray<T, MEM_MOVE>::kMinHeapAllocCount;\n\n/**\n * Subclass of SkTArray that contains a preallocated memory block for the array.\n */\ntemplate <int N, typename T, bool MEM_MOVE= false>\nclass SkSTArray : public SkTArray<T, MEM_MOVE> {\nprivate:\n    typedef SkTArray<T, MEM_MOVE> INHERITED;\n\npublic:\n    SkSTArray() : INHERITED(&fStorage) {\n    }\n\n    SkSTArray(const SkSTArray& array)\n        : INHERITED(array, &fStorage) {\n    }\n\n    SkSTArray(SkSTArray&& array)\n        : INHERITED(std::move(array), &fStorage) {\n    }\n\n    explicit SkSTArray(const INHERITED& array)\n        : INHERITED(array, &fStorage) {\n    }\n\n    explicit SkSTArray(INHERITED&& array)\n        : INHERITED(std::move(array), &fStorage) {\n    }\n\n    explicit SkSTArray(int reserveCount)\n        : INHERITED(reserveCount) {\n    }\n\n    SkSTArray(const T* array, int count)\n        : INHERITED(array, count, &fStorage) {\n    }\n\n    SkSTArray& operator=(const SkSTArray& array) {\n        INHERITED::operator=(array);\n        return *this;\n    }\n\n    SkSTArray& operator=(SkSTArray&& array) {\n        INHERITED::operator=(std::move(array));\n        return *this;\n    }\n\n    SkSTArray& operator=(const INHERITED& array) {\n        INHERITED::operator=(array);\n        return *this;\n    }\n\n    SkSTArray& operator=(INHERITED&& array) {\n        INHERITED::operator=(std::move(array));\n        return *this;\n    }\n\nprivate:\n    SkAlignedSTStorage<N,T> fStorage;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkTDArray.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkTDArray_DEFINED\n#define SkTDArray_DEFINED\n\n#include \"SkTypes.h\"\n#include \"SkMalloc.h\"\n\ntemplate <typename T> class SkTDArray {\npublic:\n    SkTDArray() : fArray(nullptr), fReserve(0), fCount(0) {}\n    SkTDArray(const T src[], int count) {\n        SkASSERT(src || count == 0);\n\n        fReserve = fCount = 0;\n        fArray = nullptr;\n        if (count) {\n            fArray = (T*)sk_malloc_throw(count * sizeof(T));\n            memcpy(fArray, src, sizeof(T) * count);\n            fReserve = fCount = count;\n        }\n    }\n    SkTDArray(const SkTDArray<T>& src) : fArray(nullptr), fReserve(0), fCount(0) {\n        SkTDArray<T> tmp(src.fArray, src.fCount);\n        this->swap(tmp);\n    }\n    SkTDArray(SkTDArray<T>&& src) : fArray(nullptr), fReserve(0), fCount(0) {\n        this->swap(src);\n    }\n    ~SkTDArray() {\n        sk_free(fArray);\n    }\n\n    SkTDArray<T>& operator=(const SkTDArray<T>& src) {\n        if (this != &src) {\n            if (src.fCount > fReserve) {\n                SkTDArray<T> tmp(src.fArray, src.fCount);\n                this->swap(tmp);\n            } else {\n                sk_careful_memcpy(fArray, src.fArray, sizeof(T) * src.fCount);\n                fCount = src.fCount;\n            }\n        }\n        return *this;\n    }\n    SkTDArray<T>& operator=(SkTDArray<T>&& src) {\n        if (this != &src) {\n            this->swap(src);\n            src.reset();\n        }\n        return *this;\n    }\n\n    friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {\n        return  a.fCount == b.fCount &&\n                (a.fCount == 0 ||\n                 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));\n    }\n    friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {\n        return !(a == b);\n    }\n\n    void swap(SkTDArray<T>& other) {\n        SkTSwap(fArray, other.fArray);\n        SkTSwap(fReserve, other.fReserve);\n        SkTSwap(fCount, other.fCount);\n    }\n\n    bool isEmpty() const { return fCount == 0; }\n\n    /**\n     *  Return the number of elements in the array\n     */\n    int count() const { return fCount; }\n\n    /**\n     *  Return the total number of elements allocated.\n     *  reserved() - count() gives you the number of elements you can add\n     *  without causing an allocation.\n     */\n    int reserved() const { return fReserve; }\n\n    /**\n     *  return the number of bytes in the array: count * sizeof(T)\n     */\n    size_t bytes() const { return fCount * sizeof(T); }\n\n    T*  begin() { return fArray; }\n    const T*  begin() const { return fArray; }\n    T*  end() { return fArray ? fArray + fCount : nullptr; }\n    const T*  end() const { return fArray ? fArray + fCount : nullptr; }\n\n    T&  operator[](int index) {\n        SkASSERT(index < fCount);\n        return fArray[index];\n    }\n    const T&  operator[](int index) const {\n        SkASSERT(index < fCount);\n        return fArray[index];\n    }\n\n    T&  getAt(int index)  {\n        return (*this)[index];\n    }\n    const T&  getAt(int index) const {\n        return (*this)[index];\n    }\n\n    void reset() {\n        if (fArray) {\n            sk_free(fArray);\n            fArray = nullptr;\n            fReserve = fCount = 0;\n        } else {\n            SkASSERT(fReserve == 0 && fCount == 0);\n        }\n    }\n\n    void rewind() {\n        // same as setCount(0)\n        fCount = 0;\n    }\n\n    /**\n     *  Sets the number of elements in the array.\n     *  If the array does not have space for count elements, it will increase\n     *  the storage allocated to some amount greater than that required.\n     *  It will never shrink the storage.\n     */\n    void setCount(int count) {\n        SkASSERT(count >= 0);\n        if (count > fReserve) {\n            this->resizeStorageToAtLeast(count);\n        }\n        fCount = count;\n    }\n\n    void setReserve(int reserve) {\n        SkASSERT(reserve >= 0);\n        if (reserve > fReserve) {\n            this->resizeStorageToAtLeast(reserve);\n        }\n    }\n\n    T* prepend() {\n        this->adjustCount(1);\n        memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));\n        return fArray;\n    }\n\n    T* append() {\n        return this->append(1, nullptr);\n    }\n    T* append(int count, const T* src = nullptr) {\n        int oldCount = fCount;\n        if (count)  {\n            SkASSERT(src == nullptr || fArray == nullptr ||\n                    src + count <= fArray || fArray + oldCount <= src);\n\n            this->adjustCount(count);\n            if (src) {\n                memcpy(fArray + oldCount, src, sizeof(T) * count);\n            }\n        }\n        return fArray + oldCount;\n    }\n\n    T* appendClear() {\n        T* result = this->append();\n        *result = 0;\n        return result;\n    }\n\n    T* insert(int index) {\n        return this->insert(index, 1, nullptr);\n    }\n    T* insert(int index, int count, const T* src = nullptr) {\n        SkASSERT(count);\n        SkASSERT(index <= fCount);\n        size_t oldCount = fCount;\n        this->adjustCount(count);\n        T* dst = fArray + index;\n        memmove(dst + count, dst, sizeof(T) * (oldCount - index));\n        if (src) {\n            memcpy(dst, src, sizeof(T) * count);\n        }\n        return dst;\n    }\n\n    void remove(int index, int count = 1) {\n        SkASSERT(index + count <= fCount);\n        fCount = fCount - count;\n        memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));\n    }\n\n    void removeShuffle(int index) {\n        SkASSERT(index < fCount);\n        int newCount = fCount - 1;\n        fCount = newCount;\n        if (index != newCount) {\n            memcpy(fArray + index, fArray + newCount, sizeof(T));\n        }\n    }\n\n    int find(const T& elem) const {\n        const T* iter = fArray;\n        const T* stop = fArray + fCount;\n\n        for (; iter < stop; iter++) {\n            if (*iter == elem) {\n                return SkToInt(iter - fArray);\n            }\n        }\n        return -1;\n    }\n\n    int rfind(const T& elem) const {\n        const T* iter = fArray + fCount;\n        const T* stop = fArray;\n\n        while (iter > stop) {\n            if (*--iter == elem) {\n                return SkToInt(iter - stop);\n            }\n        }\n        return -1;\n    }\n\n    /**\n     * Returns true iff the array contains this element.\n     */\n    bool contains(const T& elem) const {\n        return (this->find(elem) >= 0);\n    }\n\n    /**\n     * Copies up to max elements into dst. The number of items copied is\n     * capped by count - index. The actual number copied is returned.\n     */\n    int copyRange(T* dst, int index, int max) const {\n        SkASSERT(max >= 0);\n        SkASSERT(!max || dst);\n        if (index >= fCount) {\n            return 0;\n        }\n        int count = SkMin32(max, fCount - index);\n        memcpy(dst, fArray + index, sizeof(T) * count);\n        return count;\n    }\n\n    void copy(T* dst) const {\n        this->copyRange(dst, 0, fCount);\n    }\n\n    // routines to treat the array like a stack\n    T*       push() { return this->append(); }\n    void     push(const T& elem) { *this->append() = elem; }\n    const T& top() const { return (*this)[fCount - 1]; }\n    T&       top() { return (*this)[fCount - 1]; }\n    void     pop(T* elem) { SkASSERT(fCount > 0); if (elem) *elem = (*this)[fCount - 1]; --fCount; }\n    void     pop() { SkASSERT(fCount > 0); --fCount; }\n\n    void deleteAll() {\n        T*  iter = fArray;\n        T*  stop = fArray + fCount;\n        while (iter < stop) {\n            delete *iter;\n            iter += 1;\n        }\n        this->reset();\n    }\n\n    void freeAll() {\n        T*  iter = fArray;\n        T*  stop = fArray + fCount;\n        while (iter < stop) {\n            sk_free(*iter);\n            iter += 1;\n        }\n        this->reset();\n    }\n\n    void unrefAll() {\n        T*  iter = fArray;\n        T*  stop = fArray + fCount;\n        while (iter < stop) {\n            (*iter)->unref();\n            iter += 1;\n        }\n        this->reset();\n    }\n\n    void safeUnrefAll() {\n        T*  iter = fArray;\n        T*  stop = fArray + fCount;\n        while (iter < stop) {\n            SkSafeUnref(*iter);\n            iter += 1;\n        }\n        this->reset();\n    }\n\n    void visitAll(void visitor(T&)) {\n        T* stop = this->end();\n        for (T* curr = this->begin(); curr < stop; curr++) {\n            if (*curr) {\n                visitor(*curr);\n            }\n        }\n    }\n\n#ifdef SK_DEBUG\n    void validate() const {\n        SkASSERT((fReserve == 0 && fArray == nullptr) ||\n                 (fReserve > 0 && fArray != nullptr));\n        SkASSERT(fCount <= fReserve);\n    }\n#endif\n\n    void shrinkToFit() {\n        fReserve = fCount;\n        fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T));\n    }\n\nprivate:\n    T*      fArray;\n    int     fReserve;\n    int     fCount;\n\n    /**\n     *  Adjusts the number of elements in the array.\n     *  This is the same as calling setCount(count() + delta).\n     */\n    void adjustCount(int delta) {\n        SkASSERT(delta > 0);\n\n        // We take care to avoid overflow here.\n        // The sum of fCount and delta is at most 4294967294, which fits fine in uint32_t.\n        uint32_t count = (uint32_t)fCount + (uint32_t)delta;\n        SkASSERT_RELEASE( SkTFitsIn<int>(count) );\n\n        this->setCount(SkTo<int>(count));\n    }\n\n    /**\n     *  Increase the storage allocation such that it can hold (fCount + extra)\n     *  elements.\n     *  It never shrinks the allocation, and it may increase the allocation by\n     *  more than is strictly required, based on a private growth heuristic.\n     *\n     *  note: does NOT modify fCount\n     */\n    void resizeStorageToAtLeast(int count) {\n        SkASSERT(count > fReserve);\n\n        // We take care to avoid overflow here.\n        // The maximum value we can get for reserve here is 2684354563, which fits in uint32_t.\n        uint32_t reserve = (uint32_t)count + 4;\n        reserve += reserve / 4;\n        SkASSERT_RELEASE( SkTFitsIn<int>(reserve) );\n\n        fReserve = SkTo<int>(reserve);\n        fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T));\n    }\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkTFitsIn.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTFitsIn_DEFINED\n#define SkTFitsIn_DEFINED\n\n#include \"../private/SkTLogic.h\"\n#include <limits>\n#include <type_traits>\n\n/**\n * In C++ an unsigned to signed cast where the source value cannot be represented in the destination\n * type results in an implementation defined destination value. Unlike C, C++ does not allow a trap.\n * This makes \"(S)(D)s == s\" a possibly useful test. However, there are two cases where this is\n * incorrect:\n *\n * when testing if a value of a smaller signed type can be represented in a larger unsigned type\n * (int8_t)(uint16_t)-1 == -1 => (int8_t)0xFFFF == -1 => [implementation defined] == -1\n *\n * when testing if a value of a larger unsigned type can be represented in a smaller signed type\n * (uint16_t)(int8_t)0xFFFF == 0xFFFF => (uint16_t)-1 == 0xFFFF => 0xFFFF == 0xFFFF => true.\n *\n * Consider the cases:\n * u = unsigned, s = signed, X = more digits, x = less digits\n * ux -> uX: (ux)(uX)ux == ux, trivially true\n * uX -> ux: (uX)(ux)uX == uX, both casts well defined, test works\n * sx -> sX: (sx)(sX)sx == sx, trivially true\n * sX -> sx: (sX)(sx)sX == sX, first cast implementation value, second cast defined, test works\n * sx -> uX: (sx)(uX)sx == sx, this is bad, the second cast results in implementation defined value\n * sX -> ux: (sX)(ux)sX == sX, the second cast is required to prevent promotion of rhs to unsigned\n * ux -> sX: (ux)(sX)ux == ux, trivially true\n * uX -> sx: (uX)(sx)uX == uX, this is bad,\n *                             first cast results in implementation defined value,\n *                             second cast is defined. However, this creates false positives\n *                             uint16_t x = 0xFFFF\n *                                (uint16_t)(int8_t)x == x\n *                             => (uint16_t)-1        == x\n *                             => 0xFFFF              == x\n *                             => true\n *\n * So for the eight cases three are trivially true, three more are valid casts, and two are special.\n * The two 'full' checks which otherwise require two comparisons are valid cast checks.\n * The two remaining checks uX -> sx [uX < max(sx)] and sx -> uX [sx > 0] can be done with one op.\n */\n\nnamespace sktfitsin {\nnamespace Private {\n\n/** SkTMux::type = (a && b) ? Both : (a) ? A : (b) ? B : Neither; */\ntemplate <bool a, bool b, typename Both, typename A, typename B, typename Neither>\nstruct SkTMux {\n    using type = skstd::conditional_t<a, skstd::conditional_t<b, Both, A>,\n                                         skstd::conditional_t<b, B, Neither>>;\n};\n\n/** SkTHasMoreDigits = (digits(A) >= digits(B)) ? true_type : false_type. */\ntemplate <typename A, typename B> struct SkTHasMoreDigits\n    : skstd::bool_constant<std::numeric_limits<A>::digits >= std::numeric_limits<B>::digits>\n{ };\n\n/** Returns true.\n *  Used when it is statically known that source values are in the range of the Destination.\n */\ntemplate <typename S> struct SkTInRange_True {\n    static constexpr bool fits(S) {\n        return true;\n    }\n};\n\n/** Tests that (S)(D)s == s.\n *  This is not valid for uX -> sx and sx -> uX conversions.\n */\ntemplate <typename D, typename S> struct SkTInRange_Cast {\n    static constexpr bool fits(S s) {\n        using S_is_bigger = SkTHasMoreDigits<S, D>;\n        using D_is_bigger = SkTHasMoreDigits<D, S>;\n\n        using S_is_signed = skstd::bool_constant<std::numeric_limits<S>::is_signed>;\n        using D_is_signed = skstd::bool_constant<std::numeric_limits<D>::is_signed>;\n\n        using precondition = skstd::bool_constant<\n            !((!S_is_signed::value &&  D_is_signed::value && S_is_bigger::value) ||\n              ( S_is_signed::value && !D_is_signed::value && D_is_bigger::value)   )>;\n        static_assert(precondition::value, \"not valid for uX -> sx and sx -> uX conversions\");\n\n        return static_cast<S>(static_cast<D>(s)) == s;\n    }\n};\n\n/** Tests if the source value <= Max(D).\n *  Assumes that Max(S) >= Max(D).\n */\ntemplate <typename D, typename S> struct SkTInRange_LE_MaxD {\n    static constexpr bool fits(S s) {\n        using precondition = SkTHasMoreDigits<S, D>;\n        static_assert(precondition::value, \"maxS < maxD\");\n\n        return s <= static_cast<S>((std::numeric_limits<D>::max)());\n\n    }\n};\n\n/** Tests if the source value >= 0. */\ntemplate <typename D, typename S> struct SkTInRange_GE_Zero {\n    static constexpr bool fits(S s) {\n        return static_cast<S>(0) <= s;\n    }\n};\n\n/** SkTFitsIn_Unsigned2Unsiged::type is an SkTInRange with an fits(S s) method\n *  the implementation of which is tailored for the source and destination types.\n *  Assumes that S and D are unsigned integer types.\n */\ntemplate <typename D, typename S> struct SkTFitsIn_Unsigned2Unsiged {\n    using CastCheck = SkTInRange_Cast<D, S>;\n    using NoCheck = SkTInRange_True<S>;\n\n    // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, nothing to check.\n    using sourceFitsInDesitination = SkTHasMoreDigits<D, S>;\n    using type = skstd::conditional_t<sourceFitsInDesitination::value, NoCheck, CastCheck>;\n};\n\n/** SkTFitsIn_Signed2Signed::type is an SkTInRange with an fits(S s) method\n *  the implementation of which is tailored for the source and destination types.\n *  Assumes that S and D are signed integer types.\n */\ntemplate <typename D, typename S> struct SkTFitsIn_Signed2Signed {\n    using CastCheck = SkTInRange_Cast<D, S>;\n    using NoCheck = SkTInRange_True<S>;\n\n    // If std::numeric_limits<D>::digits >= std::numeric_limits<S>::digits, nothing to check.\n    using sourceFitsInDesitination = SkTHasMoreDigits<D, S>;\n    using type = skstd::conditional_t<sourceFitsInDesitination::value, NoCheck, CastCheck>;\n};\n\n/** SkTFitsIn_Signed2Unsigned::type is an SkTInRange with an fits(S s) method\n *  the implementation of which is tailored for the source and destination types.\n *  Assumes that S is a signed integer type and D is an unsigned integer type.\n */\ntemplate <typename D, typename S> struct SkTFitsIn_Signed2Unsigned {\n    using CastCheck = SkTInRange_Cast<D, S>;\n    using LowSideOnlyCheck = SkTInRange_GE_Zero<D, S>;\n\n    // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(),\n    // no need to check the high side. (Until C++11, assume more digits means greater max.)\n    // This also protects the precondition of SkTInRange_Cast.\n    using sourceCannotExceedDest = SkTHasMoreDigits<D, S>;\n    using type = skstd::conditional_t<sourceCannotExceedDest::value, LowSideOnlyCheck, CastCheck>;\n};\n\n/** SkTFitsIn_Unsigned2Signed::type is an SkTInRange with an fits(S s) method\n *  the implementation of which is tailored for the source and destination types.\n *  Assumes that S is an usigned integer type and D is a signed integer type.\n */\ntemplate <typename D, typename S> struct SkTFitsIn_Unsigned2Signed {\n    using HighSideCheck = SkTInRange_LE_MaxD<D, S>;\n    using NoCheck = SkTInRange_True<S>;\n\n    // If std::numeric_limits<D>::max() >= std::numeric_limits<S>::max(), nothing to check.\n    // (Until C++11, assume more digits means greater max.)\n    using sourceCannotExceedDest = SkTHasMoreDigits<D, S>;\n    using type = skstd::conditional_t<sourceCannotExceedDest::value, NoCheck, HighSideCheck>;\n};\n\n/** SkTFitsIn::type is an SkTInRange with an fits(S s) method\n *  the implementation of which is tailored for the source and destination types.\n *  Assumes that S and D are integer types.\n */\ntemplate <typename D, typename S> struct SkTFitsIn {\n    // One of the following will be the 'selector' type.\n    using S2S = SkTFitsIn_Signed2Signed<D, S>;\n    using S2U = SkTFitsIn_Signed2Unsigned<D, S>;\n    using U2S = SkTFitsIn_Unsigned2Signed<D, S>;\n    using U2U = SkTFitsIn_Unsigned2Unsiged<D, S>;\n\n    using S_is_signed = skstd::bool_constant<std::numeric_limits<S>::is_signed>;\n    using D_is_signed = skstd::bool_constant<std::numeric_limits<D>::is_signed>;\n\n    using selector = typename SkTMux<S_is_signed::value, D_is_signed::value,\n                                     S2S, S2U, U2S, U2U>::type;\n    // This type is an SkTInRange.\n    using type = typename selector::type;\n};\n\ntemplate <typename T, bool = std::is_enum<T>::value> struct underlying_type {\n    using type = skstd::underlying_type_t<T>;\n};\ntemplate <typename T> struct underlying_type<T, false> {\n    using type = T;\n};\n\n} // namespace Private\n} // namespace sktfitsin\n\n/** Returns true if the integer source value 's' will fit in the integer destination type 'D'. */\ntemplate <typename D, typename S> constexpr inline bool SkTFitsIn(S s) {\n    static_assert(std::is_integral<S>::value || std::is_enum<S>::value, \"S must be integral.\");\n    static_assert(std::is_integral<D>::value || std::is_enum<D>::value, \"D must be integral.\");\n\n    using RealS = typename sktfitsin::Private::underlying_type<S>::type;\n    using RealD = typename sktfitsin::Private::underlying_type<D>::type;\n\n    return sktfitsin::Private::SkTFitsIn<RealD, RealS>::type::fits(static_cast<RealS>(s));\n}\n\n#endif\n"
  },
  {
    "path": "include/private/SkTHash.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTHash_DEFINED\n#define SkTHash_DEFINED\n\n#include \"SkChecksum.h\"\n#include \"SkTypes.h\"\n#include \"SkTemplates.h\"\n\n// Before trying to use SkTHashTable, look below to see if SkTHashMap or SkTHashSet works for you.\n// They're easier to use, usually perform the same, and have fewer sharp edges.\n\n// T and K are treated as ordinary copyable C++ types.\n// Traits must have:\n//   - static K GetKey(T)\n//   - static uint32_t Hash(K)\n// If the key is large and stored inside T, you may want to make K a const&.\n// Similarly, if T is large you might want it to be a pointer.\ntemplate <typename T, typename K, typename Traits = T>\nclass SkTHashTable : SkNoncopyable {\npublic:\n    SkTHashTable() : fCount(0), fCapacity(0) {}\n\n    // Clear the table.\n    void reset() {\n        this->~SkTHashTable();\n        new (this) SkTHashTable;\n    }\n\n    // How many entries are in the table?\n    int count() const { return fCount; }\n\n    // Approximately how many bytes of memory do we use beyond sizeof(*this)?\n    size_t approxBytesUsed() const { return fCapacity * sizeof(Slot); }\n\n    // !!!!!!!!!!!!!!!!!                 CAUTION                   !!!!!!!!!!!!!!!!!\n    // set(), find() and foreach() all allow mutable access to table entries.\n    // If you change an entry so that it no longer has the same key, all hell\n    // will break loose.  Do not do that!\n    //\n    // Please prefer to use SkTHashMap or SkTHashSet, which do not have this danger.\n\n    // The pointers returned by set() and find() are valid only until the next call to set().\n    // The pointers you receive in foreach() are only valid for its duration.\n\n    // Copy val into the hash table, returning a pointer to the copy now in the table.\n    // If there already is an entry in the table with the same key, we overwrite it.\n    T* set(T val) {\n        if (4 * fCount >= 3 * fCapacity) {\n            this->resize(fCapacity > 0 ? fCapacity * 2 : 4);\n        }\n        return this->uncheckedSet(std::move(val));\n    }\n\n    // If there is an entry in the table with this key, return a pointer to it.  If not, null.\n    T* find(const K& key) const {\n        uint32_t hash = Hash(key);\n        int index = hash & (fCapacity-1);\n        for (int n = 0; n < fCapacity; n++) {\n            Slot& s = fSlots[index];\n            if (s.empty()) {\n                return nullptr;\n            }\n            if (hash == s.hash && key == Traits::GetKey(s.val)) {\n                return &s.val;\n            }\n            index = this->next(index);\n        }\n        SkASSERT(fCapacity == 0);\n        return nullptr;\n    }\n\n    // Remove the value with this key from the hash table.\n    void remove(const K& key) {\n        SkASSERT(this->find(key));\n\n        uint32_t hash = Hash(key);\n        int index = hash & (fCapacity-1);\n        for (int n = 0; n < fCapacity; n++) {\n            Slot& s = fSlots[index];\n            SkASSERT(!s.empty());\n            if (hash == s.hash && key == Traits::GetKey(s.val)) {\n                fCount--;\n                break;\n            }\n            index = this->next(index);\n        }\n\n        // Rearrange elements to restore the invariants for linear probing.\n        for (;;) {\n            Slot& emptySlot = fSlots[index];\n            int emptyIndex = index;\n            int originalIndex;\n            // Look for an element that can be moved into the empty slot.\n            // If the empty slot is in between where an element landed, and its native slot, then\n            // move it to the empty slot. Don't move it if its native slot is in between where\n            // the element landed and the empty slot.\n            // [native] <= [empty] < [candidate] == GOOD, can move candidate to empty slot\n            // [empty] < [native] < [candidate] == BAD, need to leave candidate where it is\n            do {\n                index = this->next(index);\n                Slot& s = fSlots[index];\n                if (s.empty()) {\n                    // We're done shuffling elements around.  Clear the last empty slot.\n                    emptySlot = Slot();\n                    return;\n                }\n                originalIndex = s.hash & (fCapacity - 1);\n            } while ((index <= originalIndex && originalIndex < emptyIndex)\n                     || (originalIndex < emptyIndex && emptyIndex < index)\n                     || (emptyIndex < index && index <= originalIndex));\n            // Move the element to the empty slot.\n            Slot& moveFrom = fSlots[index];\n            emptySlot = std::move(moveFrom);\n        }\n    }\n\n    // Call fn on every entry in the table.  You may mutate the entries, but be very careful.\n    template <typename Fn>  // f(T*)\n    void foreach(Fn&& fn) {\n        for (int i = 0; i < fCapacity; i++) {\n            if (!fSlots[i].empty()) {\n                fn(&fSlots[i].val);\n            }\n        }\n    }\n\n    // Call fn on every entry in the table.  You may not mutate anything.\n    template <typename Fn>  // f(T) or f(const T&)\n    void foreach(Fn&& fn) const {\n        for (int i = 0; i < fCapacity; i++) {\n            if (!fSlots[i].empty()) {\n                fn(fSlots[i].val);\n            }\n        }\n    }\n\nprivate:\n    T* uncheckedSet(T&& val) {\n        const K& key = Traits::GetKey(val);\n        uint32_t hash = Hash(key);\n        int index = hash & (fCapacity-1);\n        for (int n = 0; n < fCapacity; n++) {\n            Slot& s = fSlots[index];\n            if (s.empty()) {\n                // New entry.\n                s.val  = std::move(val);\n                s.hash = hash;\n                fCount++;\n                return &s.val;\n            }\n            if (hash == s.hash && key == Traits::GetKey(s.val)) {\n                // Overwrite previous entry.\n                // Note: this triggers extra copies when adding the same value repeatedly.\n                s.val = std::move(val);\n                return &s.val;\n            }\n\n            index = this->next(index);\n        }\n        SkASSERT(false);\n        return nullptr;\n    }\n\n    void resize(int capacity) {\n        int oldCapacity = fCapacity;\n        SkDEBUGCODE(int oldCount = fCount);\n\n        fCount = 0;\n        fCapacity = capacity;\n        SkAutoTArray<Slot> oldSlots = std::move(fSlots);\n        fSlots = SkAutoTArray<Slot>(capacity);\n\n        for (int i = 0; i < oldCapacity; i++) {\n            Slot& s = oldSlots[i];\n            if (!s.empty()) {\n                this->uncheckedSet(std::move(s.val));\n            }\n        }\n        SkASSERT(fCount == oldCount);\n    }\n\n    int next(int index) const {\n        index--;\n        if (index < 0) { index += fCapacity; }\n        return index;\n    }\n\n    static uint32_t Hash(const K& key) {\n        uint32_t hash = Traits::Hash(key);\n        return hash ? hash : 1;  // We reserve hash 0 to mark empty.\n    }\n\n    struct Slot {\n        Slot() : hash(0) {}\n        Slot(T&& v, uint32_t h) : val(std::move(v)), hash(h) {}\n        Slot(Slot&& o) { *this = std::move(o); }\n        Slot& operator=(Slot&& o) {\n            val  = std::move(o.val);\n            hash = o.hash;\n            return *this;\n        }\n\n        bool empty() const { return this->hash == 0; }\n\n        T        val;\n        uint32_t hash;\n    };\n\n    int fCount, fCapacity;\n    SkAutoTArray<Slot> fSlots;\n};\n\n// Maps K->V.  A more user-friendly wrapper around SkTHashTable, suitable for most use cases.\n// K and V are treated as ordinary copyable C++ types, with no assumed relationship between the two.\ntemplate <typename K, typename V, typename HashK = SkGoodHash>\nclass SkTHashMap : SkNoncopyable {\npublic:\n    SkTHashMap() {}\n\n    // Clear the map.\n    void reset() { fTable.reset(); }\n\n    // How many key/value pairs are in the table?\n    int count() const { return fTable.count(); }\n\n    // Approximately how many bytes of memory do we use beyond sizeof(*this)?\n    size_t approxBytesUsed() const { return fTable.approxBytesUsed(); }\n\n    // N.B. The pointers returned by set() and find() are valid only until the next call to set().\n\n    // Set key to val in the table, replacing any previous value with the same key.\n    // We copy both key and val, and return a pointer to the value copy now in the table.\n    V* set(K key, V val) {\n        Pair* out = fTable.set({std::move(key), std::move(val)});\n        return &out->val;\n    }\n\n    // If there is key/value entry in the table with this key, return a pointer to the value.\n    // If not, return null.\n    V* find(const K& key) const {\n        if (Pair* p = fTable.find(key)) {\n            return &p->val;\n        }\n        return nullptr;\n    }\n\n    // Remove the key/value entry in the table with this key.\n    void remove(const K& key) {\n        SkASSERT(this->find(key));\n        fTable.remove(key);\n    }\n\n    // Call fn on every key/value pair in the table.  You may mutate the value but not the key.\n    template <typename Fn>  // f(K, V*) or f(const K&, V*)\n    void foreach(Fn&& fn) {\n        fTable.foreach([&fn](Pair* p){ fn(p->key, &p->val); });\n    }\n\n    // Call fn on every key/value pair in the table.  You may not mutate anything.\n    template <typename Fn>  // f(K, V), f(const K&, V), f(K, const V&) or f(const K&, const V&).\n    void foreach(Fn&& fn) const {\n        fTable.foreach([&fn](const Pair& p){ fn(p.key, p.val); });\n    }\n\nprivate:\n    struct Pair {\n        K key;\n        V val;\n        static const K& GetKey(const Pair& p) { return p.key; }\n        static uint32_t Hash(const K& key) { return HashK()(key); }\n    };\n\n    SkTHashTable<Pair, K> fTable;\n};\n\n// A set of T.  T is treated as an ordinary copyable C++ type.\ntemplate <typename T, typename HashT = SkGoodHash>\nclass SkTHashSet : SkNoncopyable {\npublic:\n    SkTHashSet() {}\n\n    // Clear the set.\n    void reset() { fTable.reset(); }\n\n    // How many items are in the set?\n    int count() const { return fTable.count(); }\n\n    // Approximately how many bytes of memory do we use beyond sizeof(*this)?\n    size_t approxBytesUsed() const { return fTable.approxBytesUsed(); }\n\n    // Copy an item into the set.\n    void add(T item) { fTable.set(std::move(item)); }\n\n    // Is this item in the set?\n    bool contains(const T& item) const { return SkToBool(this->find(item)); }\n\n    // If an item equal to this is in the set, return a pointer to it, otherwise null.\n    // This pointer remains valid until the next call to add().\n    const T* find(const T& item) const { return fTable.find(item); }\n\n    // Remove the item in the set equal to this.\n    void remove(const T& item) {\n        SkASSERT(this->contains(item));\n        fTable.remove(item);\n    }\n\n    // Call fn on every item in the set.  You may not mutate anything.\n    template <typename Fn>  // f(T), f(const T&)\n    void foreach (Fn&& fn) const {\n        fTable.foreach(fn);\n    }\n\nprivate:\n    struct Traits {\n        static const T& GetKey(const T& item) { return item; }\n        static uint32_t Hash(const T& item) { return HashT()(item); }\n    };\n    SkTHashTable<T, T, Traits> fTable;\n};\n\n#endif//SkTHash_DEFINED\n"
  },
  {
    "path": "include/private/SkTInternalLList.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkTInternalLList_DEFINED\n#define SkTInternalLList_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n * Helper class to automatically initialize the doubly linked list created pointers.\n */\ntemplate <typename T> class SkPtrWrapper {\n  public:\n      SkPtrWrapper() : fPtr(nullptr) {}\n      SkPtrWrapper& operator =(T* ptr) { fPtr = ptr; return *this; }\n      operator T*() const { return fPtr; }\n      T* operator->() { return fPtr; }\n  private:\n      T* fPtr;\n};\n\n\n/**\n * This macro creates the member variables required by the SkTInternalLList class. It should be\n * placed in the private section of any class that will be stored in a double linked list.\n */\n#define SK_DECLARE_INTERNAL_LLIST_INTERFACE(ClassName)              \\\n    friend class SkTInternalLList<ClassName>;                       \\\n    /* back pointer to the owning list - for debugging */           \\\n    SkDEBUGCODE(SkPtrWrapper<SkTInternalLList<ClassName> > fList;)  \\\n    SkPtrWrapper<ClassName> fPrev;                                  \\\n    SkPtrWrapper<ClassName> fNext\n\n/**\n * This class implements a templated internal doubly linked list data structure.\n */\ntemplate <class T> class SkTInternalLList : SkNoncopyable {\npublic:\n    SkTInternalLList()\n        : fHead(nullptr)\n        , fTail(nullptr) {\n    }\n\n    void reset() {\n        fHead = nullptr;\n        fTail = nullptr;\n    }\n\n    void remove(T* entry) {\n        SkASSERT(fHead && fTail);\n        SkASSERT(this->isInList(entry));\n\n        T* prev = entry->fPrev;\n        T* next = entry->fNext;\n\n        if (prev) {\n            prev->fNext = next;\n        } else {\n            fHead = next;\n        }\n        if (next) {\n            next->fPrev = prev;\n        } else {\n            fTail = prev;\n        }\n\n        entry->fPrev = nullptr;\n        entry->fNext = nullptr;\n\n#ifdef SK_DEBUG\n        entry->fList = nullptr;\n#endif\n    }\n\n    void addToHead(T* entry) {\n        SkASSERT(nullptr == entry->fPrev && nullptr == entry->fNext);\n        SkASSERT(nullptr == entry->fList);\n\n        entry->fPrev = nullptr;\n        entry->fNext = fHead;\n        if (fHead) {\n            fHead->fPrev = entry;\n        }\n        fHead = entry;\n        if (nullptr == fTail) {\n            fTail = entry;\n        }\n\n#ifdef SK_DEBUG\n        entry->fList = this;\n#endif\n    }\n\n    void addToTail(T* entry) {\n        SkASSERT(nullptr == entry->fPrev && nullptr == entry->fNext);\n        SkASSERT(nullptr == entry->fList);\n\n        entry->fPrev = fTail;\n        entry->fNext = nullptr;\n        if (fTail) {\n            fTail->fNext = entry;\n        }\n        fTail = entry;\n        if (nullptr == fHead) {\n            fHead = entry;\n        }\n\n#ifdef SK_DEBUG\n        entry->fList = this;\n#endif\n    }\n\n    /**\n     * Inserts a new list entry before an existing list entry. The new entry must not already be\n     * a member of this or any other list. If existingEntry is NULL then the new entry is added\n     * at the tail.\n     */\n    void addBefore(T* newEntry, T* existingEntry) {\n        SkASSERT(newEntry);\n\n        if (nullptr == existingEntry) {\n            this->addToTail(newEntry);\n            return;\n        }\n\n        SkASSERT(this->isInList(existingEntry));\n        newEntry->fNext = existingEntry;\n        T* prev = existingEntry->fPrev;\n        existingEntry->fPrev = newEntry;\n        newEntry->fPrev = prev;\n        if (nullptr == prev) {\n            SkASSERT(fHead == existingEntry);\n            fHead = newEntry;\n        } else {\n            prev->fNext = newEntry;\n        }\n#ifdef SK_DEBUG\n        newEntry->fList = this;\n#endif\n    }\n\n    /**\n     * Inserts a new list entry after an existing list entry. The new entry must not already be\n     * a member of this or any other list. If existingEntry is NULL then the new entry is added\n     * at the head.\n     */\n    void addAfter(T* newEntry, T* existingEntry) {\n        SkASSERT(newEntry);\n\n        if (nullptr == existingEntry) {\n            this->addToHead(newEntry);\n            return;\n        }\n\n        SkASSERT(this->isInList(existingEntry));\n        newEntry->fPrev = existingEntry;\n        T* next = existingEntry->fNext;\n        existingEntry->fNext = newEntry;\n        newEntry->fNext = next;\n        if (nullptr == next) {\n            SkASSERT(fTail == existingEntry);\n            fTail = newEntry;\n        } else {\n            next->fPrev = newEntry;\n        }\n#ifdef SK_DEBUG\n        newEntry->fList = this;\n#endif\n    }\n\n    void concat(SkTInternalLList&& list) {\n        if (list.isEmpty()) {\n            return;\n        }\n\n        list.fHead->fPrev = fTail;\n        if (!fHead) {\n            SkASSERT(!list.fHead->fPrev);\n            fHead = list.fHead;\n        } else {\n            SkASSERT(fTail);\n            fTail->fNext = list.fHead;\n        }\n        fTail = list.fTail;\n\n#ifdef SK_DEBUG\n        for (T* node = list.fHead; node; node = node->fNext) {\n            SkASSERT(node->fList == &list);\n            node->fList = this;\n        }\n#endif\n\n        list.fHead = list.fTail = nullptr;\n    }\n\n    bool isEmpty() const {\n        SkASSERT(SkToBool(fHead) == SkToBool(fTail));\n        return !fHead;\n    }\n\n    T* head() { return fHead; }\n    T* tail() { return fTail; }\n\n    class Iter {\n    public:\n        enum IterStart {\n            kHead_IterStart,\n            kTail_IterStart\n        };\n\n        Iter() : fCurr(nullptr) {}\n        Iter(const Iter& iter) : fCurr(iter.fCurr) {}\n        Iter& operator= (const Iter& iter) { fCurr = iter.fCurr; return *this; }\n\n        T* init(const SkTInternalLList& list, IterStart startLoc) {\n            if (kHead_IterStart == startLoc) {\n                fCurr = list.fHead;\n            } else {\n                SkASSERT(kTail_IterStart == startLoc);\n                fCurr = list.fTail;\n            }\n\n            return fCurr;\n        }\n\n        T* get() { return fCurr; }\n\n        /**\n         * Return the next/previous element in the list or NULL if at the end.\n         */\n        T* next() {\n            if (nullptr == fCurr) {\n                return nullptr;\n            }\n\n            fCurr = fCurr->fNext;\n            return fCurr;\n        }\n\n        T* prev() {\n            if (nullptr == fCurr) {\n                return nullptr;\n            }\n\n            fCurr = fCurr->fPrev;\n            return fCurr;\n        }\n\n        /**\n         * C++11 range-for interface.\n         */\n        bool operator!=(const Iter& that) { return fCurr != that.fCurr; }\n        T* operator*() { return this->get(); }\n        void operator++() { this->next(); }\n\n    private:\n        T* fCurr;\n    };\n\n    Iter begin() const {\n        Iter iter;\n        iter.init(*this, Iter::kHead_IterStart);\n        return iter;\n    }\n\n    Iter end() const { return Iter(); }\n\n#ifdef SK_DEBUG\n    void validate() const {\n        SkASSERT(!fHead == !fTail);\n        Iter iter;\n        for (T* item = iter.init(*this, Iter::kHead_IterStart); item; item = iter.next()) {\n            SkASSERT(this->isInList(item));\n            if (nullptr == item->fPrev) {\n                SkASSERT(fHead == item);\n            } else {\n                SkASSERT(item->fPrev->fNext == item);\n            }\n            if (nullptr == item->fNext) {\n                SkASSERT(fTail == item);\n            } else {\n                SkASSERT(item->fNext->fPrev == item);\n            }\n        }\n    }\n\n    /**\n     * Debugging-only method that uses the list back pointer to check if 'entry' is indeed in 'this'\n     * list.\n     */\n    bool isInList(const T* entry) const {\n        return entry->fList == this;\n    }\n\n    /**\n     * Debugging-only method that laboriously counts the list entries.\n     */\n    int countEntries() const {\n        int count = 0;\n        for (T* entry = fHead; entry; entry = entry->fNext) {\n            ++count;\n        }\n        return count;\n    }\n#endif // SK_DEBUG\n\nprivate:\n    T* fHead;\n    T* fTail;\n\n    typedef SkNoncopyable INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/private/SkTLogic.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n *\n *\n * This header provides some of the helpers (like std::enable_if_t) which will\n * become available with C++14 in the type_traits header (in the skstd\n * namespace). This header also provides several Skia specific additions such\n * as SK_WHEN and the sknonstd namespace.\n */\n\n#ifndef SkTLogic_DEFINED\n#define SkTLogic_DEFINED\n\n#include <array>\n#include <stddef.h>\n#include <stdint.h>\n#include <type_traits>\n#include <utility>\n\nnamespace skstd {\n\ntemplate <bool B> using bool_constant = std::integral_constant<bool, B>;\n\ntemplate <bool B, typename T, typename F> using conditional_t = typename std::conditional<B, T, F>::type;\ntemplate <bool B, typename T = void> using enable_if_t = typename std::enable_if<B, T>::type;\n\ntemplate <typename T> using remove_const_t = typename std::remove_const<T>::type;\ntemplate <typename T> using remove_volatile_t = typename std::remove_volatile<T>::type;\ntemplate <typename T> using remove_cv_t = typename std::remove_cv<T>::type;\ntemplate <typename T> using remove_pointer_t = typename std::remove_pointer<T>::type;\ntemplate <typename T> using remove_reference_t = typename std::remove_reference<T>::type;\ntemplate <typename T> using remove_extent_t = typename std::remove_extent<T>::type;\n\ntemplate <typename T> using add_const_t = typename std::add_const<T>::type;\ntemplate <typename T> using add_volatile_t = typename std::add_volatile<T>::type;\ntemplate <typename T> using add_cv_t = typename std::add_cv<T>::type;\ntemplate <typename T> using add_pointer_t = typename std::add_pointer<T>::type;\ntemplate <typename T> using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;\n\ntemplate <typename T> using result_of_t = typename std::result_of<T>::type;\n\ntemplate <typename... T> using common_type_t = typename std::common_type<T...>::type;\n\n// Chromium currently requires gcc 4.8.2 or a recent clang compiler, but uses libstdc++4.6.4.\n// Note that Precise actually uses libstdc++4.6.3.\n// Unfortunately, libstdc++ STL before libstdc++4.7 do not define std::underlying_type.\n// Newer gcc and clang compilers have __underlying_type which does not depend on runtime support.\n// See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html for __GLIBCXX__ values.\n// Unfortunately __GLIBCXX__ is a date, but no updates to versions before 4.7 are now anticipated.\n#define SK_GLIBCXX_4_7_0 20120322\n// Updates to versions before 4.7 but released after 4.7 was released.\n#define SK_GLIBCXX_4_5_4 20120702\n#define SK_GLIBCXX_4_6_4 20121127\n#if defined(__GLIBCXX__) && (__GLIBCXX__ <  SK_GLIBCXX_4_7_0 || \\\n                             __GLIBCXX__ == SK_GLIBCXX_4_5_4 || \\\n                             __GLIBCXX__ == SK_GLIBCXX_4_6_4)\ntemplate <typename T> struct underlying_type {\n    using type = __underlying_type(T);\n};\ntemplate <typename T> using is_trivially_destructible = std::has_trivial_destructor<T>;\n#else\ntemplate <typename T> using underlying_type = std::underlying_type<T>;\ntemplate <typename T> using is_trivially_destructible = std::is_trivially_destructible<T>;\n#endif\ntemplate <typename T> using underlying_type_t = typename skstd::underlying_type<T>::type;\n\n\ntemplate <std::size_t... Ints> struct index_sequence {\n    using type = index_sequence;\n    using value_type = size_t;\n    static constexpr std::size_t size() noexcept { return sizeof...(Ints); }\n};\n\ntemplate <typename S1, typename S2> struct make_index_sequence_combine;\ntemplate <size_t... I1, size_t... I2>\nstruct make_index_sequence_combine<skstd::index_sequence<I1...>, skstd::index_sequence<I2...>>\n    : skstd::index_sequence<I1..., (sizeof...(I1)+I2)...>\n{ };\n\ntemplate <size_t N> struct make_index_sequence\n    : make_index_sequence_combine<typename skstd::make_index_sequence<    N/2>::type,\n                                  typename skstd::make_index_sequence<N - N/2>::type>{};\ntemplate<> struct make_index_sequence<0> : skstd::index_sequence< >{};\ntemplate<> struct make_index_sequence<1> : skstd::index_sequence<0>{};\n\n}  // namespace skstd\n\n// The sknonstd namespace contains things we would like to be proposed and feel std-ish.\nnamespace sknonstd {\n\n// The name 'copy' here is fraught with peril. In this case it means 'append', not 'overwrite'.\n// Alternate proposed names are 'propagate', 'augment', or 'append' (and 'add', but already taken).\n// std::experimental::propagate_const already exists for other purposes in TSv2.\n// These also follow the <dest, source> pattern used by boost.\ntemplate <typename D, typename S> struct copy_const {\n    using type = skstd::conditional_t<std::is_const<S>::value, skstd::add_const_t<D>, D>;\n};\ntemplate <typename D, typename S> using copy_const_t = typename copy_const<D, S>::type;\n\ntemplate <typename D, typename S> struct copy_volatile {\n    using type = skstd::conditional_t<std::is_volatile<S>::value, skstd::add_volatile_t<D>, D>;\n};\ntemplate <typename D, typename S> using copy_volatile_t = typename copy_volatile<D, S>::type;\n\ntemplate <typename D, typename S> struct copy_cv {\n    using type = copy_volatile_t<copy_const_t<D, S>, S>;\n};\ntemplate <typename D, typename S> using copy_cv_t = typename copy_cv<D, S>::type;\n\n// The name 'same' here means 'overwrite'.\n// Alternate proposed names are 'replace', 'transfer', or 'qualify_from'.\n// same_xxx<D, S> can be written as copy_xxx<remove_xxx_t<D>, S>\ntemplate <typename D, typename S> using same_const = copy_const<skstd::remove_const_t<D>, S>;\ntemplate <typename D, typename S> using same_const_t = typename same_const<D, S>::type;\ntemplate <typename D, typename S> using same_volatile =copy_volatile<skstd::remove_volatile_t<D>,S>;\ntemplate <typename D, typename S> using same_volatile_t = typename same_volatile<D, S>::type;\ntemplate <typename D, typename S> using same_cv = copy_cv<skstd::remove_cv_t<D>, S>;\ntemplate <typename D, typename S> using same_cv_t = typename same_cv<D, S>::type;\n\n}  // namespace sknonstd\n\n// Just a pithier wrapper for enable_if_t.\n#define SK_WHEN(condition, T) skstd::enable_if_t<!!(condition), T>\n\n#endif\n"
  },
  {
    "path": "include/private/SkTSearch.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkTSearch_DEFINED\n#define SkTSearch_DEFINED\n\n#include \"SkTypes.h\"\n\n/**\n *  All of the SkTSearch variants want to return the index (0...N-1) of the\n *  found element, or the bit-not of where to insert the element.\n *\n *  At a simple level, if the return value is negative, it was not found.\n *\n *  For clients that want to insert the new element if it was not found, use\n *  the following logic:\n *\n *  int index = SkTSearch(...);\n *  if (index >= 0) {\n *      // found at index\n *  } else {\n *      index = ~index; // now we are positive\n *      // insert at index\n *  }\n */\n\n\n// The most general form of SkTSearch takes an array of T and a key of type K. A functor, less, is\n// used to perform comparisons. It has two function operators:\n//      bool operator() (const T& t, const K& k)\n//      bool operator() (const K& t, const T& k)\ntemplate <typename T, typename K, typename LESS>\nint SkTSearch(const T base[], int count, const K& key, size_t elemSize, LESS& less)\n{\n    SkASSERT(count >= 0);\n    if (count <= 0) {\n        return ~0;\n    }\n\n    SkASSERT(base != nullptr); // base may be nullptr if count is zero\n\n    int lo = 0;\n    int hi = count - 1;\n\n    while (lo < hi) {\n        int mid = lo + ((hi - lo) >> 1);\n        const T* elem = (const T*)((const char*)base + mid * elemSize);\n\n        if (less(*elem, key))\n            lo = mid + 1;\n        else\n            hi = mid;\n    }\n\n    const T* elem = (const T*)((const char*)base + hi * elemSize);\n    if (less(*elem, key)) {\n        hi += 1;\n        hi = ~hi;\n    } else if (less(key, *elem)) {\n        hi = ~hi;\n    }\n    return hi;\n}\n\n// Adapts a less-than function to a functor.\ntemplate <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToFunctorAdaptor {\n    bool operator()(const T& a, const T& b) { return LESS(a, b); }\n};\n\n// Specialization for case when T==K and the caller wants to use a function rather than functor.\ntemplate <typename T, bool (LESS)(const T&, const T&)>\nint SkTSearch(const T base[], int count, const T& target, size_t elemSize) {\n    static SkTLessFunctionToFunctorAdaptor<T, LESS> functor;\n    return SkTSearch(base, count, target, elemSize, functor);\n}\n\n// Adapts operator < to a functor.\ntemplate <typename T> struct SkTLessFunctor {\n    bool operator()(const T& a, const T& b) { return a < b; }\n};\n\n// Specialization for T==K, compare using op <.\ntemplate <typename T>\nint SkTSearch(const T base[], int count, const T& target, size_t elemSize) {\n    static SkTLessFunctor<T> functor;\n    return SkTSearch(base, count, target, elemSize, functor);\n}\n\n// Similar to SkLessFunctionToFunctorAdaptor but makes the functor interface take T* rather than T.\ntemplate <typename T, bool (LESS)(const T&, const T&)> struct SkTLessFunctionToPtrFunctorAdaptor {\n    bool operator() (const T* t, const T* k) { return LESS(*t, *k); }\n};\n\n// Specialization for case where domain is an array of T* and the key value is a T*, and you want\n// to compare the T objects, not the pointers.\ntemplate <typename T, bool (LESS)(const T&, const T&)>\nint SkTSearch(T* base[], int count, T* target, size_t elemSize) {\n    static SkTLessFunctionToPtrFunctorAdaptor<T, LESS> functor;\n    return SkTSearch(base, count, target, elemSize, functor);\n}\n\nint SkStrSearch(const char*const* base, int count, const char target[],\n                size_t target_len, size_t elemSize);\nint SkStrSearch(const char*const* base, int count, const char target[],\n                size_t elemSize);\n\n/** Like SkStrSearch, but treats target as if it were all lower-case. Assumes that\n    base points to a table of lower-case strings.\n*/\nint SkStrLCSearch(const char*const* base, int count, const char target[],\n                  size_t target_len, size_t elemSize);\nint SkStrLCSearch(const char*const* base, int count, const char target[],\n                  size_t elemSize);\n\n/** Helper class to convert a string to lower-case, but only modifying the ascii\n    characters. This makes the routine very fast and never changes the string\n    length, but it is not suitable for linguistic purposes. Normally this is\n    used for buiding and searching string tables.\n*/\nclass SkAutoAsciiToLC {\npublic:\n    SkAutoAsciiToLC(const char str[], size_t len = (size_t)-1);\n    ~SkAutoAsciiToLC();\n\n    const char* lc() const { return fLC; }\n    size_t      length() const { return fLength; }\n\nprivate:\n    char*   fLC;    // points to either the heap or fStorage\n    size_t  fLength;\n    enum {\n        STORAGE = 64\n    };\n    char    fStorage[STORAGE+1];\n};\n\n// Helper when calling qsort with a compare proc that has typed its arguments\n#define SkCastForQSort(compare) reinterpret_cast<int (*)(const void*, const void*)>(compare)\n\n#endif\n"
  },
  {
    "path": "include/private/SkTemplates.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkTemplates_DEFINED\n#define SkTemplates_DEFINED\n\n#include \"SkMath.h\"\n#include \"SkMalloc.h\"\n#include \"SkTLogic.h\"\n#include \"SkTypes.h\"\n#include <limits.h>\n#include <memory>\n#include <new>\n\n/** \\file SkTemplates.h\n\n    This file contains light-weight template classes for type-safe and exception-safe\n    resource management.\n*/\n\n/**\n *  Marks a local variable as known to be unused (to avoid warnings).\n *  Note that this does *not* prevent the local variable from being optimized away.\n */\ntemplate<typename T> inline void sk_ignore_unused_variable(const T&) { }\n\n/**\n *  Returns a pointer to a D which comes immediately after S[count].\n */\ntemplate <typename D, typename S> static D* SkTAfter(S* ptr, size_t count = 1) {\n    return reinterpret_cast<D*>(ptr + count);\n}\n\n/**\n *  Returns a pointer to a D which comes byteOffset bytes after S.\n */\ntemplate <typename D, typename S> static D* SkTAddOffset(S* ptr, size_t byteOffset) {\n    // The intermediate char* has the same cv-ness as D as this produces better error messages.\n    // This relies on the fact that reinterpret_cast can add constness, but cannot remove it.\n    return reinterpret_cast<D*>(reinterpret_cast<sknonstd::same_cv_t<char, D>*>(ptr) + byteOffset);\n}\n\ntemplate <typename R, typename T, R (*P)(T*)> struct SkFunctionWrapper {\n    R operator()(T* t) { return P(t); }\n};\n\n/** \\class SkAutoTCallVProc\n\n    Call a function when this goes out of scope. The template uses two\n    parameters, the object, and a function that is to be called in the destructor.\n    If release() is called, the object reference is set to null. If the object\n    reference is null when the destructor is called, we do not call the\n    function.\n*/\ntemplate <typename T, void (*P)(T*)> class SkAutoTCallVProc\n    : public std::unique_ptr<T, SkFunctionWrapper<void, T, P>> {\npublic:\n    SkAutoTCallVProc(T* obj): std::unique_ptr<T, SkFunctionWrapper<void, T, P>>(obj) {}\n\n    operator T*() const { return this->get(); }\n};\n\n/** \\class SkAutoTCallIProc\n\nCall a function when this goes out of scope. The template uses two\nparameters, the object, and a function that is to be called in the destructor.\nIf release() is called, the object reference is set to null. If the object\nreference is null when the destructor is called, we do not call the\nfunction.\n*/\ntemplate <typename T, int (*P)(T*)> class SkAutoTCallIProc\n    : public std::unique_ptr<T, SkFunctionWrapper<int, T, P>> {\npublic:\n    SkAutoTCallIProc(T* obj): std::unique_ptr<T, SkFunctionWrapper<int, T, P>>(obj) {}\n\n    operator T*() const { return this->get(); }\n};\n\n/** Allocate an array of T elements, and free the array in the destructor\n */\ntemplate <typename T> class SkAutoTArray  {\npublic:\n    SkAutoTArray() {}\n    /** Allocate count number of T elements\n     */\n    explicit SkAutoTArray(int count) {\n        SkASSERT(count >= 0);\n        if (count) {\n            fArray.reset(new T[count]);\n        }\n        SkDEBUGCODE(fCount = count;)\n    }\n\n    SkAutoTArray(SkAutoTArray&& other) : fArray(std::move(other.fArray)) {\n        SkDEBUGCODE(fCount = other.fCount; other.fCount = 0;)\n    }\n    SkAutoTArray& operator=(SkAutoTArray&& other) {\n        if (this != &other) {\n            fArray = std::move(other.fArray);\n            SkDEBUGCODE(fCount = other.fCount; other.fCount = 0;)\n        }\n        return *this;\n    }\n\n    /** Reallocates given a new count. Reallocation occurs even if new count equals old count.\n     */\n    void reset(int count) { *this = SkAutoTArray(count);  }\n\n    /** Return the array of T elements. Will be NULL if count == 0\n     */\n    T* get() const { return fArray.get(); }\n\n    /** Return the nth element in the array\n     */\n    T&  operator[](int index) const {\n        SkASSERT((unsigned)index < (unsigned)fCount);\n        return fArray[index];\n    }\n\nprivate:\n    std::unique_ptr<T[]> fArray;\n    SkDEBUGCODE(int fCount = 0;)\n};\n\n/** Wraps SkAutoTArray, with room for kCountRequested elements preallocated.\n */\ntemplate <int kCountRequested, typename T> class SkAutoSTArray : SkNoncopyable {\npublic:\n    /** Initialize with no objects */\n    SkAutoSTArray() {\n        fArray = nullptr;\n        fCount = 0;\n    }\n\n    /** Allocate count number of T elements\n     */\n    SkAutoSTArray(int count) {\n        fArray = nullptr;\n        fCount = 0;\n        this->reset(count);\n    }\n\n    ~SkAutoSTArray() {\n        this->reset(0);\n    }\n\n    /** Destroys previous objects in the array and default constructs count number of objects */\n    void reset(int count) {\n        T* start = fArray;\n        T* iter = start + fCount;\n        while (iter > start) {\n            (--iter)->~T();\n        }\n\n        SkASSERT(count >= 0);\n        if (fCount != count) {\n            if (fCount > kCount) {\n                // 'fArray' was allocated last time so free it now\n                SkASSERT((T*) fStorage != fArray);\n                sk_free(fArray);\n            }\n\n            if (count > kCount) {\n                fArray = (T*) sk_malloc_throw(count, sizeof(T));\n            } else if (count > 0) {\n                fArray = (T*) fStorage;\n            } else {\n                fArray = nullptr;\n            }\n\n            fCount = count;\n        }\n\n        iter = fArray;\n        T* stop = fArray + count;\n        while (iter < stop) {\n            new (iter++) T;\n        }\n    }\n\n    /** Return the number of T elements in the array\n     */\n    int count() const { return fCount; }\n\n    /** Return the array of T elements. Will be NULL if count == 0\n     */\n    T* get() const { return fArray; }\n\n    T* begin() { return fArray; }\n\n    const T* begin() const { return fArray; }\n\n    T* end() { return fArray + fCount; }\n\n    const T* end() const { return fArray + fCount; }\n\n    /** Return the nth element in the array\n     */\n    T&  operator[](int index) const {\n        SkASSERT(index < fCount);\n        return fArray[index];\n    }\n\nprivate:\n#if defined(SK_BUILD_FOR_GOOGLE3)\n    // Stack frame size is limited for SK_BUILD_FOR_GOOGLE3. 4k is less than the actual max, but some functions\n    // have multiple large stack allocations.\n    static const int kMaxBytes = 4 * 1024;\n    static const int kCount = kCountRequested * sizeof(T) > kMaxBytes\n        ? kMaxBytes / sizeof(T)\n        : kCountRequested;\n#else\n    static const int kCount = kCountRequested;\n#endif\n\n    int     fCount;\n    T*      fArray;\n    // since we come right after fArray, fStorage should be properly aligned\n    char    fStorage[kCount * sizeof(T)];\n};\n\n/** Manages an array of T elements, freeing the array in the destructor.\n *  Does NOT call any constructors/destructors on T (T must be POD).\n */\ntemplate <typename T> class SkAutoTMalloc  {\npublic:\n    /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */\n    explicit SkAutoTMalloc(T* ptr = nullptr) : fPtr(ptr) {}\n\n    /** Allocates space for 'count' Ts. */\n    explicit SkAutoTMalloc(size_t count)\n        : fPtr(count ? (T*)sk_malloc_throw(count, sizeof(T)) : nullptr) {}\n\n    SkAutoTMalloc(SkAutoTMalloc&&) = default;\n    SkAutoTMalloc& operator=(SkAutoTMalloc&&) = default;\n\n    /** Resize the memory area pointed to by the current ptr preserving contents. */\n    void realloc(size_t count) {\n        fPtr.reset(count ? (T*)sk_realloc_throw(fPtr.release(), count * sizeof(T)) : nullptr);\n    }\n\n    /** Resize the memory area pointed to by the current ptr without preserving contents. */\n    T* reset(size_t count = 0) {\n        fPtr.reset(count ? (T*)sk_malloc_throw(count, sizeof(T)) : nullptr);\n        return this->get();\n    }\n\n    T* get() const { return fPtr.get(); }\n\n    operator T*() { return fPtr.get(); }\n\n    operator const T*() const { return fPtr.get(); }\n\n    T& operator[](int index) { return fPtr.get()[index]; }\n\n    const T& operator[](int index) const { return fPtr.get()[index]; }\n\n    /**\n     *  Transfer ownership of the ptr to the caller, setting the internal\n     *  pointer to NULL. Note that this differs from get(), which also returns\n     *  the pointer, but it does not transfer ownership.\n     */\n    T* release() { return fPtr.release(); }\n\nprivate:\n    std::unique_ptr<T, SkFunctionWrapper<void, void, sk_free>> fPtr;\n};\n\ntemplate <size_t kCountRequested, typename T> class SkAutoSTMalloc : SkNoncopyable {\npublic:\n    SkAutoSTMalloc() : fPtr(fTStorage) {}\n\n    SkAutoSTMalloc(size_t count) {\n        if (count > kCount) {\n            fPtr = (T*)sk_malloc_throw(count, sizeof(T));\n        } else if (count) {\n            fPtr = fTStorage;\n        } else {\n            fPtr = nullptr;\n        }\n    }\n\n    ~SkAutoSTMalloc() {\n        if (fPtr != fTStorage) {\n            sk_free(fPtr);\n        }\n    }\n\n    // doesn't preserve contents\n    T* reset(size_t count) {\n        if (fPtr != fTStorage) {\n            sk_free(fPtr);\n        }\n        if (count > kCount) {\n            fPtr = (T*)sk_malloc_throw(count, sizeof(T));\n        } else if (count) {\n            fPtr = fTStorage;\n        } else {\n            fPtr = nullptr;\n        }\n        return fPtr;\n    }\n\n    T* get() const { return fPtr; }\n\n    operator T*() {\n        return fPtr;\n    }\n\n    operator const T*() const {\n        return fPtr;\n    }\n\n    T& operator[](int index) {\n        return fPtr[index];\n    }\n\n    const T& operator[](int index) const {\n        return fPtr[index];\n    }\n\n    // Reallocs the array, can be used to shrink the allocation.  Makes no attempt to be intelligent\n    void realloc(size_t count) {\n        if (count > kCount) {\n            if (fPtr == fTStorage) {\n                fPtr = (T*)sk_malloc_throw(count, sizeof(T));\n                memcpy(fPtr, fTStorage, kCount * sizeof(T));\n            } else {\n                fPtr = (T*)sk_realloc_throw(fPtr, count, sizeof(T));\n            }\n        } else if (count) {\n            if (fPtr != fTStorage) {\n                fPtr = (T*)sk_realloc_throw(fPtr, count, sizeof(T));\n            }\n        } else {\n            this->reset(0);\n        }\n    }\n\nprivate:\n    // Since we use uint32_t storage, we might be able to get more elements for free.\n    static const size_t kCountWithPadding = SkAlign4(kCountRequested*sizeof(T)) / sizeof(T);\n#if defined(SK_BUILD_FOR_GOOGLE3)\n    // Stack frame size is limited for SK_BUILD_FOR_GOOGLE3. 4k is less than the actual max, but some functions\n    // have multiple large stack allocations.\n    static const size_t kMaxBytes = 4 * 1024;\n    static const size_t kCount = kCountRequested * sizeof(T) > kMaxBytes\n        ? kMaxBytes / sizeof(T)\n        : kCountWithPadding;\n#else\n    static const size_t kCount = kCountWithPadding;\n#endif\n\n    T*          fPtr;\n    union {\n        uint32_t    fStorage32[SkAlign4(kCount*sizeof(T)) >> 2];\n        T           fTStorage[1];   // do NOT want to invoke T::T()\n    };\n};\n\n//////////////////////////////////////////////////////////////////////////////////////////////////\n\n/**\n *  Pass the object and the storage that was offered during SkInPlaceNewCheck, and this will\n *  safely destroy (and free if it was dynamically allocated) the object.\n */\ntemplate <typename T> void SkInPlaceDeleteCheck(T* obj, void* storage) {\n    if (storage == obj) {\n        obj->~T();\n    } else {\n        delete obj;\n    }\n}\n\n/**\n *  Allocates T, using storage if it is large enough, and allocating on the heap (via new) if\n *  storage is not large enough.\n *\n *      obj = SkInPlaceNewCheck<Type>(storage, size);\n *      ...\n *      SkInPlaceDeleteCheck(obj, storage);\n */\ntemplate<typename T, typename... Args>\nT* SkInPlaceNewCheck(void* storage, size_t size, Args&&... args) {\n    return (sizeof(T) <= size) ? new (storage) T(std::forward<Args>(args)...)\n                               : new T(std::forward<Args>(args)...);\n}\n/**\n * Reserves memory that is aligned on double and pointer boundaries.\n * Hopefully this is sufficient for all practical purposes.\n */\ntemplate <size_t N> class SkAlignedSStorage : SkNoncopyable {\npublic:\n    size_t size() const { return N; }\n    void* get() { return fData; }\n    const void* get() const { return fData; }\n\nprivate:\n    union {\n        void*   fPtr;\n        double  fDouble;\n        char    fData[N];\n    };\n};\n\n/**\n * Reserves memory that is aligned on double and pointer boundaries.\n * Hopefully this is sufficient for all practical purposes. Otherwise,\n * we have to do some arcane trickery to determine alignment of non-POD\n * types. Lifetime of the memory is the lifetime of the object.\n */\ntemplate <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {\npublic:\n    /**\n     * Returns void* because this object does not initialize the\n     * memory. Use placement new for types that require a cons.\n     */\n    void* get() { return fStorage.get(); }\n    const void* get() const { return fStorage.get(); }\nprivate:\n    SkAlignedSStorage<sizeof(T)*N> fStorage;\n};\n\nusing SkAutoFree = std::unique_ptr<void, SkFunctionWrapper<void, void, sk_free>>;\n\ntemplate<typename C, std::size_t... Is>\nconstexpr auto SkMakeArrayFromIndexSequence(C c, skstd::index_sequence<Is...>)\n-> std::array<skstd::result_of_t<C(std::size_t)>, sizeof...(Is)> {\n    return {{ c(Is)... }};\n}\n\ntemplate<size_t N, typename C> constexpr auto SkMakeArray(C c)\n-> std::array<skstd::result_of_t<C(std::size_t)>, N> {\n    return SkMakeArrayFromIndexSequence(c, skstd::make_index_sequence<N>{});\n}\n\n#endif\n"
  },
  {
    "path": "include/private/SkThreadID.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkThreadID_DEFINED\n#define SkThreadID_DEFINED\n\n#include \"SkTypes.h\"\n\ntypedef int64_t SkThreadID;\n\nSkThreadID SkGetThreadID();\n\nconst SkThreadID kIllegalThreadID = 0;\n\n#endif  // SkThreadID_DEFINED\n"
  },
  {
    "path": "include/private/SkWeakRefCnt.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkWeakRefCnt_DEFINED\n#define SkWeakRefCnt_DEFINED\n\n#include \"SkRefCnt.h\"\n#include <atomic>\n\n/** \\class SkWeakRefCnt\n\n    SkWeakRefCnt is the base class for objects that may be shared by multiple\n    objects. When an existing strong owner wants to share a reference, it calls\n    ref(). When a strong owner wants to release its reference, it calls\n    unref(). When the shared object's strong reference count goes to zero as\n    the result of an unref() call, its (virtual) weak_dispose method is called.\n    It is an error for the destructor to be called explicitly (or via the\n    object going out of scope on the stack or calling delete) if\n    getRefCnt() > 1.\n\n    In addition to strong ownership, an owner may instead obtain a weak\n    reference by calling weak_ref(). A call to weak_ref() must be balanced by a\n    call to weak_unref(). To obtain a strong reference from a weak reference,\n    call try_ref(). If try_ref() returns true, the owner's pointer is now also\n    a strong reference on which unref() must be called. Note that this does not\n    affect the original weak reference, weak_unref() must still be called. When\n    the weak reference count goes to zero, the object is deleted. While the\n    weak reference count is positive and the strong reference count is zero the\n    object still exists, but will be in the disposed state. It is up to the\n    object to define what this means.\n\n    Note that a strong reference implicitly implies a weak reference. As a\n    result, it is allowable for the owner of a strong ref to call try_ref().\n    This will have the same effect as calling ref(), but may be more expensive.\n\n    Example:\n\n    SkWeakRefCnt myRef = strongRef.weak_ref();\n    ... // strongRef.unref() may or may not be called\n    if (myRef.try_ref()) {\n        ... // use myRef\n        myRef.unref();\n    } else {\n        // myRef is in the disposed state\n    }\n    myRef.weak_unref();\n*/\nclass SK_API SkWeakRefCnt : public SkRefCnt {\npublic:\n    /** Default construct, initializing the reference counts to 1.\n        The strong references collectively hold one weak reference. When the\n        strong reference count goes to zero, the collectively held weak\n        reference is released.\n    */\n    SkWeakRefCnt() : SkRefCnt(), fWeakCnt(1) {}\n\n    /** Destruct, asserting that the weak reference count is 1.\n    */\n    ~SkWeakRefCnt() override {\n#ifdef SK_DEBUG\n        SkASSERT(getWeakCnt() == 1);\n        fWeakCnt.store(0, std::memory_order_relaxed);\n#endif\n    }\n\n#ifdef SK_DEBUG\n    /** Return the weak reference count. */\n    int32_t getWeakCnt() const {\n        return fWeakCnt.load(std::memory_order_relaxed);\n    }\n\n    void validate() const {\n        this->INHERITED::validate();\n        SkASSERT(getWeakCnt() > 0);\n    }\n#endif\n\nprivate:\n    /** If fRefCnt is 0, returns 0.\n     *  Otherwise increments fRefCnt, acquires, and returns the old value.\n     */\n    int32_t atomic_conditional_acquire_strong_ref() const {\n        int32_t prev = fRefCnt.load(std::memory_order_relaxed);\n        do {\n            if (0 == prev) {\n                break;\n            }\n        } while(!fRefCnt.compare_exchange_weak(prev, prev+1, std::memory_order_acquire,\n                                                             std::memory_order_relaxed));\n        return prev;\n    }\n\npublic:\n    /** Creates a strong reference from a weak reference, if possible. The\n        caller must already be an owner. If try_ref() returns true the owner\n        is in posession of an additional strong reference. Both the original\n        reference and new reference must be properly unreferenced. If try_ref()\n        returns false, no strong reference could be created and the owner's\n        reference is in the same state as before the call.\n    */\n    bool SK_WARN_UNUSED_RESULT try_ref() const {\n        if (atomic_conditional_acquire_strong_ref() != 0) {\n            // Acquire barrier (L/SL), if not provided above.\n            // Prevents subsequent code from happening before the increment.\n            return true;\n        }\n        return false;\n    }\n\n    /** Increment the weak reference count. Must be balanced by a call to\n        weak_unref().\n    */\n    void weak_ref() const {\n        SkASSERT(getRefCnt() > 0);\n        SkASSERT(getWeakCnt() > 0);\n        // No barrier required.\n        (void)fWeakCnt.fetch_add(+1, std::memory_order_relaxed);\n    }\n\n    /** Decrement the weak reference count. If the weak reference count is 1\n        before the decrement, then call delete on the object. Note that if this\n        is the case, then the object needs to have been allocated via new, and\n        not on the stack.\n    */\n    void weak_unref() const {\n        SkASSERT(getWeakCnt() > 0);\n        // A release here acts in place of all releases we \"should\" have been doing in ref().\n        if (1 == fWeakCnt.fetch_add(-1, std::memory_order_acq_rel)) {\n            // Like try_ref(), the acquire is only needed on success, to make sure\n            // code in internal_dispose() doesn't happen before the decrement.\n#ifdef SK_DEBUG\n            // so our destructor won't complain\n            fWeakCnt.store(1, std::memory_order_relaxed);\n#endif\n            this->INHERITED::internal_dispose();\n        }\n    }\n\n    /** Returns true if there are no strong references to the object. When this\n        is the case all future calls to try_ref() will return false.\n    */\n    bool weak_expired() const {\n        return fRefCnt.load(std::memory_order_relaxed) == 0;\n    }\n\nprotected:\n    /** Called when the strong reference count goes to zero. This allows the\n        object to free any resources it may be holding. Weak references may\n        still exist and their level of allowed access to the object is defined\n        by the object's class.\n    */\n    virtual void weak_dispose() const {\n    }\n\nprivate:\n    /** Called when the strong reference count goes to zero. Calls weak_dispose\n        on the object and releases the implicit weak reference held\n        collectively by the strong references.\n    */\n    void internal_dispose() const override {\n        weak_dispose();\n        weak_unref();\n    }\n\n    /* Invariant: fWeakCnt = #weak + (fRefCnt > 0 ? 1 : 0) */\n    mutable std::atomic<int32_t> fWeakCnt;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/svg/SkSVGCanvas.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkSVGCanvas_DEFINED\n#define SkSVGCanvas_DEFINED\n\n#include \"SkCanvas.h\"\n\nclass SkWStream;\nclass SkXMLWriter;\n\nclass SK_API SkSVGCanvas {\npublic:\n    /**\n     *  Returns a new canvas that will generate SVG commands from its draw calls, and send\n     *  them to the provided xmlwriter. Ownership of the xmlwriter is not transfered to the canvas,\n     *  but it must stay valid during the lifetime of the returned canvas.\n     *\n     *  The canvas may buffer some drawing calls, so the output is not guaranteed to be valid\n     *  or complete until the canvas instance is deleted.\n     *\n     *  The 'bounds' parameter defines an initial SVG viewport (viewBox attribute on the root\n     *  SVG element).\n     */\n    static std::unique_ptr<SkCanvas> Make(const SkRect& bounds, SkWStream*);\n\n    // Internal only.\n    static std::unique_ptr<SkCanvas> Make(const SkRect& bounds, SkXMLWriter*);\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkCamera.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n//  Inspired by Rob Johnson's most excellent QuickDraw GX sample code\n\n#ifndef SkCamera_DEFINED\n#define SkCamera_DEFINED\n\n#include \"SkMatrix.h\"\n\nclass SkCanvas;\n\nstruct SkUnit3D {\n    SkScalar fX, fY, fZ;\n\n    void set(SkScalar x, SkScalar y, SkScalar z) {\n        fX = x; fY = y; fZ = z;\n    }\n    static SkScalar Dot(const SkUnit3D&, const SkUnit3D&);\n    static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross);\n};\n\nstruct SkPoint3D {\n    SkScalar    fX, fY, fZ;\n\n    void set(SkScalar x, SkScalar y, SkScalar z) {\n        fX = x; fY = y; fZ = z;\n    }\n    SkScalar    normalize(SkUnit3D*) const;\n};\ntypedef SkPoint3D SkVector3D;\n\nstruct SkMatrix3D {\n    SkScalar    fMat[3][4];\n\n    void reset();\n\n    void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0) {\n        SkASSERT((unsigned)row < 3);\n        fMat[row][0] = a;\n        fMat[row][1] = b;\n        fMat[row][2] = c;\n        fMat[row][3] = d;\n    }\n\n    void setRotateX(SkScalar deg);\n    void setRotateY(SkScalar deg);\n    void setRotateZ(SkScalar deg);\n    void setTranslate(SkScalar x, SkScalar y, SkScalar z);\n\n    void preRotateX(SkScalar deg);\n    void preRotateY(SkScalar deg);\n    void preRotateZ(SkScalar deg);\n    void preTranslate(SkScalar x, SkScalar y, SkScalar z);\n\n    void setConcat(const SkMatrix3D& a, const SkMatrix3D& b);\n    void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const;\n    void mapVector(const SkVector3D& src, SkVector3D* dst) const;\n\n    void mapPoint(SkPoint3D* v) const {\n        this->mapPoint(*v, v);\n    }\n\n    void mapVector(SkVector3D* v) const {\n        this->mapVector(*v, v);\n    }\n};\n\nclass SkPatch3D {\npublic:\n    SkPatch3D();\n\n    void    reset();\n    void    transform(const SkMatrix3D&, SkPatch3D* dst = nullptr) const;\n\n    // dot a unit vector with the patch's normal\n    SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const;\n    SkScalar dotWith(const SkVector3D& v) const {\n        return this->dotWith(v.fX, v.fY, v.fZ);\n    }\n\n    // deprecated, but still here for animator (for now)\n    void rotate(SkScalar /*x*/, SkScalar /*y*/, SkScalar /*z*/) {}\n    void rotateDegrees(SkScalar /*x*/, SkScalar /*y*/, SkScalar /*z*/) {}\n\nprivate:\npublic: // make public for SkDraw3D for now\n    SkVector3D  fU, fV;\n    SkPoint3D   fOrigin;\n\n    friend class SkCamera3D;\n};\n\nclass SkCamera3D {\npublic:\n    SkCamera3D();\n\n    void reset();\n    void update();\n    void patchToMatrix(const SkPatch3D&, SkMatrix* matrix) const;\n\n    SkPoint3D   fLocation;   // origin of the camera's space\n    SkPoint3D   fAxis;       // view direction\n    SkPoint3D   fZenith;     // up direction\n    SkPoint3D   fObserver;   // eye position (may not be the same as the origin)\n\nprivate:\n    mutable SkMatrix    fOrientation;\n    mutable bool        fNeedToUpdate;\n\n    void doUpdate() const;\n};\n\nclass SK_API Sk3DView : SkNoncopyable {\npublic:\n    Sk3DView();\n    ~Sk3DView();\n\n    void save();\n    void restore();\n\n    void translate(SkScalar x, SkScalar y, SkScalar z);\n    void rotateX(SkScalar deg);\n    void rotateY(SkScalar deg);\n    void rotateZ(SkScalar deg);\n\n#ifdef SK_BUILD_FOR_ANDROID\n    void setCameraLocation(SkScalar x, SkScalar y, SkScalar z);\n    SkScalar getCameraLocationX();\n    SkScalar getCameraLocationY();\n    SkScalar getCameraLocationZ();\n#endif\n\n    void getMatrix(SkMatrix*) const;\n    void applyToCanvas(SkCanvas*) const;\n\n    SkScalar dotWithNormal(SkScalar dx, SkScalar dy, SkScalar dz) const;\n\nprivate:\n    struct Rec {\n        Rec*        fNext;\n        SkMatrix3D  fMatrix;\n    };\n    Rec*        fRec;\n    Rec         fInitialRec;\n    SkCamera3D  fCamera;\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkCanvasStateUtils.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkCanvasStateUtils_DEFINED\n#define SkCanvasStateUtils_DEFINED\n\n#include \"SkCanvas.h\"\n\nclass SkCanvasState;\n\n/**\n * A set of functions that are useful for copying the state of an SkCanvas\n * across a library boundary where the Skia library on the other side of the\n * boundary may be newer. The expected usage is outline below...\n *\n *                          Lib Boundary\n * CaptureCanvasState(...)      |||\n *   SkCanvas --> SkCanvasState |||\n *                              ||| CreateFromCanvasState(...)\n *                              |||   SkCanvasState --> SkCanvas`\n *                              ||| Draw into SkCanvas`\n *                              ||| Unref SkCanvas`\n * ReleaseCanvasState(...)      |||\n *\n */\nclass SK_API SkCanvasStateUtils {\npublic:\n    /**\n     * Captures the current state of the canvas into an opaque ptr that is safe\n     * to pass to a different instance of Skia (which may be the same version,\n     * or may be newer). The function will return NULL in the event that one of the\n     * following conditions are true.\n     *  1) the canvas device type is not supported (currently only raster is supported)\n     *  2) the canvas clip type is not supported (currently only non-AA clips are supported)\n     *\n     * It is recommended that the original canvas also not be used until all\n     * canvases that have been created using its captured state have been dereferenced.\n     *\n     * Finally, it is important to note that any draw filters attached to the\n     * canvas are NOT currently captured.\n     *\n     * @param canvas The canvas you wish to capture the current state of.\n     * @return NULL or an opaque ptr that can be passed to CreateFromCanvasState\n     *         to reconstruct the canvas. The caller is responsible for calling\n     *         ReleaseCanvasState to free the memory associated with this state.\n     */\n    static SkCanvasState* CaptureCanvasState(SkCanvas* canvas);\n\n    /**\n     * Create a new SkCanvas from the captured state of another SkCanvas. The\n     * function will return NULL in the event that one of the\n     * following conditions are true.\n     *  1) the captured state is in an unrecognized format\n     *  2) the captured canvas device type is not supported\n     *\n     * @param state Opaque object created by CaptureCanvasState.\n     * @return NULL or an SkCanvas* whose devices and matrix/clip state are\n     *         identical to the captured canvas. The caller is responsible for\n     *         calling unref on the SkCanvas.\n     */\n    static std::unique_ptr<SkCanvas> MakeFromCanvasState(const SkCanvasState* state);\n\n    /**\n     * Free the memory associated with the captured canvas state.  The state\n     * should not be released until all SkCanvas objects created using that\n     * state have been dereferenced. Must be called from the same library\n     * instance that created the state via CaptureCanvasState.\n     *\n     * @param state The captured state you wish to dispose of.\n     */\n    static void ReleaseCanvasState(SkCanvasState* state);\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkEventTracer.h",
    "content": "/*\n * Copyright (C) 2014 Google Inc. All rights reserved.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEventTracer_DEFINED\n#define SkEventTracer_DEFINED\n\n// The class in this header defines the interface between Skia's internal\n// tracing macros and an external entity (e.g., Chrome) that will consume them.\n// Such an entity should subclass SkEventTracer and provide an instance of\n// that event to SkEventTracer::SetInstance.\n\n// If you're looking for the tracing macros to instrument Skia itself, those\n// live in src/core/SkTraceEvent.h\n\n#include \"SkTypes.h\"\n\nclass SK_API SkEventTracer {\npublic:\n\n    typedef uint64_t Handle;\n\n    /**\n     * If this is the first call to SetInstance or GetInstance then the passed instance is\n     * installed and true is returned. Otherwise, false is returned. In either case ownership of the\n     * tracer is transferred and it will be deleted when no longer needed.\n     */\n    static bool SetInstance(SkEventTracer*);\n\n    /**\n     * Gets the event tracer. If this is the first call to SetInstance or GetIntance then a default\n     * event tracer is installed and returned.\n     */\n    static SkEventTracer* GetInstance();\n\n    virtual ~SkEventTracer() { }\n\n    // The pointer returned from GetCategoryGroupEnabled() points to a\n    // value with zero or more of the following bits. Used in this class only.\n    // The TRACE_EVENT macros should only use the value as a bool.\n    // These values must be in sync with macro values in trace_event.h in chromium.\n    enum CategoryGroupEnabledFlags {\n        // Category group enabled for the recording mode.\n        kEnabledForRecording_CategoryGroupEnabledFlags = 1 << 0,\n        // Category group enabled for the monitoring mode.\n        kEnabledForMonitoring_CategoryGroupEnabledFlags = 1 << 1,\n        // Category group enabled by SetEventCallbackEnabled().\n        kEnabledForEventCallback_CategoryGroupEnabledFlags = 1 << 2,\n    };\n\n    virtual const uint8_t* getCategoryGroupEnabled(const char* name) = 0;\n    virtual const char* getCategoryGroupName(const uint8_t* categoryEnabledFlag) = 0;\n\n    virtual SkEventTracer::Handle\n        addTraceEvent(char phase,\n                      const uint8_t* categoryEnabledFlag,\n                      const char* name,\n                      uint64_t id,\n                      int32_t numArgs,\n                      const char** argNames,\n                      const uint8_t* argTypes,\n                      const uint64_t* argValues,\n                      uint8_t flags) = 0;\n\n    virtual void\n        updateTraceEventDuration(const uint8_t* categoryEnabledFlag,\n                                 const char* name,\n                                 SkEventTracer::Handle handle) = 0;\n};\n\n#endif // SkEventTracer_DEFINED\n"
  },
  {
    "path": "include/utils/SkFrontBufferedStream.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkFrontBufferedStream_DEFINED\n#define SkFrontBufferedStream_DEFINED\n\n#include \"SkStream.h\"\n\n/**\n *  Specialized stream that buffers the first X bytes of a stream,\n *  where X is passed in by the user. Note that unlike some buffered\n *  stream APIs, once more bytes than can fit in the buffer are read,\n *  no more buffering is done. This stream is designed for a use case\n *  where the caller knows that rewind will only be called from within\n *  X bytes (inclusive), and the wrapped stream is not necessarily\n *  able to rewind at all.\n */\nclass SK_API SkFrontBufferedStream {\npublic:\n    /**\n     *  Creates a new stream that wraps and buffers an SkStream.\n     *  @param stream SkStream to buffer. If stream is NULL, NULL is\n     *      returned. When this call succeeds (i.e. returns non NULL),\n     *      SkFrontBufferedStream is expected to be the only owner of\n     *      stream, so it should no be longer used directly.\n     *      SkFrontBufferedStream will delete stream upon deletion.\n     *  @param minBufferSize Minimum size of buffer required.\n     *  @return An SkStream that can buffer at least minBufferSize, or\n     *      NULL on failure. The caller is required to delete when finished with\n     *      this object.\n     */\n    static std::unique_ptr<SkStreamRewindable> Make(std::unique_ptr<SkStream> stream,\n                                                    size_t minBufferSize);\n};\n#endif  // SkFrontBufferedStream_DEFINED\n"
  },
  {
    "path": "include/utils/SkInterpolator.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkInterpolator_DEFINED\n#define SkInterpolator_DEFINED\n\n#include \"SkScalar.h\"\n\nclass SK_API SkInterpolatorBase : SkNoncopyable {\npublic:\n    enum Result {\n        kNormal_Result,\n        kFreezeStart_Result,\n        kFreezeEnd_Result\n    };\nprotected:\n    SkInterpolatorBase();\n    ~SkInterpolatorBase();\npublic:\n    void    reset(int elemCount, int frameCount);\n\n    /** Return the start and end time for this interpolator.\n        If there are no key frames, return false.\n        @param startTime If not null, returns the time (in milliseconds) of the\n                         first keyframe. If there are no keyframes, this param\n                         is ignored (left unchanged).\n        @param endTime If not null, returns the time (in milliseconds) of the\n                       last keyframe. If there are no keyframes, this parameter\n                       is ignored (left unchanged).\n        @return True if there are key frames, or false if there are none.\n    */\n    bool    getDuration(SkMSec* startTime, SkMSec* endTime) const;\n\n\n    /** Set the whether the repeat is mirrored.\n        @param mirror If true, the odd repeats interpolate from the last key\n                      frame and the first.\n    */\n    void setMirror(bool mirror) {\n        fFlags = SkToU8((fFlags & ~kMirror) | (int)mirror);\n    }\n\n    /** Set the repeat count. The repeat count may be fractional.\n        @param repeatCount Multiplies the total time by this scalar.\n    */\n    void    setRepeatCount(SkScalar repeatCount) { fRepeat = repeatCount; }\n\n    /** Set the whether the repeat is mirrored.\n        @param reset If true, the odd repeats interpolate from the last key\n                     frame and the first.\n    */\n    void setReset(bool reset) {\n        fFlags = SkToU8((fFlags & ~kReset) | (int)reset);\n    }\n\n    Result  timeToT(SkMSec time, SkScalar* T, int* index, bool* exact) const;\n\nprotected:\n    enum Flags {\n        kMirror = 1,\n        kReset = 2,\n        kHasBlend = 4\n    };\n    static SkScalar ComputeRelativeT(SkMSec time, SkMSec prevTime, SkMSec nextTime,\n                                     const SkScalar blend[4] = nullptr);\n    int16_t fFrameCount;\n    uint8_t fElemCount;\n    uint8_t fFlags;\n    SkScalar fRepeat;\n    struct SkTimeCode {\n        SkMSec  fTime;\n        SkScalar fBlend[4];\n    };\n    SkTimeCode* fTimes;     // pointer into fStorage\n    void* fStorage;\n#ifdef SK_DEBUG\n    SkTimeCode(* fTimesArray)[10];\n#endif\n};\n\nclass SK_API SkInterpolator : public SkInterpolatorBase {\npublic:\n    SkInterpolator();\n    SkInterpolator(int elemCount, int frameCount);\n    void    reset(int elemCount, int frameCount);\n\n    /** Add or replace a key frame, copying the values[] data into the\n        interpolator.\n        @param index    The index of this frame (frames must be ordered by time)\n        @param time The millisecond time for this frame\n        @param values   The array of values [elemCount] for this frame. The data\n                        is copied into the interpolator.\n        @param blend    A positive scalar specifying how to blend between this\n                        and the next key frame. [0...1) is a cubic lag/log/lag\n                        blend (slow to change at the beginning and end)\n                        1 is a linear blend (default)\n    */\n    bool setKeyFrame(int index, SkMSec time, const SkScalar values[],\n                     const SkScalar blend[4] = nullptr);\n\n    /** Return the computed values given the specified time. Return whether\n        those values are the result of pinning to either the first\n        (kFreezeStart) or last (kFreezeEnd), or from interpolated the two\n        nearest key values (kNormal).\n        @param time The time to sample (in milliseconds)\n        @param (may be null) where to write the computed values.\n    */\n    Result timeToValues(SkMSec time, SkScalar values[] = nullptr) const;\n\nprivate:\n    SkScalar* fValues;  // pointer into fStorage\n#ifdef SK_DEBUG\n    SkScalar(* fScalarsArray)[10];\n#endif\n    typedef SkInterpolatorBase INHERITED;\n};\n\n/** Interpolate a cubic curve, typically to provide an ease-in ease-out transition.\n    All the parameters are in the range of [0...1].\n    The input value is treated as the x-coordinate of the cubic.\n    The output value is the y-coordinate on the cubic at the x-coordinate.\n\n    @param value        The x-coordinate pinned between [0..1].\n    @param bx,by,cx,cy  The cubic control points where the cubic is specified\n                        as (0,0) (bx,by) (cx,cy) (1,1)\n    @return             the corresponding y-coordinate value, from [0..1].\n*/\nSkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by,\n                           SkScalar cx, SkScalar cy);\n\n#endif\n"
  },
  {
    "path": "include/utils/SkLua.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkLua_DEFINED\n#define SkLua_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkPathEffect.h\"\n#include \"SkScalar.h\"\n#include \"SkString.h\"\n\nstruct lua_State;\n\nclass SkCanvas;\nclass SkMatrix;\nclass SkPaint;\nclass SkPath;\nstruct SkRect;\nclass SkRRect;\nclass SkTextBlob;\n\n#define SkScalarToLua(x)    SkScalarToDouble(x)\n#define SkLuaToScalar(x)    SkDoubleToScalar(x)\n\nclass SkLua {\npublic:\n    static void Load(lua_State*);\n\n    SkLua(const char termCode[] = nullptr); // creates a new L, will close it\n    SkLua(lua_State*);                      // uses L, will not close it\n    ~SkLua();\n\n    lua_State* get() const { return fL; }\n    lua_State* operator*() const { return fL; }\n    lua_State* operator->() const { return fL; }\n\n    bool runCode(const char code[]);\n    bool runCode(const void* code, size_t size);\n\n    void pushBool(bool, const char tableKey[] = nullptr);\n    void pushString(const char[], const char tableKey[] = nullptr);\n    void pushString(const char[], size_t len, const char tableKey[] = nullptr);\n    void pushString(const SkString&, const char tableKey[] = nullptr);\n    void pushArrayU16(const uint16_t[], int count, const char tableKey[] = nullptr);\n    void pushArrayPoint(const SkPoint[], int count, const char key[] = nullptr);\n    void pushArrayScalar(const SkScalar[], int count, const char key[] = nullptr);\n    void pushColor(SkColor, const char tableKey[] = nullptr);\n    void pushU32(uint32_t, const char tableKey[] = nullptr);\n    void pushScalar(SkScalar, const char tableKey[] = nullptr);\n    void pushRect(const SkRect&, const char tableKey[] = nullptr);\n    void pushRRect(const SkRRect&, const char tableKey[] = nullptr);\n    void pushDash(const SkPathEffect::DashInfo&, const char tableKey[] = nullptr);\n    void pushMatrix(const SkMatrix&, const char tableKey[] = nullptr);\n    void pushPaint(const SkPaint&, const char tableKey[] = nullptr);\n    void pushPath(const SkPath&, const char tableKey[] = nullptr);\n    void pushCanvas(SkCanvas*, const char tableKey[] = nullptr);\n    void pushTextBlob(const SkTextBlob*, const char tableKey[] = nullptr);\n\nprivate:\n    lua_State*  fL;\n    SkString    fTermCode;\n    bool        fWeOwnL;\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkLuaCanvas.h",
    "content": "/*\n * Copyright 2013 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkLuaCanvas_DEFINED\n#define SkLuaCanvas_DEFINED\n\n#include \"SkCanvas.h\"\n#include \"SkString.h\"\n#include \"SkVertices.h\"\n\nstruct lua_State;\n\nclass SkLuaCanvas : public SkCanvas {\npublic:\n    void pushThis();\n\n    SkLuaCanvas(int width, int height, lua_State*, const char function[]);\n    ~SkLuaCanvas() override;\n\nprotected:\n    void willSave() override;\n    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;\n    void willRestore() override;\n\n    void didConcat(const SkMatrix&) override;\n    void didSetMatrix(const SkMatrix&) override;\n\n    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;\n    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,\n                            const SkPaint&) override;\n    virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],\n                               const SkPaint&) override;\n    virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],\n                                SkScalar constY, const SkPaint&) override;\n    virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,\n                                  const SkMatrix* matrix, const SkPaint&) override;\n    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                           const SkRect* cull, const SkPaint& paint) override;\n    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,\n                                const SkPaint& paint) override;\n\n    void onDrawPaint(const SkPaint&) override;\n    void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;\n    void onDrawRect(const SkRect&, const SkPaint&) override;\n    void onDrawOval(const SkRect&, const SkPaint&) override;\n    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;\n    void onDrawRRect(const SkRRect&, const SkPaint&) override;\n    void onDrawPath(const SkPath&, const SkPaint&) override;\n    void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,\n                          SrcRectConstraint) override;\n    void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,\n                         const SkPaint*, SrcRectConstraint) override;\n    void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,\n                          const SkPaint*) override;\n    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;\n\n    void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;\n    void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;\n    void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;\n    void onClipRegion(const SkRegion&, SkClipOp) override;\n\n    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;\n    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;\n\nprivate:\n    lua_State*  fL;\n    SkString    fFunc;\n\n    void sendverb(const char verb[]);\n\n    typedef SkCanvas INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkNWayCanvas.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkNWayCanvas_DEFINED\n#define SkNWayCanvas_DEFINED\n\n#include \"../private/SkTDArray.h\"\n#include \"SkCanvasVirtualEnforcer.h\"\n#include \"SkNoDrawCanvas.h\"\n\nclass SK_API SkNWayCanvas : public SkCanvasVirtualEnforcer<SkNoDrawCanvas> {\npublic:\n    SkNWayCanvas(int width, int height);\n    ~SkNWayCanvas() override;\n\n    virtual void addCanvas(SkCanvas*);\n    virtual void removeCanvas(SkCanvas*);\n    virtual void removeAll();\n\n    ///////////////////////////////////////////////////////////////////////////\n    // These are forwarded to the N canvases we're referencing\n\n#ifdef SK_SUPPORT_LEGACY_DRAWFILTER\n    SkDrawFilter* setDrawFilter(SkDrawFilter*) override;\n#endif\n\nprotected:\n    SkTDArray<SkCanvas*> fList;\n\n    void willSave() override;\n    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;\n    void willRestore() override;\n\n    void didConcat(const SkMatrix&) override;\n    void didSetMatrix(const SkMatrix&) override;\n\n    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;\n    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,\n                            const SkPaint&) override;\n    virtual void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],\n                               const SkPaint&) override;\n    virtual void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],\n                                SkScalar constY, const SkPaint&) override;\n    virtual void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,\n                                  const SkMatrix* matrix, const SkPaint&) override;\n    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,\n                                const SkPaint& paint) override;\n    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                           const SkRect* cull, const SkPaint& paint) override;\n    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                             const SkPoint texCoords[4], SkBlendMode,\n                             const SkPaint& paint) override;\n\n    void onDrawPaint(const SkPaint&) override;\n    void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;\n    void onDrawRect(const SkRect&, const SkPaint&) override;\n    void onDrawRegion(const SkRegion&, const SkPaint&) override;\n    void onDrawOval(const SkRect&, const SkPaint&) override;\n    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;\n    void onDrawRRect(const SkRRect&, const SkPaint&) override;\n    void onDrawPath(const SkPath&, const SkPaint&) override;\n    void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,\n                          SrcRectConstraint) override;\n    void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,\n                         const SkPaint*, SrcRectConstraint) override;\n    void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,\n                             const SkPaint*) override;\n    void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&,\n                            const SkPaint*) override;\n    void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,\n                         const SkPaint*) override;\n    void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,\n                          const SkPaint*) override;\n    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;\n    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],\n                     int, SkBlendMode, const SkRect*, const SkPaint*) override;\n    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;\n\n    void onClipRect(const SkRect&, SkClipOp, ClipEdgeStyle) override;\n    void onClipRRect(const SkRRect&, SkClipOp, ClipEdgeStyle) override;\n    void onClipPath(const SkPath&, SkClipOp, ClipEdgeStyle) override;\n    void onClipRegion(const SkRegion&, SkClipOp) override;\n\n    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;\n    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;\n    void onDrawAnnotation(const SkRect&, const char[], SkData*) override;\n\n    void onFlush() override;\n\n    class Iter;\n\nprivate:\n    typedef SkCanvasVirtualEnforcer<SkNoDrawCanvas> INHERITED;\n};\n\n\n#endif\n"
  },
  {
    "path": "include/utils/SkNoDrawCanvas.h",
    "content": "/*\n * Copyright 2016 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkNoDrawCanvas_DEFINED\n#define SkNoDrawCanvas_DEFINED\n\n#include \"SkCanvas.h\"\n#include \"SkCanvasVirtualEnforcer.h\"\n#include \"SkVertices.h\"\n\nstruct SkIRect;\n\n// SkNoDrawCanvas is a helper for SkCanvas subclasses which do not need to\n// actually rasterize (e.g., analysis of the draw calls).\n//\n// It provides the following simplifications:\n//\n//   * not backed by any device/pixels\n//   * conservative clipping (clipping calls only use rectangles)\n//\nclass SK_API SkNoDrawCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {\npublic:\n    SkNoDrawCanvas(int width, int height);\n\n    // TODO: investigate the users of this ctor.\n    SkNoDrawCanvas(const SkIRect&);\n\n    explicit SkNoDrawCanvas(sk_sp<SkBaseDevice> device);\n\n    // Optimization to reset state to be the same as after construction.\n    void resetCanvas(int width, int height) {\n        resetForNextPicture(SkIRect::MakeWH(width, height));\n    }\n\nprotected:\n    SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;\n\n    // No-op overrides for aborting rasterization earlier than SkNullBlitter.\n    void onDrawAnnotation(const SkRect&, const char[], SkData*) override {}\n    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override {}\n    void onDrawDrawable(SkDrawable*, const SkMatrix*) override {}\n    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override {}\n    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override {}\n    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override {}\n    void onDrawTextOnPath(const void*, size_t, const SkPath&, const SkMatrix*,\n                          const SkPaint&) override {}\n    void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,\n                           const SkPaint&) override {}\n    void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override {}\n    void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,\n                     const SkPaint&) override {}\n\n    void onDrawPaint(const SkPaint&) override {}\n    void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override {}\n    void onDrawRect(const SkRect&, const SkPaint&) override {}\n    void onDrawRegion(const SkRegion&, const SkPaint&) override {}\n    void onDrawOval(const SkRect&, const SkPaint&) override {}\n    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override {}\n    void onDrawRRect(const SkRRect&, const SkPaint&) override {}\n    void onDrawPath(const SkPath&, const SkPaint&) override {}\n    void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override {}\n    void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,\n                          SrcRectConstraint) override {}\n    void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override {}\n    void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,\n                         SrcRectConstraint) override {}\n    void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override {}\n    void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&,\n                          const SkPaint*) override {}\n    void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&,\n                            const SkPaint*) override {}\n    void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,\n                             const SkPaint*) override {}\n    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override {}\n    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],\n                     int, SkBlendMode, const SkRect*, const SkPaint*) override {}\n    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override {}\n    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override {}\n\nprivate:\n    typedef SkCanvasVirtualEnforcer<SkCanvas> INHERITED;\n};\n\n#endif // SkNoDrawCanvas_DEFINED\n"
  },
  {
    "path": "include/utils/SkNullCanvas.h",
    "content": "/*\n * Copyright 2012 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkNullCanvas_DEFINED\n#define SkNullCanvas_DEFINED\n\n#include \"SkCanvas.h\"\n\n/**\n * Creates a canvas that draws nothing. This is useful for performance testing.\n */\nSK_API std::unique_ptr<SkCanvas> SkMakeNullCanvas();\n\n#endif\n"
  },
  {
    "path": "include/utils/SkPaintFilterCanvas.h",
    "content": "/*\n * Copyright 2015 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkPaintFilterCanvas_DEFINED\n#define SkPaintFilterCanvas_DEFINED\n\n#include \"SkCanvasVirtualEnforcer.h\"\n#include \"SkNWayCanvas.h\"\n#include \"SkTLazy.h\"\n\n/** \\class SkPaintFilterCanvas\n\n    A utility proxy base class for implementing draw/paint filters.\n*/\nclass SK_API SkPaintFilterCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {\npublic:\n    /**\n     * The new SkPaintFilterCanvas is configured for forwarding to the\n     * specified canvas.  Also copies the target canvas matrix and clip bounds.\n     */\n    SkPaintFilterCanvas(SkCanvas* canvas);\n\n    enum Type {\n        kPaint_Type,\n        kPoint_Type,\n        kArc_Type,\n        kBitmap_Type,\n        kRect_Type,\n        kRRect_Type,\n        kDRRect_Type,\n        kOval_Type,\n        kPath_Type,\n        kPicture_Type,\n        kDrawable_Type,\n        kText_Type,\n        kTextBlob_Type,\n        kVertices_Type,\n        kPatch_Type,\n\n        kTypeCount\n    };\n\n    // Forwarded to the wrapped canvas.\n    SkISize getBaseLayerSize() const override { return proxy()->getBaseLayerSize(); }\n    GrContext*  getGrContext() override { return proxy()->getGrContext();     }\n    GrRenderTargetContext* internal_private_accessTopLayerRenderTargetContext() override {\n        return proxy()->internal_private_accessTopLayerRenderTargetContext();\n    }\n\nprotected:\n    /**\n     *  Called with the paint that will be used to draw the specified type.\n     *  The implementation may modify the paint as they wish (using SkTCopyOnFirstWrite::writable).\n     *\n     *  The result bool is used to determine whether the draw op is to be\n     *  executed (true) or skipped (false).\n     *\n     *  Note: The base implementation calls onFilter() for top-level/explicit paints only.\n     *        To also filter encapsulated paints (e.g. SkPicture, SkTextBlob), clients may need to\n     *        override the relevant methods (i.e. drawPicture, drawTextBlob).\n     */\n    virtual bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type type) const = 0;\n\n    void onDrawPaint(const SkPaint&) override;\n    void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) override;\n    void onDrawRect(const SkRect&, const SkPaint&) override;\n    void onDrawRRect(const SkRRect&, const SkPaint&) override;\n    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;\n    void onDrawRegion(const SkRegion&, const SkPaint&) override;\n    void onDrawOval(const SkRect&, const SkPaint&) override;\n    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;\n    void onDrawPath(const SkPath&, const SkPaint&) override;\n    void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst, const SkPaint*,\n                          SrcRectConstraint) override;\n    void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,\n                          const SkPaint*) override;\n    void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,\n                             const SkPaint*) override;\n    void onDrawImage(const SkImage*, SkScalar left, SkScalar top, const SkPaint*) override;\n    void onDrawImageRect(const SkImage*, const SkRect* src, const SkRect& dst,\n                         const SkPaint*, SrcRectConstraint) override;\n    void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst,\n                         const SkPaint*) override;\n    void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&,\n                            const SkPaint*) override;\n    void onDrawVerticesObject(const SkVertices*, SkBlendMode, const SkPaint&) override;\n    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],\n                             const SkPoint texCoords[4], SkBlendMode,\n                             const SkPaint& paint) override;\n    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;\n    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;\n\n    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,\n                    const SkPaint&) override;\n    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],\n                       const SkPaint&) override;\n    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],\n                        SkScalar constY, const SkPaint&) override;\n    void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,\n                          const SkMatrix* matrix, const SkPaint&) override;\n    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],\n                           const SkRect* cull, const SkPaint& paint) override;\n    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,\n                        const SkPaint& paint) override;\n    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],\n                     int, SkBlendMode, const SkRect*, const SkPaint*) override;\n    void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override;\n    void onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) override;\n\n    // Forwarded to the wrapped canvas.\n    sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;\n    bool onPeekPixels(SkPixmap* pixmap) override;\n    bool onAccessTopLayerPixels(SkPixmap* pixmap) override;\n    SkImageInfo onImageInfo() const override;\n    bool onGetProps(SkSurfaceProps* props) const override;\n\nprivate:\n    class AutoPaintFilter;\n\n    SkCanvas* proxy() const { SkASSERT(fList.count() == 1); return fList[0]; }\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkParse.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkParse_DEFINED\n#define SkParse_DEFINED\n\n#include \"SkColor.h\"\n\nclass SK_API SkParse {\npublic:\n    static int Count(const char str[]); // number of scalars or int values\n    static int Count(const char str[], char separator);\n    static const char* FindColor(const char str[], SkColor* value);\n    static const char* FindHex(const char str[], uint32_t* value);\n    static const char* FindMSec(const char str[], SkMSec* value);\n    static const char* FindNamedColor(const char str[], size_t len, SkColor* color);\n    static const char* FindS32(const char str[], int32_t* value);\n    static const char* FindScalar(const char str[], SkScalar* value);\n    static const char* FindScalars(const char str[], SkScalar value[], int count);\n\n    static bool FindBool(const char str[], bool* value);\n    // return the index of str in list[], or -1 if not found\n    static int  FindList(const char str[], const char list[]);\n#ifdef SK_SUPPORT_UNITTEST\n    static void TestColor();\n    static void UnitTest();\n#endif\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkParsePath.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkParsePath_DEFINED\n#define SkParsePath_DEFINED\n\n#include \"SkPath.h\"\n\nclass SkString;\n\nclass SkParsePath {\npublic:\n    static bool FromSVGString(const char str[], SkPath*);\n    static void ToSVGString(const SkPath&, SkString*);\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkRandom.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkRandom_DEFINED\n#define SkRandom_DEFINED\n\n#include \"../private/SkFixed.h\"\n#include \"../private/SkFloatBits.h\"\n#include \"SkScalar.h\"\n\n/** \\class SkRandom\n\n Utility class that implements pseudo random 32bit numbers using Marsaglia's\n multiply-with-carry \"mother of all\" algorithm. Unlike rand(), this class holds\n its own state, so that multiple instances can be used with no side-effects.\n\n Has a large period and all bits are well-randomized.\n */\nclass SkRandom {\npublic:\n    SkRandom() { init(0); }\n    SkRandom(uint32_t seed) { init(seed); }\n    SkRandom(const SkRandom& rand) : fK(rand.fK), fJ(rand.fJ) {}\n\n    SkRandom& operator=(const SkRandom& rand) {\n        fK = rand.fK;\n        fJ = rand.fJ;\n\n        return *this;\n    }\n\n    /** Return the next pseudo random number as an unsigned 32bit value.\n     */\n    uint32_t nextU() {\n        fK = kKMul*(fK & 0xffff) + (fK >> 16);\n        fJ = kJMul*(fJ & 0xffff) + (fJ >> 16);\n        return (((fK << 16) | (fK >> 16)) + fJ);\n    }\n\n    /** Return the next pseudo random number as a signed 32bit value.\n     */\n    int32_t nextS() { return (int32_t)this->nextU(); }\n\n    /** Return the next pseudo random number as an unsigned 16bit value.\n     */\n    U16CPU nextU16() { return this->nextU() >> 16; }\n\n    /** Return the next pseudo random number as a signed 16bit value.\n     */\n    S16CPU nextS16() { return this->nextS() >> 16; }\n\n    /**\n     *  Returns value [0...1) as an IEEE float\n     */\n    float nextF() {\n        unsigned int floatint = 0x3f800000 | (this->nextU() >> 9);\n        float f = SkBits2Float(floatint) - 1.0f;\n        return f;\n    }\n\n    /**\n     *  Returns value [min...max) as a float\n     */\n    float nextRangeF(float min, float max) {\n        return min + this->nextF() * (max - min);\n    }\n\n    /** Return the next pseudo random number, as an unsigned value of\n     at most bitCount bits.\n     @param bitCount The maximum number of bits to be returned\n     */\n    uint32_t nextBits(unsigned bitCount) {\n        SkASSERT(bitCount > 0 && bitCount <= 32);\n        return this->nextU() >> (32 - bitCount);\n    }\n\n    /** Return the next pseudo random unsigned number, mapped to lie within\n     [min, max] inclusive.\n     */\n    uint32_t nextRangeU(uint32_t min, uint32_t max) {\n        SkASSERT(min <= max);\n        uint32_t range = max - min + 1;\n        if (0 == range) {\n            return this->nextU();\n        } else {\n            return min + this->nextU() % range;\n        }\n    }\n\n    /** Return the next pseudo random unsigned number, mapped to lie within\n     [0, count).\n     */\n    uint32_t nextULessThan(uint32_t count) {\n        SkASSERT(count > 0);\n        return this->nextRangeU(0, count - 1);\n    }\n\n    /** Return the next pseudo random number expressed as a SkScalar\n     in the range [0..SK_Scalar1).\n     */\n    SkScalar nextUScalar1() { return SkFixedToScalar(this->nextUFixed1()); }\n\n    /** Return the next pseudo random number expressed as a SkScalar\n     in the range [min..max).\n     */\n    SkScalar nextRangeScalar(SkScalar min, SkScalar max) {\n        return this->nextUScalar1() * (max - min) + min;\n    }\n\n    /** Return the next pseudo random number expressed as a SkScalar\n     in the range [-SK_Scalar1..SK_Scalar1).\n     */\n    SkScalar nextSScalar1() { return SkFixedToScalar(this->nextSFixed1()); }\n\n    /** Return the next pseudo random number as a bool.\n     */\n    bool nextBool() { return this->nextU() >= 0x80000000; }\n\n    /** A biased version of nextBool().\n     */\n    bool nextBiasedBool(SkScalar fractionTrue) {\n        SkASSERT(fractionTrue >= 0 && fractionTrue <= SK_Scalar1);\n        return this->nextUScalar1() <= fractionTrue;\n    }\n\n    /**\n     *  Return the next pseudo random number as a signed 64bit value.\n     */\n    int64_t next64() {\n        int64_t hi = this->nextS();\n        return (hi << 32) | this->nextU();\n    }\n\n    /** Reset the random object.\n     */\n    void setSeed(uint32_t seed) { init(seed); }\n\nprivate:\n    // Initialize state variables with LCG.\n    // We must ensure that both J and K are non-zero, otherwise the\n    // multiply-with-carry step will forevermore return zero.\n    void init(uint32_t seed) {\n        fK = NextLCG(seed);\n        if (0 == fK) {\n            fK = NextLCG(fK);\n        }\n        fJ = NextLCG(fK);\n        if (0 == fJ) {\n            fJ = NextLCG(fJ);\n        }\n        SkASSERT(0 != fK && 0 != fJ);\n    }\n    static uint32_t NextLCG(uint32_t seed) { return kMul*seed + kAdd; }\n\n    /** Return the next pseudo random number expressed as an unsigned SkFixed\n     in the range [0..SK_Fixed1).\n     */\n    SkFixed nextUFixed1() { return this->nextU() >> 16; }\n\n    /** Return the next pseudo random number expressed as a signed SkFixed\n     in the range [-SK_Fixed1..SK_Fixed1).\n     */\n    SkFixed nextSFixed1() { return this->nextS() >> 15; }\n\n    //  See \"Numerical Recipes in C\", 1992 page 284 for these constants\n    //  For the LCG that sets the initial state from a seed\n    enum {\n        kMul = 1664525,\n        kAdd = 1013904223\n    };\n    // Constants for the multiply-with-carry steps\n    enum {\n        kKMul = 30345,\n        kJMul = 18000,\n    };\n\n    uint32_t fK;\n    uint32_t fJ;\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/SkShadowUtils.h",
    "content": "\n/*\n * Copyright 2017 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkShadowUtils_DEFINED\n#define SkShadowUtils_DEFINED\n\n#include \"SkColor.h\"\n#include \"SkPoint3.h\"\n#include \"SkScalar.h\"\n#include \"../private/SkShadowFlags.h\"\n\nclass SkCanvas;\nclass SkPath;\nclass SkResourceCache;\n\nclass SK_API SkShadowUtils {\npublic:\n    /**\n     * Draw an offset spot shadow and outlining ambient shadow for the given path using a disc\n     * light. The shadow may be cached, depending on the path type and canvas matrix. If the\n     * matrix is perspective or the path is volatile, it will not be cached.\n     *\n     * @param canvas  The canvas on which to draw the shadows.\n     * @param path  The occluder used to generate the shadows.\n     * @param zPlaneParams  Values for the plane function which returns the Z offset of the\n     *  occluder from the canvas based on local x and y values (the current matrix is not applied).\n     * @param lightPos  The 3D position of the light relative to the canvas plane. This is\n     *  independent of the canvas's current matrix.\n     * @param lightRadius  The radius of the disc light.\n     * @param ambientColor  The color of the ambient shadow.\n     * @param spotColor  The color of the spot shadow.\n     * @param flags  Options controlling opaque occluder optimizations and shadow appearance. See\n     *               SkShadowFlags.\n     */\n    static void DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoint3& zPlaneParams,\n                           const SkPoint3& lightPos, SkScalar lightRadius,\n                           SkColor ambientColor, SkColor spotColor,\n                           uint32_t flags = SkShadowFlags::kNone_ShadowFlag);\n\n    /**\n     * Helper routine to compute color values for one-pass tonal alpha.\n     *\n     * @param inAmbientColor  Original ambient color\n     * @param inSpotColor  Original spot color\n     * @param outAmbientColor  Modified ambient color\n     * @param outSpotColor  Modified spot color\n     */\n    static void ComputeTonalColors(SkColor inAmbientColor, SkColor inSpotColor,\n                                   SkColor* outAmbientColor, SkColor* outSpotColor);\n};\n\n#endif\n"
  },
  {
    "path": "include/utils/mac/SkCGUtils.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkCGUtils_DEFINED\n#define SkCGUtils_DEFINED\n\n#include \"SkSize.h\"\n#include \"SkImageInfo.h\"\n#include \"SkImage.h\"\n#include \"SkPixmap.h\"\n\n#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)\n\n#ifdef SK_BUILD_FOR_MAC\n#include <ApplicationServices/ApplicationServices.h>\n#endif\n\n#ifdef SK_BUILD_FOR_IOS\n#include <CoreGraphics/CoreGraphics.h>\n#endif\n\nclass SkBitmap;\nclass SkData;\nclass SkPixmap;\nclass SkStreamRewindable;\n\nSK_API CGContextRef SkCreateCGContext(const SkPixmap&);\n\n/**\n *  Given a CGImage, allocate an SkBitmap and copy the image's pixels into it. If scaleToFit is not\n *  null, use it to determine the size of the bitmap, and scale the image to fill the bitmap.\n *  Otherwise use the image's width/height.\n *\n *  On failure, return false, and leave bitmap unchanged.\n */\nSK_API bool SkCreateBitmapFromCGImage(SkBitmap* dst, CGImageRef src);\n\nSK_API sk_sp<SkImage> SkMakeImageFromCGImage(CGImageRef);\n\n/**\n *  Copy the pixels from src into the memory specified by info/rowBytes/dstPixels. On failure,\n *  return false (e.g. ImageInfo incompatible with src).\n */\nSK_API bool SkCopyPixelsFromCGImage(const SkImageInfo& info, size_t rowBytes, void* dstPixels,\n                                    CGImageRef src);\nstatic inline bool SkCopyPixelsFromCGImage(const SkPixmap& dst, CGImageRef src) {\n    return SkCopyPixelsFromCGImage(dst.info(), dst.rowBytes(), dst.writable_addr(), src);\n}\n\n/**\n *  Create an imageref from the specified bitmap using the specified colorspace.\n *  If space is NULL, then CGColorSpaceCreateDeviceRGB() is used.\n */\nSK_API CGImageRef SkCreateCGImageRefWithColorspace(const SkBitmap& bm,\n                                                   CGColorSpaceRef space);\n\n/**\n *  Create an imageref from the specified bitmap using the colorspace returned\n *  by CGColorSpaceCreateDeviceRGB()\n */\nstatic inline CGImageRef SkCreateCGImageRef(const SkBitmap& bm) {\n    return SkCreateCGImageRefWithColorspace(bm, NULL);\n}\n\n/**\n *  Draw the bitmap into the specified CG context. The bitmap will be converted\n *  to a CGImage using the generic RGB colorspace. (x,y) specifies the position\n *  of the top-left corner of the bitmap. The bitmap is converted using the\n *  colorspace returned by CGColorSpaceCreateDeviceRGB()\n */\nvoid SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);\n\n/**\n *  Return a provider that wraps the specified stream.\n *  When the provider is finally deleted, it will delete the stream.\n */\nCGDataProviderRef SkCreateDataProviderFromStream(std::unique_ptr<SkStreamRewindable>);\n\nCGDataProviderRef SkCreateDataProviderFromData(sk_sp<SkData>);\n\n#endif  // defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)\n#endif  // SkCGUtils_DEFINED\n"
  },
  {
    "path": "include/views/SkEvent.h",
    "content": "/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n#ifndef SkEvent_DEFINED\n#define SkEvent_DEFINED\n\n#include \"SkMetaData.h\"\n\n/** Unique 32bit id used to identify an instance of SkEventSink. When events are\n    posted, they are posted to a specific sinkID. When it is time to dispatch the\n    event, the sinkID is used to find the specific SkEventSink object. If it is found,\n    its doEvent() method is called with the event.\n*/\ntypedef uint32_t SkEventSinkID;\n\n/**\n *  \\class SkEvent\n *\n *  When an event is dispatched from the event queue, it is either sent to\n *  the eventsink matching the target ID (if not 0), or the target proc is\n *  called (if not NULL).\n */\nclass SkEvent {\npublic:\n    SkEvent();\n    explicit SkEvent(const char type[]);\n    SkEvent(const SkEvent& src);\n    ~SkEvent();\n\n    /** Returns true if the event's type matches exactly the specified type (case sensitive) */\n    bool isType(const char type[]) const;\n\n    /**\n     *  Set the event's type to the specified string.\n     */\n    void setType(const char type[]);\n\n    /**\n     *  Return the event's unnamed 32bit field. Default value is 0\n     */\n    uint32_t getFast32() const { return f32; }\n\n    /**\n     *  Set the event's unnamed 32bit field.\n     */\n    void setFast32(uint32_t x) { f32 = x; }\n\n    /** Return true if the event contains the named 32bit field, and return the field\n        in value (if value is non-null). If there is no matching named field, return false\n        and ignore the value parameter.\n    */\n    bool findS32(const char name[], int32_t* value = nullptr) const {\n        return fMeta.findS32(name, value);\n    }\n    /** Return true if the event contains the named SkScalar field, and return the field\n        in value (if value is non-null). If there is no matching named field, return false\n        and ignore the value parameter.\n    */\n    bool findScalar(const char name[], SkScalar* value = nullptr) const {\n        return fMeta.findScalar(name, value);\n    }\n    /** Return true if the event contains the named SkScalar field, and return the fields\n        in value[] (if value is non-null), and return the number of SkScalars in count (if count is non-null).\n        If there is no matching named field, return false and ignore the value and count parameters.\n    */\n    const SkScalar* findScalars(const char name[], int* count, SkScalar values[] = nullptr) const {\n        return fMeta.findScalars(name, count, values);\n    }\n    /** Return the value of the named string field, or if no matching named field exists, return null.\n    */\n    const char* findString(const char name[]) const { return fMeta.findString(name); }\n    /** Return true if the event contains the named pointer field, and return the field\n        in value (if value is non-null). If there is no matching named field, return false\n        and ignore the value parameter.\n    */\n    bool findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); }\n    bool findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); }\n    const void* findData(const char name[], size_t* byteCount = nullptr) const {\n        return fMeta.findData(name, byteCount);\n    }\n\n    /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */\n    bool hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); }\n    /** Returns true if ethe event contains the named SkScalar field, and if it equals the specified value */\n    bool hasScalar(const char name[], SkScalar value) const { return fMeta.hasScalar(name, value); }\n    /** Returns true if ethe event contains the named string field, and if it equals (using strcmp) the specified value */\n    bool hasString(const char name[], const char value[]) const { return fMeta.hasString(name, value); }\n    /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */\n    bool hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); }\n    bool hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); }\n    bool hasData(const char name[], const void* data, size_t byteCount) const {\n        return fMeta.hasData(name, data, byteCount);\n    }\n\n    /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */\n    void setS32(const char name[], int32_t value) { fMeta.setS32(name, value); }\n    /** Add/replace the named SkScalar field to the event. In XML use the subelement <data name=... scalar=... /> */\n    void setScalar(const char name[], SkScalar value) { fMeta.setScalar(name, value); }\n    /** Add/replace the named SkScalar[] field to the event. */\n    SkScalar* setScalars(const char name[], int count, const SkScalar values[] = nullptr) {\n        return fMeta.setScalars(name, count, values);\n    }\n    /** Add/replace the named string field to the event. In XML use the subelement <data name=... string=... */\n    void setString(const char name[], const char value[]) { fMeta.setString(name, value); }\n    /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */\n    void setPtr(const char name[], void* value) { fMeta.setPtr(name, value); }\n    void setBool(const char name[], bool value) { fMeta.setBool(name, value); }\n    void setData(const char name[], const void* data, size_t byteCount) {\n        fMeta.setData(name, data, byteCount);\n    }\n\n    /** Return the underlying metadata object */\n    SkMetaData& getMetaData() { return fMeta; }\n    /** Return the underlying metadata object */\n    const SkMetaData& getMetaData() const { return fMeta; }\n\n    ///////////////////////////////////////////////////////////////////////////\n\nprivate:\n    SkMetaData      fMeta;\n    char*           fType;\n    uint32_t        f32;\n\n    void initialize(const char* type);\n};\n\n#endif\n"
  },
  {
    "path": "include/views/SkEventSink.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkEventSink_DEFINED\n#define SkEventSink_DEFINED\n\n#include \"SkRefCnt.h\"\n#include \"SkEvent.h\"\n\n/** \\class SkEventSink\n\n    SkEventSink is the base class for all objects that receive SkEvents.\n*/\nclass SkEventSink : public SkRefCnt {\npublic:\n\n\n             SkEventSink();\n    virtual ~SkEventSink();\n\n    /**\n     *  Returns this eventsink's unique ID. Use this to post SkEvents to\n     *  this eventsink.\n     */\n    SkEventSinkID getSinkID() const { return fID; }\n\n    /**\n     *  Call this to pass an event to this object for processing. Returns true if the\n     *  event was handled.\n     */\n    bool doEvent(const SkEvent&);\n\n    /** Returns true if the sink (or one of its subclasses) understands the event as a query.\n        If so, the sink may modify the event to communicate its \"answer\".\n    */\n    bool doQuery(SkEvent* query);\n\n    /**\n     *  Returns the matching eventsink, or null if not found\n     */\n    static SkEventSink* FindSink(SkEventSinkID);\n\nprotected:\n    /** Override this to handle events in your subclass. Be sure to call the inherited version\n        for events that you don't handle.\n    */\n    virtual bool onEvent(const SkEvent&);\n    virtual bool onQuery(SkEvent*);\n\nprivate:\n    SkEventSinkID   fID;\n\n    // for our private link-list\n    SkEventSink*    fNextSink;\n\n    typedef SkRefCnt INHERITED;\n};\n\n#endif\n"
  },
  {
    "path": "include/views/SkKey.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkKey_DEFINED\n#define SkKey_DEFINED\n\n#include \"SkTypes.h\"\n\nenum SkModifierKeys {\n    kShift_SkModifierKey    = 1 << 0,\n    kControl_SkModifierKey  = 1 << 1,\n    kOption_SkModifierKey   = 1 << 2,   // same as ALT\n    kCommand_SkModifierKey  = 1 << 3,\n};\n\n#endif\n"
  },
  {
    "path": "include/views/SkTouchGesture.h",
    "content": "\n/*\n * Copyright 2011 Google Inc.\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n#ifndef SkTouchGesture_DEFINED\n#define SkTouchGesture_DEFINED\n\n#include \"../private/SkTDArray.h\"\n#include \"SkMatrix.h\"\n\nstruct SkFlingState {\n    SkFlingState() : fActive(false) {}\n\n    bool isActive() const { return fActive; }\n    void stop() { fActive = false; }\n\n    void reset(float sx, float sy);\n    bool evaluateMatrix(SkMatrix* matrix);\n\nprivate:\n    SkPoint     fDirection;\n    SkScalar    fSpeed0;\n    double      fTime0;\n    bool        fActive;\n};\n\nclass SkTouchGesture {\npublic:\n    SkTouchGesture();\n    ~SkTouchGesture();\n\n    void touchBegin(void* owner, float x, float y);\n    void touchMoved(void* owner, float x, float y);\n    void touchEnd(void* owner);\n    void reset();\n    void resetTouchState();\n\n    bool isActive() { return fFlinger.isActive(); }\n    void stop() { fFlinger.stop(); }\n    bool isBeingTouched() { return kEmpty_State != fState; }\n\n    const SkMatrix& localM();\n    const SkMatrix& globalM() const { return fGlobalM; }\n\n    void setTransLimit(const SkRect& contentRect, const SkRect& windowRect,\n                       const SkMatrix& preTouchM);\n\nprivate:\n    enum State {\n        kEmpty_State,\n        kTranslate_State,\n        kZoom_State,\n    };\n\n    struct Rec {\n        void*   fOwner;\n        float   fStartX, fStartY;\n        float   fPrevX, fPrevY;\n        float   fLastX, fLastY;\n        float   fPrevT, fLastT;\n    };\n    SkTDArray<Rec> fTouches;\n\n    State           fState;\n    SkMatrix        fLocalM, fGlobalM, fPreTouchM;\n    SkFlingState    fFlinger;\n    double          fLastUpMillis;\n    SkPoint         fLastUpP;\n\n    // The following rects are used to limit the translation so the content never leaves the window\n    SkRect          fContentRect, fWindowRect;\n    bool            fIsTransLimited = false;\n\n    void limitTrans(); // here we only limit the translation with respect to globalM\n    void flushLocalM();\n    int findRec(void* owner) const;\n    void appendNewRec(void* owner, float x, float y);\n    float computePinch(const Rec&, const Rec&);\n    float limitTotalZoom(float scale) const;\n    bool handleDblTap(float, float);\n};\n\n#endif\n"
  },
  {
    "path": "include/views/SkView.h",
    "content": "\n/*\n * Copyright 2006 The Android Open Source Project\n *\n * Use of this source code is governed by a BSD-style license that can be\n * found in the LICENSE file.\n */\n\n\n#ifndef SkView_DEFINED\n#define SkView_DEFINED\n\n#include \"SkEventSink.h\"\n#include \"SkRect.h\"\n#include \"SkMatrix.h\"\n#include \"SkMetaData.h\"\n\nclass SkCanvas;\n\n/** \\class SkView\n\n    SkView is the base class for screen management. All widgets and controls inherit\n    from SkView.\n*/\nclass SkView : public SkEventSink {\npublic:\n    enum Flag_Shift {\n        kVisible_Shift,\n        kNoClip_Shift,\n\n        kFlagShiftCount\n    };\n    enum Flag_Mask {\n        kVisible_Mask   = 1 << kVisible_Shift,      //!< set if the view is visible\n        kNoClip_Mask    = 1 << kNoClip_Shift,        //!< set if the view is not clipped to its bounds\n\n        kAllFlagMasks   = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)\n    };\n\n                SkView(uint32_t flags = 0);\n    virtual     ~SkView();\n\n    /** Return the flags associated with the view\n    */\n    uint32_t    getFlags() const { return fFlags; }\n    /** Set the flags associated with the view\n    */\n    void        setFlags(uint32_t flags);\n\n    /** Helper that returns non-zero if the kVisible_Mask bit is set in the view's flags\n    */\n    int         isVisible() const { return fFlags & kVisible_Mask; }\n    int         isClipToBounds() const { return !(fFlags & kNoClip_Mask); }\n    /** Helper to set/clear the view's kVisible_Mask flag */\n    void        setVisibleP(bool);\n    void        setClipToBounds(bool);\n\n    /** Return the view's width */\n    SkScalar    width() const { return fWidth; }\n    /** Return the view's height */\n    SkScalar    height() const { return fHeight; }\n    /** Set the view's width and height. These must both be >= 0. This does not affect the view's loc */\n    void        setSize(SkScalar width, SkScalar height);\n    void        setSize(const SkPoint& size) { this->setSize(size.fX, size.fY); }\n    void        setWidth(SkScalar width) { this->setSize(width, fHeight); }\n    void        setHeight(SkScalar height) { this->setSize(fWidth, height); }\n\n    /** Call this to have the view draw into the specified canvas. */\n    virtual void draw(SkCanvas* canvas);\n\n    //  Click handling\n\n    class Click {\n    public:\n        Click(SkView* target);\n        virtual ~Click();\n\n        enum State {\n            kDown_State,\n            kMoved_State,\n            kUp_State\n        };\n        SkPoint     fOrig, fPrev, fCurr;\n        SkIPoint    fIOrig, fIPrev, fICurr;\n        State       fState;\n        unsigned    fModifierKeys;\n\n        SkMetaData  fMeta;\n    private:\n        SkEventSinkID   fTargetID;\n\n        friend class SkView;\n    };\n    Click*  findClickHandler(SkScalar x, SkScalar y, unsigned modifierKeys);\n\n    static void DoClickDown(Click*, int x, int y, unsigned modi);\n    static void DoClickMoved(Click*, int x, int y, unsigned modi);\n    static void DoClickUp(Click*, int x, int y, unsigned modi);\n\nprotected:\n    /** Override this to draw inside the view. Be sure to call the inherited version too */\n    virtual void    onDraw(SkCanvas*);\n    /** Override this to be notified when the view's size changes. Be sure to call the inherited version too */\n    virtual void    onSizeChange();\n\n    /** Override this if you might handle the click\n    */\n    virtual Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi);\n    /** Override this to track clicks, returning true as long as you want to track\n        the pen/mouse.\n    */\n    virtual bool    onClick(Click*);\n\nprivate:\n    SkScalar    fWidth, fHeight;\n    uint8_t     fFlags;\n};\n\n#endif\n"
  },
  {
    "path": "libskia.a",
    "content": "version https://git-lfs.github.com/spec/v1\noid sha256:619c5a2eb2f2970b18c21773ae61a29cd0b72f981889bd39d170cc14cc27c945\nsize 25780584\n"
  },
  {
    "path": "skia.h",
    "content": "// skia.h generated by GN.\n#ifndef skia_h_DEFINED\n#define skia_h_DEFINED\n#include \"GrBackendSemaphore.h\"\n#include \"GrBackendSurface.h\"\n#include \"GrBlend.h\"\n#include \"GrConfig.h\"\n#include \"GrContext.h\"\n#include \"GrContextOptions.h\"\n#include \"GrDriverBugWorkarounds.h\"\n#include \"GrGpuResource.h\"\n#include \"GrRenderTarget.h\"\n#include \"GrResourceKey.h\"\n#include \"GrSamplerState.h\"\n#include \"GrSurface.h\"\n#include \"GrTexture.h\"\n#include \"GrTypes.h\"\n#include \"Sk1DPathEffect.h\"\n#include \"Sk2DPathEffect.h\"\n#include \"SkAlphaThresholdFilter.h\"\n#include \"SkArithmeticImageFilter.h\"\n#include \"SkBBHFactory.h\"\n#include \"SkBitmap.h\"\n#include \"SkBlurDrawLooper.h\"\n#include \"SkBlurImageFilter.h\"\n#include \"SkBlurMaskFilter.h\"\n#include \"SkCGUtils.h\"\n#include \"SkCamera.h\"\n#include \"SkCanvas.h\"\n#include \"SkCanvasStateUtils.h\"\n#include \"SkColor.h\"\n#include \"SkColorFilter.h\"\n#include \"SkColorFilterImageFilter.h\"\n#include \"SkColorMatrix.h\"\n#include \"SkColorMatrixFilter.h\"\n#include \"SkColorPriv.h\"\n#include \"SkCornerPathEffect.h\"\n#include \"SkDashPathEffect.h\"\n#include \"SkData.h\"\n#include \"SkDeferredDisplayListRecorder.h\"\n#include \"SkDeque.h\"\n#include \"SkDiscretePathEffect.h\"\n#include \"SkDisplacementMapEffect.h\"\n#include \"SkDocument.h\"\n#include \"SkDrawFilter.h\"\n#include \"SkDrawLooper.h\"\n#include \"SkDrawable.h\"\n#include \"SkDropShadowImageFilter.h\"\n#include \"SkEventTracer.h\"\n#include \"SkFlattenable.h\"\n#include \"SkFontArguments.h\"\n#include \"SkFontLCDConfig.h\"\n#include \"SkFontStyle.h\"\n#include \"SkFrontBufferedStream.h\"\n#include \"SkGradientShader.h\"\n#include \"SkGraphics.h\"\n#include \"SkImage.h\"\n#include \"SkImageEncoder.h\"\n#include \"SkImageFilter.h\"\n#include \"SkImageGenerator.h\"\n#include \"SkImageInfo.h\"\n#include \"SkImageSource.h\"\n#include \"SkInterpolator.h\"\n#include \"SkLayerDrawLooper.h\"\n#include \"SkLightingImageFilter.h\"\n#include \"SkLumaColorFilter.h\"\n#include \"SkMagnifierImageFilter.h\"\n#include \"SkMallocPixelRef.h\"\n#include \"SkMaskFilter.h\"\n#include \"SkMath.h\"\n#include \"SkMatrix.h\"\n#include \"SkMatrix44.h\"\n#include \"SkMetaData.h\"\n#include \"SkMorphologyImageFilter.h\"\n#include \"SkMultiPictureDraw.h\"\n#include \"SkNWayCanvas.h\"\n#include \"SkNoDrawCanvas.h\"\n#include \"SkNullCanvas.h\"\n#include \"SkOffsetImageFilter.h\"\n#include \"SkOverdrawCanvas.h\"\n#include \"SkOverdrawColorFilter.h\"\n#include \"SkPaint.h\"\n#include \"SkPaintFilterCanvas.h\"\n#include \"SkPaintFlagsDrawFilter.h\"\n#include \"SkPaintImageFilter.h\"\n#include \"SkParse.h\"\n#include \"SkParsePath.h\"\n#include \"SkPath.h\"\n#include \"SkPathEffect.h\"\n#include \"SkPathMeasure.h\"\n#include \"SkPathOps.h\"\n#include \"SkPerlinNoiseShader.h\"\n#include \"SkPicture.h\"\n#include \"SkPictureRecorder.h\"\n#include \"SkPixelRef.h\"\n#include \"SkPoint.h\"\n#include \"SkPoint3.h\"\n#include \"SkPreConfig.h\"\n#include \"SkRRect.h\"\n#include \"SkRSXform.h\"\n#include \"SkRandom.h\"\n#include \"SkRect.h\"\n#include \"SkRefCnt.h\"\n#include \"SkRegion.h\"\n#include \"SkScalar.h\"\n#include \"SkShader.h\"\n#include \"SkShadowUtils.h\"\n#include \"SkStream.h\"\n#include \"SkString.h\"\n#include \"SkStrokeRec.h\"\n#include \"SkSurface.h\"\n#include \"SkSurfaceCharacterization.h\"\n#include \"SkSwizzle.h\"\n#include \"SkTLazy.h\"\n#include \"SkTableColorFilter.h\"\n#include \"SkTableMaskFilter.h\"\n#include \"SkTextBlob.h\"\n#include \"SkTileImageFilter.h\"\n#include \"SkTime.h\"\n#include \"SkToSRGBColorFilter.h\"\n#include \"SkTypeface.h\"\n#include \"SkTypes.h\"\n#include \"SkUnPreMultiply.h\"\n#include \"SkVertices.h\"\n#include \"SkXfermodeImageFilter.h\"\n#include \"gl/GrGLAssembleInterface.h\"\n#include \"gl/GrGLConfig.h\"\n#include \"gl/GrGLExtensions.h\"\n#include \"gl/GrGLFunctions.h\"\n#include \"gl/GrGLInterface.h\"\n#include \"gl/GrGLTypes.h\"\n#endif//skia_h_DEFINED\n"
  },
  {
    "path": "skia_bindings.cpp",
    "content": "#include <iostream>\n#include \"skia.h\"\n#include \"include/ports/SkFontMgr.h\"\n#include <GL/gl.h>\n\n#include <emscripten.h>\n#include <emscripten/html5.h>\n\n// Hack to avoid embind creating a binding for SkData destructor\nnamespace emscripten {\n    namespace internal {\n        template<typename ClassType>\n        void raw_destructor(ClassType *);\n\n        template<>\n        void raw_destructor<SkData>(SkData *ptr) {\n        }\n    }\n}\n// Hack to avoid embind creating a binding for SkTypeface destructor\nnamespace emscripten {\n    namespace internal {\n        template<typename ClassType>\n        void raw_destructor(ClassType *);\n\n        template<>\n        void raw_destructor<SkTypeface>(SkTypeface *ptr) {\n        }\n    }\n}\n\n#include <emscripten/bind.h>\n\nusing namespace emscripten;\nusing emscripten::val;\nusing emscripten::vecFromJSArray;\n\n// to map from raw memory to a uint8array\nval getSkDataBytes(const SkData *data) {\n    return val(typed_memory_view(data->size(), data->bytes()));\n}\n\nsk_sp<SkSurface> makeWebGLSurface(std::string id, int width, int height) {\n    // Context configurations\n    EmscriptenWebGLContextAttributes attrs;\n    emscripten_webgl_init_context_attributes(&attrs);\n    attrs.alpha = true;\n    attrs.premultipliedAlpha = true;\n    attrs.majorVersion = 1;\n    attrs.enableExtensionsByDefault = true;\n\n    EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(id.c_str(), &attrs);\n    if (context < 0) {\n        printf(\"failed to create webgl context %d\\n\", context);\n    }\n    EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);\n    if (r < 0) {\n        printf(\"failed to make webgl current %d\\n\", r);\n    }\n\n    glViewport(0, 0, width, height);\n    glClearColor(1, 1, 1, 1);\n    glClearStencil(0);\n    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);\n\n    // setup GrContext\n    auto interface = GrGLMakeNativeInterface();\n\n    // setup contexts\n    sk_sp<GrContext> grContext(GrContext::MakeGL(interface));\n\n    // Wrap the frame buffer object attached to the screen in a Skia render target so Skia can\n    // render to it\n    GrGLint buffer;\n    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer);\n    GrGLFramebufferInfo info;\n    info.fFBOID = (GrGLuint) buffer;\n    SkColorType colorType;\n\n    info.fFormat = GL_RGBA8;\n    colorType = kRGBA_8888_SkColorType;\n\n\n    GrBackendRenderTarget target(width, height, 0, 8, info);\n\n    SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType);\n\n    sk_sp<SkSurface> surface(SkSurface::MakeFromBackendRenderTarget(grContext.get(), target,\n                                                                    kBottomLeft_GrSurfaceOrigin,\n                                                                    colorType, nullptr, &props));\n    return surface;\n}\n\nEMSCRIPTEN_BINDINGS(skia_module) {\n        // register array types, used by various functions to provide arrays as arguments functionality\n        register_vector<SkPoint>(\"VectorSkPoint\");\n        register_vector<SkColor>(\"VectorSkColor\");\n        register_vector<SkScalar>(\"VectorSkScalar\");\n\n        function(\"getSkDataBytes\", &getSkDataBytes, allow_raw_pointers());\n        function(\"GrGLMakeAssembledInterface\", &GrGLMakeAssembledInterface, allow_raw_pointers());\n        function(\"makeWebGLSurface\", &makeWebGLSurface, allow_raw_pointers());\n\n        // GrContext.h ->\n        class_<GrGLInterface>(\"GrGLInterface\");\n        // GrContext.h ^\n\n        // SkSurfaceProps.h ->\n        class_<SkSurfaceProps>(\"SkSurfaceProps\")\n        .constructor<uint32_t, SkPixelGeometry>()\n        .function(\"flags\", &SkSurfaceProps::flags);\n\n        enum_<SkPixelGeometry>(\"SkPixelGeometry\")\n        .value(\"kUnknown_SkPixelGeometry\", SkPixelGeometry::kUnknown_SkPixelGeometry)\n        .value(\"kRGB_H_SkPixelGeometry\", SkPixelGeometry::kRGB_H_SkPixelGeometry)\n        .value(\"kBGR_H_SkPixelGeometry\", SkPixelGeometry::kBGR_H_SkPixelGeometry)\n        .value(\"kRGB_V_SkPixelGeometry\", SkPixelGeometry::kRGB_V_SkPixelGeometry)\n        .value(\"kBGR_V_SkPixelGeometry\", SkPixelGeometry::kBGR_V_SkPixelGeometry);\n\n        enum_<SkSurfaceProps::Flags>(\"SkSurfaceProps.Flags\")\n        .value(\"kUseDeviceIndependentFonts_Flag\", SkSurfaceProps::Flags::kUseDeviceIndependentFonts_Flag);\n        EM_ASM(\n        Module['SkSurfaceProps']['Flags'] = Module['SkSurfaceProps.Flags'];\n        delete Module['SkSurfaceProps.Flags'];\n        );\n        // SkSurfaceProps.h ^\n\n        // SkBitmap.h ->\n        class_<SkBitmap>(\"SkBitmap\");\n        // SkBitmap.h ^\n\n        // SkImageInfo.h ->\n        class_<SkImageInfo>(\"SkImageInfo\")\n        .constructor<>();\n        // SkImageInfo.h ^\n\n        // SkData.h ->\n        class_<SkData>(\"SkData\")\n        .smart_ptr<sk_sp<SkData>>(\"sk_sp<SkData>>\")\n        .class_function(\"MakeFromMalloc\",\n        optional_override([](std::string data, size_t length)->sk_sp<SkData>{\n            return SkData::MakeFromMalloc(&data[0], length);\n        }),\n        allow_raw_pointers())\n        .class_function(\"MakeUninitialized\", &SkData::MakeUninitialized)\n        .function(\"size\", &SkData::size);\n        // SkData.h ^\n\n        // SkPoint.h ->\n        class_<SkPoint>(\"SkPoint\")\n        .class_function(\"Make\", &SkPoint::Make)\n        .property(\"fX\", &SkPoint::fX)\n        .property(\"fY\", &SkPoint::fY);\n        // SkPoint.h ^\n\n        // SkString.h ->\n        class_<SkString>(\"SkString\")\n        .constructor<>()\n        .function(\"c_str\",\n        optional_override([](SkString& this_)->std::string{\n            return std::string(this_.SkString::c_str());\n        })\n        );\n        // SkString.h ^\n\n        //SkImage.h ->\n        class_<SkImage>(\"SkImage\")\n        .smart_ptr<sk_sp<SkImage>>(\"sk_sp<SkImage>\")\n        .function(\"encodeToData\", select_overload<sk_sp<SkData>()const>(&SkImage::encodeToData));\n        //SkImage.h ^\n\n        // SkPath.h ->\n        class_<SkPath>(\"SkPath\")\n        .constructor<>()\n        .constructor<const SkPath&>()\n        .function(\"setFillType\",&SkPath::setFillType)\n        .function(\"moveToXY\",\n        select_overload<void(SkScalar, SkScalar)>(&SkPath::moveTo))\n        .function(\"moveToPoint\",\n        select_overload<void(const SkPoint& p)>(&SkPath::moveTo))\n        .function(\"lineToXY\",\n        select_overload<void(SkScalar, SkScalar)>(&SkPath::lineTo))\n        .function(\"lineToPoint\",\n        select_overload<void(const SkPoint& p)>(&SkPath::lineTo))\n        .function(\"close\", &SkPath::close);\n\n        enum_<SkPath::FillType>(\"SkPath.FillType\")\n        .value(\"kWinding_FillType\", SkPath::FillType::kWinding_FillType)\n        .value(\"kEvenOdd_FillType\", SkPath::FillType::kEvenOdd_FillType)\n        .value(\"kInverseWinding_FillType\", SkPath::FillType::kInverseWinding_FillType)\n        .value(\"kInverseEvenOdd_FillType\", SkPath::FillType::kInverseEvenOdd_FillType);\n        EM_ASM(\n        Module['SkPath']['FillType'] = Module['SkPath.FillType'];\n        delete Module['SkPath.FillType'];\n        );\n        // SkPath.h ^\n\n        // SkFontStyle.h ->\n        class_<SkFontStyle>(\"SkFontStyle\")\n        .constructor<>()\n        .class_function(\"Normal\", &SkFontStyle::Normal)\n        .class_function(\"Bold\", &SkFontStyle::Bold)\n        .class_function(\"Italic\", &SkFontStyle::Italic)\n        .class_function(\"BoldItalic\", &SkFontStyle::BoldItalic);\n        // SkFontStyle ^\n\n        // SkTypeFace ->\n        class_<SkTypeface>(\"SkTypeface\")\n        .smart_ptr<sk_sp<SkTypeface>>(\"sk_sp<SkTypeface>\")\n        .class_function(\"MakeDefault\", &SkTypeface::MakeDefault)\n        .class_function(\"MakeFromFile\",\n        optional_override([](std::string path, int index)->sk_sp<SkTypeface>{\n            return SkTypeface::MakeFromFile(path.c_str(), index);\n        }))\n        .class_function(\"MakeFromName\",\n        optional_override([](std::string familyName, SkFontStyle fontStyle)->sk_sp<SkTypeface>{\n            return SkTypeface::MakeFromName(familyName.c_str(), fontStyle);\n        }))\n        .function(\"countGlyphs\", &SkTypeface::countGlyphs);\n        // SkTypeFace ^\n\n        // SkFontMgr.h ->\n        class_<SkFontMgr>(\"SkFontMgr\")\n        .smart_ptr<sk_sp<SkFontMgr>>(\"sk_sp<SkFontMgr>\")\n        .class_function(\"RefDefault\", &SkFontMgr::RefDefault)\n        .function(\"countFamilies\", &SkFontMgr::countFamilies)\n        .function(\"getFamilyName\", &SkFontMgr::getFamilyName, allow_raw_pointers())\n        .function(\"makeFromData\", &SkFontMgr::makeFromData)\n        .function(\"matchFaceStyle\", &SkFontMgr::matchFaceStyle, allow_raw_pointers())\n        .function(\"makeFromFile\",\n        optional_override([](SkFontMgr& this_, std::string path, int ttcIndex)->sk_sp<SkTypeface>{\n            return this_.SkFontMgr::makeFromFile(path.c_str(), ttcIndex);\n        }));\n        // SkFontMgr.h ^\n\n        // SkPaint.h ->\n        class_<SkPaint>(\"SkPaint\")\n        .constructor<>()\n        .function(\"setAntiAlias\", &SkPaint::setAntiAlias)\n        .function(\"setTextSize\", &SkPaint::setTextSize)\n        .function(\"setColor\", &SkPaint::setColor)\n        .function(\"setStyle\", &SkPaint::setStyle)\n        .function(\"setStrokeWidth\", &SkPaint::setStrokeWidth)\n        .function(\"setTextScaleX\", &SkPaint::setTextScaleX)\n        .function(\"getTypeface\", &SkPaint::getTypeface, allow_raw_pointers())\n        .function(\"setTypeface\", &SkPaint::setTypeface)\n        .function(\"setShader\", &SkPaint::setShader);\n\n        enum_<SkPaint::Style>(\"SkPaint.Style\")\n        .value(\"kFill_Style\", SkPaint::Style::kFill_Style)\n        .value(\"kStroke_Style\", SkPaint::Style::kStroke_Style)\n        .value(\"kStrokeAndFill_Style\", SkPaint::Style::kStrokeAndFill_Style);\n        EM_ASM(\n        Module['SkPaint']['Style'] = Module['SkPaint.Style'];\n        delete Module['SkPaint.Flags'];\n        );\n        // SkPaint.h ^\n\n        // SkCanvas.h ->\n        class_<SkCanvas>(\"SkCanvas\")\n        .constructor<>()\n        .function(\"flush\", &SkCanvas::flush)\n        .function(\"clear\", &SkCanvas::clear)\n        .function(\"translate\", &SkCanvas::translate)\n        .function(\"drawPath\", &SkCanvas::drawPath)\n        .function(\"save\", &SkCanvas::save)\n        .function(\"restore\", &SkCanvas::restore)\n        .function(\"drawRect\", &SkCanvas::drawRect)\n        .function(\"rotate\",\n        select_overload<void(SkScalar)>(&SkCanvas::rotate),\n        allow_raw_pointers())\n        .function(\"drawImage\",\n        select_overload<void(const sk_sp<SkImage>&,SkScalar,SkScalar,const SkPaint*)>(&SkCanvas::drawImage),\n        allow_raw_pointers())\n        .function(\"drawText\",\n        // we wrap the real function in a lambda to do the conversion of the js string (represented as an std:string) to a c string\n        optional_override([](SkCanvas& this_, const std::string text, SkScalar x, SkScalar y, const SkPaint& p){\n            return this_.SkCanvas::drawText(text.c_str(), text.length(), x, y, p);\n        }),\n        allow_raw_pointers())\n        .function(\"drawPaint\", &SkCanvas::drawPaint);\n        // SkCanvas ^\n\n        // SkSurface.h ->\n        class_<SkSurface>(\"SkSurface\")\n        .smart_ptr<sk_sp<SkSurface>>(\"sk_sp<SkSurface>\")\n        .class_function(\"MakeRasterDirect\", &SkSurface::MakeRasterDirect, allow_raw_pointers())\n        .class_function(\"MakeRasterN32Premul\", &SkSurface::MakeRasterN32Premul, allow_raw_pointers())\n        .class_function(\"MakeRasterAutoRow\",\n        select_overload<sk_sp<SkSurface>(const SkImageInfo&, const SkSurfaceProps*)>(&SkSurface::MakeRaster),\n        allow_raw_pointers())\n        .function(\"width\", &SkSurface::width)\n        .function(\"height\", &SkSurface::height)\n        .function(\"getCanvas\", &SkSurface::getCanvas, allow_raw_pointers())\n        .function(\"makeImageSnapshot\", &SkSurface::makeImageSnapshot);\n        // SkSurface.h ^\n\n        // SkShader.h ->\n        class_<SkShader>(\"SkShader\")\n        .smart_ptr<sk_sp<SkShader>>(\"sk_sp<SkShader>\");\n\n        enum_<SkShader::TileMode>(\"SkShader.TileMode\")\n        .value(\"kClamp_TileMode\", SkShader::TileMode::kClamp_TileMode)\n        .value(\"kRepeat_TileMode\", SkShader::TileMode::kRepeat_TileMode)\n        .value(\"kMirror_TileMode\", SkShader::TileMode::kMirror_TileMode);\n        EM_ASM(\n        Module['SkShader']['TileMode'] = Module['SkShader.TileMode'];\n        delete Module['SkShader.TileMode'];\n        );\n        // SkShader.h ^\n\n        // SkGradientShader.h ->\n        class_<SkGradientShader>(\"SkGradientShader\")\n        .class_function(\"MakeLinear\",\n        optional_override([](const std::vector<SkPoint> pts, const std::vector<SkColor> colors, const std::vector<SkScalar> pos, int count, SkShader::TileMode mode)->sk_sp<SkShader>{\n            const SkPoint *ptsPtr = pts.data();\n            const SkColor *colorsPtr = colors.data();\n            const SkScalar *posPtr = pos.data();\n\n            return SkGradientShader::MakeLinear(ptsPtr, colorsPtr, posPtr, count, mode);\n        }),\n        allow_raw_pointers());\n        // SkGradientShader.h ^\n\n        // SkMatrix.h ->\n        class_<SkMatrix>(\"SkMatrix\")\n        .constructor<>()\n        .function(\"setRotate\",\n        select_overload<void(SkScalar)>(&SkMatrix::setRotate))\n        .function(\"mapPoints\",\n        select_overload<void(SkPoint[],const SkPoint[],int)const>(&SkMatrix::mapPoints),\n        allow_raw_pointers());\n        // SkMatrix.h ^\n\n        // SkRandom.h ->\n        class_<SkRandom>(\"SkRandom\")\n        .constructor<>()\n        .function(\"nextU\",&SkRandom::nextU);\n        // SkRandom.h ^\n\n        // SkRect.h ->\n        class_<SkRect>(\"SkRect\")\n        .class_function(\"MakeLTRB\", &SkRect::MakeLTRB, allow_raw_pointers())\n        .property(\"fRight\",&SkRect::fRight)\n        .property(\"fBottom\",&SkRect::fBottom);\n        // SkRect.h ^\n}\n"
  },
  {
    "path": "wasm_compatible_build.patch",
    "content": "Index: BUILD.gn\nIDEA additional info:\nSubsystem: com.intellij.openapi.diff.impl.patch.CharsetEP\n<+>UTF-8\n===================================================================\n--- BUILD.gn\t(date 1527627664000)\n+++ BUILD.gn\t(date 1528206782000)\n@@ -392,7 +392,7 @@\n }\n \n optional(\"fontmgr_custom\") {\n-  enabled = is_linux && skia_use_freetype && !skia_use_fontconfig\n+  enabled = (is_linux || target_cpu == \"wasm\") && skia_use_freetype && !skia_use_fontconfig\n \n   deps = [\n     \":typeface_freetype\",\n@@ -948,7 +948,7 @@\n     ]\n   }\n \n-  if (is_linux) {\n+  if (is_linux || target_cpu == \"wasm\") {\n     sources += [ \"src/ports/SkDebug_stdio.cpp\" ]\n     if (skia_use_egl) {\n       libs += [ \"GLESv2\" ]\n"
  }
]