소스 검색

Skia integration - preprocessing of shape geometry

Viktor Chlumský 4 년 전
부모
커밋
9d22335ea0
100개의 변경된 파일21611개의 추가작업 그리고 57개의 파일을 삭제
  1. 1 0
      .gitattributes
  2. 11 9
      .gitignore
  3. 19 0
      CHANGELOG.md
  4. 8 1
      CMakeLists.txt
  5. BIN
      Msdfgen.aps
  6. BIN
      Msdfgen.rc
  7. 38 36
      Msdfgen.vcxproj
  8. 6 0
      Msdfgen.vcxproj.filters
  9. 2 1
      README.md
  10. 89 0
      ext/resolve-shape-geometry.cpp
  11. 15 0
      ext/resolve-shape-geometry.h
  12. 67 7
      main.cpp
  13. 4 1
      msdfgen-ext.h
  14. 2 2
      msdfgen.h
  15. 29 0
      skia/LICENSE
  16. 40 0
      skia/include/android/SkAndroidFrameworkUtils.h
  17. 154 0
      skia/include/android/SkAnimatedImage.h
  18. 29 0
      skia/include/android/SkBRDAllocator.h
  19. 92 0
      skia/include/android/SkBitmapRegionDecoder.h
  20. 42 0
      skia/include/atlastext/SkAtlasTextContext.h
  21. 35 0
      skia/include/atlastext/SkAtlasTextFont.h
  22. 72 0
      skia/include/atlastext/SkAtlasTextRenderer.h
  23. 100 0
      skia/include/atlastext/SkAtlasTextTarget.h
  24. 159 0
      skia/include/c/sk_canvas.h
  25. 25 0
      skia/include/c/sk_colorspace.h
  26. 70 0
      skia/include/c/sk_data.h
  27. 71 0
      skia/include/c/sk_image.h
  28. 62 0
      skia/include/c/sk_imageinfo.h
  29. 47 0
      skia/include/c/sk_maskfilter.h
  30. 49 0
      skia/include/c/sk_matrix.h
  31. 145 0
      skia/include/c/sk_paint.h
  32. 84 0
      skia/include/c/sk_path.h
  33. 70 0
      skia/include/c/sk_picture.h
  34. 143 0
      skia/include/c/sk_shader.h
  35. 73 0
      skia/include/c/sk_surface.h
  36. 256 0
      skia/include/c/sk_types.h
  37. 287 0
      skia/include/codec/SkAndroidCodec.h
  38. 921 0
      skia/include/codec/SkCodec.h
  39. 43 0
      skia/include/codec/SkCodecAnimation.h
  40. 23 0
      skia/include/codec/SkEncodedOrigin.h
  41. 130 0
      skia/include/config/SkUserConfig.h
  42. 50 0
      skia/include/core/SkAnnotation.h
  43. 31 0
      skia/include/core/SkBBHFactory.h
  44. 1195 0
      skia/include/core/SkBitmap.h
  45. 75 0
      skia/include/core/SkBlendMode.h
  46. 22 0
      skia/include/core/SkBlurTypes.h
  47. 2779 0
      skia/include/core/SkCanvas.h
  48. 93 0
      skia/include/core/SkCanvasVirtualEnforcer.h
  49. 33 0
      skia/include/core/SkClipOp.h
  50. 389 0
      skia/include/core/SkColor.h
  51. 196 0
      skia/include/core/SkColorFilter.h
  52. 163 0
      skia/include/core/SkColorPriv.h
  53. 237 0
      skia/include/core/SkColorSpace.h
  54. 20 0
      skia/include/core/SkColorSpaceXformCanvas.h
  55. 30 0
      skia/include/core/SkCoverageMode.h
  56. 182 0
      skia/include/core/SkData.h
  57. 119 0
      skia/include/core/SkDataTable.h
  58. 165 0
      skia/include/core/SkDeferredDisplayListRecorder.h
  59. 139 0
      skia/include/core/SkDeque.h
  60. 91 0
      skia/include/core/SkDocument.h
  61. 129 0
      skia/include/core/SkDrawLooper.h
  62. 150 0
      skia/include/core/SkDrawable.h
  63. 34 0
      skia/include/core/SkEncodedImageFormat.h
  64. 33 0
      skia/include/core/SkExecutor.h
  65. 26 0
      skia/include/core/SkFilterQuality.h
  66. 107 0
      skia/include/core/SkFlattenable.h
  67. 488 0
      skia/include/core/SkFont.h
  68. 79 0
      skia/include/core/SkFontArguments.h
  69. 58 0
      skia/include/core/SkFontLCDConfig.h
  70. 106 0
      skia/include/core/SkFontMetrics.h
  71. 163 0
      skia/include/core/SkFontMgr.h
  72. 38 0
      skia/include/core/SkFontParameters.h
  73. 80 0
      skia/include/core/SkFontStyle.h
  74. 49 0
      skia/include/core/SkFontTypes.h
  75. 185 0
      skia/include/core/SkGraphics.h
  76. 23 0
      skia/include/core/SkICC.h
  77. 1026 0
      skia/include/core/SkImage.h
  78. 68 0
      skia/include/core/SkImageEncoder.h
  79. 479 0
      skia/include/core/SkImageFilter.h
  80. 207 0
      skia/include/core/SkImageGenerator.h
  81. 623 0
      skia/include/core/SkImageInfo.h
  82. 195 0
      skia/include/core/SkLights.h
  83. 93 0
      skia/include/core/SkMallocPixelRef.h
  84. 77 0
      skia/include/core/SkMaskFilter.h
  85. 75 0
      skia/include/core/SkMath.h
  86. 1863 0
      skia/include/core/SkMatrix.h
  87. 495 0
      skia/include/core/SkMatrix44.h
  88. 175 0
      skia/include/core/SkMetaData.h
  89. 9 0
      skia/include/core/SkMilestone.h
  90. 75 0
      skia/include/core/SkMultiPictureDraw.h
  91. 74 0
      skia/include/core/SkOverdrawCanvas.h
  92. 1427 0
      skia/include/core/SkPaint.h
  93. 1779 0
      skia/include/core/SkPath.h
  94. 187 0
      skia/include/core/SkPathEffect.h
  95. 125 0
      skia/include/core/SkPathMeasure.h
  96. 284 0
      skia/include/core/SkPicture.h
  97. 125 0
      skia/include/core/SkPictureRecorder.h
  98. 129 0
      skia/include/core/SkPixelRef.h
  99. 706 0
      skia/include/core/SkPixmap.h
  100. 45 0
      skia/include/core/SkPngChunkReader.h

+ 1 - 0
.gitattributes

@@ -2,3 +2,4 @@
 include/** linguist-vendored
 lib/** linguist-vendored
 freetype/** linguist-vendored
+skia/** linguist-vendored

+ 11 - 9
.gitignore

@@ -1,11 +1,11 @@
-Debug/
-Release/
-Release OpenMP/
-Debug Library/
-Release Library/
-Release Library OpenMP/
-x86/
-x64/
+/Debug/
+/Release/
+/Release OpenMP/
+/Debug Library/
+/Release Library/
+/Release Library OpenMP/
+/x86/
+/x64/
 .vs/
 *.exe
 *.zip
@@ -17,9 +17,11 @@ x64/
 *.suo
 *.VC.opendb
 *.VC.db
-bin/*.lib
+/bin/*.lib
 output.png
 render.png
 out/
 build/
 build_xcode/
+skia/win32/
+skia/win64/

+ 19 - 0
CHANGELOG.md

@@ -1,4 +1,23 @@
 
+## Version 1.8 (2020-10-17)
+
+- Integrated the Skia library into the project, which is used to preprocess the shape geometry and eliminate any self-intersections and other irregularities previously unsupported by the software
+    - The scanline pass and overlapping contour mode is made obsolete by this step and has been disabled by default. The preprocess step can be disabled by the new `-nopreprocess` switch and the former enabled by `-scanline` and `-overlap` respectively.
+    - The project can be built without the Skia library, forgoing the geometry preprocessing feature. This is controlled by the macro definition `MSDFGEN_USE_SKIA`
+- Significantly improved performance of the core algorithm by reusing results from previously computed pixels
+- Introduced an additional error correction routine which eliminates MSDF artifacts by analytically predicting results of bilinear interpolation
+- Added the possibility to load font glyphs by their index rather than a Unicode value (use the prefix `g` before the character code in `-font` argument)
+- Added `-distanceshift` argument that can be used to adjust the center of the distance range in the output distance field
+- Fixed several errors in the evaluation of curve distances
+- Fixed an issue with paths containing convergent corners (those whose inner angle is zero)
+- The algorithm for pseudo-distance computation slightly changed, fixing certain rare edge cases and improving consistency
+- Added the ability to supply own `FT_Face` handle to the msdfgen library
+- Minor refactor of the core algorithm
+
+### Version 1.7.1 (2020-03-09)
+
+- Fixed an edge case bug in scanline rasterization
+
 ## Version 1.7 (2020-03-07)
 
 - Added `mtsdf` mode - a combination of `msdf` with `sdf` in the alpha channel

+ 8 - 1
CMakeLists.txt

@@ -1,9 +1,10 @@
 cmake_minimum_required(VERSION 3.10)
 
-project(msdfgen VERSION 1.7.1 LANGUAGES CXX)
+project(msdfgen VERSION 1.8 LANGUAGES CXX)
 option(MSDFGEN_BUILD_MSDFGEN_STANDALONE "Build the msdfgen standalone executable" ON)
 option(MSDFGEN_USE_OPENMP "Build with OpenMP support for multithreaded code" OFF)
 option(MSDFGEN_USE_CPP11 "Build with C++11 enabled" ON)
+option(MSDFGEN_USE_SKIA "Build with the Skia library" OFF)
 option(FREETYPE_WITH_PNG "Link libpng and zlib because FreeType is configured to require it" OFF)
 option(FREETYPE_WITH_HARFBUZZ "Link HarfBuzz because FreeType is configured to require it" OFF)
 
@@ -71,6 +72,12 @@ if(MSDFGEN_USE_OPENMP)
 	target_compile_definitions(msdfgen PRIVATE MSDFGEN_USE_OPENMP)
 endif()
 
+if(MSDFGEN_USE_SKIA)
+	find_package(Skia REQUIRED)
+	target_link_libraries(msdfgen-ext PRIVATE Skia::Skia)
+	target_compile_definitions(msdfgen-ext PUBLIC MSDFGEN_USE_SKIA)
+endif()
+
 add_library(msdfgen-ext ${msdfgen-ext_SOURCES} ${msdfgen-ext_PUBLIC_HEADERS} ${msdfgen-ext_PRIVATE_HEADERS} "./msdfgen-ext.h")
 add_library(msdfgen::msdfgen-ext ALIAS msdfgen-ext)
 set_target_properties(msdfgen-ext PROPERTIES

BIN
Msdfgen.aps


BIN
Msdfgen.rc


+ 38 - 36
Msdfgen.vcxproj

@@ -231,13 +231,13 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Library|Win32'">
@@ -245,9 +245,9 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
@@ -255,7 +255,7 @@
     </Link>
     <Lib>
       <TargetMachine>MachineX86</TargetMachine>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
     <ProjectReference />
   </ItemDefinitionGroup>
@@ -264,13 +264,13 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Library|x64'">
@@ -278,12 +278,12 @@
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
     </ClCompile>
     <Lib>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -293,15 +293,15 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>No</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
@@ -312,16 +312,16 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_USE_OPENMP;MSDFGEN_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>No</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
@@ -332,9 +332,9 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -345,7 +345,7 @@
     </Link>
     <Lib>
       <TargetMachine>MachineX86</TargetMachine>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Library OpenMP|Win32'">
@@ -355,9 +355,9 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
     <Link>
@@ -369,7 +369,7 @@
     </Link>
     <Lib>
       <TargetMachine>MachineX86</TargetMachine>
-      <AdditionalLibraryDirectories>freetype/win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -379,15 +379,15 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     </ClCompile>
     <Link>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>false</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
@@ -398,8 +398,8 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>MSDFGEN_STANDALONE;MSDFGEN_USE_CPP11;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_STANDALONE;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
@@ -407,7 +407,7 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <SubSystem>Console</SubSystem>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
       <GenerateDebugInformation>false</GenerateDebugInformation>
     </Link>
   </ItemDefinitionGroup>
@@ -418,8 +418,8 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
     </ClCompile>
     <Link>
@@ -427,7 +427,7 @@
       <OptimizeReferences>true</OptimizeReferences>
     </Link>
     <Lib>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Library OpenMP|x64'">
@@ -437,8 +437,8 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <SDLCheck>true</SDLCheck>
-      <AdditionalIncludeDirectories>include;freetype/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>include;freetype/include;skia/include;skia/include/core;skia/include/config;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDFGEN_USE_OPENMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <OpenMPSupport>true</OpenMPSupport>
     </ClCompile>
@@ -447,7 +447,7 @@
       <OptimizeReferences>true</OptimizeReferences>
     </Link>
     <Lib>
-      <AdditionalLibraryDirectories>freetype/win64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>freetype/win$(PlatformArchitecture);skia/win$(PlatformArchitecture)/release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
     </Lib>
   </ItemDefinitionGroup>
   <ItemGroup>
@@ -481,6 +481,7 @@
     <ClInclude Include="core\Vector2.h" />
     <ClInclude Include="ext\import-font.h" />
     <ClInclude Include="ext\import-svg.h" />
+    <ClInclude Include="ext\resolve-shape-geometry.h" />
     <ClInclude Include="ext\save-png.h" />
     <ClInclude Include="msdfgen-ext.h" />
     <ClInclude Include="msdfgen.h" />
@@ -508,6 +509,7 @@
     <ClCompile Include="core\Vector2.cpp" />
     <ClCompile Include="ext\import-font.cpp" />
     <ClCompile Include="ext\import-svg.cpp" />
+    <ClCompile Include="ext\resolve-shape-geometry.cpp" />
     <ClCompile Include="ext\save-png.cpp" />
     <ClCompile Include="lib\lodepng.cpp" />
     <ClCompile Include="lib\tinyxml2.cpp" />

+ 6 - 0
Msdfgen.vcxproj.filters

@@ -120,6 +120,9 @@
     <ClInclude Include="core\msdf-edge-artifact-patcher.h">
       <Filter>Core</Filter>
     </ClInclude>
+    <ClInclude Include="ext\resolve-shape-geometry.h">
+      <Filter>Extensions</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
@@ -200,6 +203,9 @@
     <ClCompile Include="core\msdf-edge-artifact-patcher.cpp">
       <Filter>Core</Filter>
     </ClCompile>
+    <ClCompile Include="ext\resolve-shape-geometry.cpp">
+      <Filter>Extensions</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Msdfgen.rc">

+ 2 - 1
README.md

@@ -26,7 +26,8 @@ Extensions contain utilities for loading fonts and SVG files, as well as saving
 Those are exposed by the [msdfgen-ext.h](msdfgen-ext.h) header. This module uses
 [FreeType](http://www.freetype.org/),
 [TinyXML2](http://www.grinninglizard.com/tinyxml2/),
-and [LodePNG](http://lodev.org/lodepng/).
+[LodePNG](http://lodev.org/lodepng/),
+and (optionally) [Skia](https://skia.org/).
 
 Additionally, there is the [main.cpp](main.cpp), which wraps the functionality into
 a comprehensive standalone console program. To start using the program immediately,

+ 89 - 0
ext/resolve-shape-geometry.cpp

@@ -0,0 +1,89 @@
+
+#include "resolve-shape-geometry.h"
+
+#ifdef MSDFGEN_USE_SKIA
+
+#include <core/SkPath.h>
+#include <pathops/SkPathOps.h>
+#include "../core/Vector2.h"
+#include "../core/edge-segments.h"
+#include "../core/Contour.h"
+
+#ifdef _WIN32
+    #pragma comment(lib, "skia.lib")
+#endif
+
+namespace msdfgen {
+
+SkPoint pointToSkiaPoint(Point2 p) {
+    return SkPoint::Make((SkScalar) p.x, (SkScalar) p.y);
+}
+
+Point2 pointFromSkiaPoint(const SkPoint p) {
+    return Point2((double) p.x(), (double) p.y());
+}
+
+void shapeToSkiaPath(SkPath &skPath, const Shape &shape) {
+    for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
+        if (!contour->edges.empty()) {
+            skPath.moveTo(pointToSkiaPoint(contour->edges.front()->point(0)));
+            for (std::vector<EdgeHolder>::const_iterator edge = contour->edges.begin(); edge != contour->edges.end(); ++edge) {
+                {
+                    const LinearSegment *linearSegment = dynamic_cast<const LinearSegment *>(&**edge);
+                    if (linearSegment)
+                        skPath.lineTo(pointToSkiaPoint(linearSegment->p[1]));
+                } {
+                    const QuadraticSegment *quadraticSegment = dynamic_cast<const QuadraticSegment *>(&**edge);
+                    if (quadraticSegment)
+                        skPath.quadTo(pointToSkiaPoint(quadraticSegment->p[1]), pointToSkiaPoint(quadraticSegment->p[2]));
+                } {
+                    const CubicSegment *cubicSegment = dynamic_cast<const CubicSegment *>(&**edge);
+                    if (cubicSegment)
+                        skPath.cubicTo(pointToSkiaPoint(cubicSegment->p[1]), pointToSkiaPoint(cubicSegment->p[2]), pointToSkiaPoint(cubicSegment->p[3]));
+                }
+            }
+        }
+    }
+}
+
+void shapeFromSkiaPath(Shape &shape, const SkPath &skPath) {
+    shape.contours.clear();
+    Contour *contour = &shape.addContour();
+    SkPath::Iter pathIterator(skPath, true);
+    SkPoint edgePoints[4];
+    for (SkPath::Verb op; (op = pathIterator.next(edgePoints)) != SkPath::kDone_Verb;) {
+        switch (op) {
+            case SkPath::kMove_Verb:
+                if (!contour->edges.empty())
+                    contour = &shape.addContour();
+                break;
+            case SkPath::kLine_Verb:
+                contour->addEdge(new LinearSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1])));
+                break;
+            case SkPath::kQuad_Verb:
+                contour->addEdge(new QuadraticSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1]), pointFromSkiaPoint(edgePoints[2])));
+                break;
+            case SkPath::kCubic_Verb:
+                contour->addEdge(new CubicSegment(pointFromSkiaPoint(edgePoints[0]), pointFromSkiaPoint(edgePoints[1]), pointFromSkiaPoint(edgePoints[2]), pointFromSkiaPoint(edgePoints[3])));
+                break;
+            default:;
+        }
+    }
+    if (contour->edges.empty())
+        shape.contours.pop_back();
+}
+
+bool resolveShapeGeometry(Shape &shape) {
+    SkPath skPath;
+    shapeToSkiaPath(skPath, shape);
+    if (!Simplify(skPath, &skPath))
+        return false;
+    // Skia's AsWinding doesn't seem to work for unknown reasons
+    shapeFromSkiaPath(shape, skPath);
+    shape.orientContours();
+    return true;
+}
+
+}
+
+#endif

+ 15 - 0
ext/resolve-shape-geometry.h

@@ -0,0 +1,15 @@
+
+#pragma once
+
+#include "../core/Shape.h"
+
+#ifdef MSDFGEN_USE_SKIA
+
+namespace msdfgen {
+
+/// Resolves any intersections within the shape by subdividing its contours using the Skia library and makes sure its contours have a consistent winding.
+bool resolveShapeGeometry(Shape &shape);
+
+}
+
+#endif

+ 67 - 7
main.cpp

@@ -1,6 +1,6 @@
 
 /*
- * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.7 (2020-03-07) - standalone console program
+ * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.8 (2020-10-17) - standalone console program
  * --------------------------------------------------------------------------------------------
  * A utility by Viktor Chlumsky, (c) 2014 - 2020
  *
@@ -252,10 +252,24 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
     return NULL;
 }
 
+#if defined(MSDFGEN_USE_SKIA) && defined(MSDFGEN_USE_OPENMP)
+    #define TITLE_SUFFIX    " with Skia & OpenMP"
+    #define EXTRA_UNDERLINE "-------------------"
+#elif defined(MSDFGEN_USE_SKIA)
+    #define TITLE_SUFFIX    " with Skia"
+    #define EXTRA_UNDERLINE "----------"
+#elif defined(MSDFGEN_USE_OPENMP)
+    #define TITLE_SUFFIX    " with OpenMP"
+    #define EXTRA_UNDERLINE "------------"
+#else
+    #define TITLE_SUFFIX
+    #define EXTRA_UNDERLINE
+#endif
+
 static const char *helpText =
     "\n"
-    "Multi-channel signed distance field generator by Viktor Chlumsky v" MSDFGEN_VERSION "\n"
-    "---------------------------------------------------------------------\n"
+    "Multi-channel signed distance field generator by Viktor Chlumsky v" MSDFGEN_VERSION TITLE_SUFFIX "\n"
+    "---------------------------------------------------------------------" EXTRA_UNDERLINE "\n"
     "  Usage: msdfgen"
     #ifdef _WIN32
         ".exe"
@@ -273,7 +287,8 @@ static const char *helpText =
     "  -defineshape <definition>\n"
         "\tDefines input shape using the ad-hoc text definition.\n"
     "  -font <filename.ttf> <character code>\n"
-        "\tLoads a single glyph from the specified font file. Format of character code is '?', 63, 0x3F (Unicode value), or g34 (glyph index).\n"
+        "\tLoads a single glyph from the specified font file.\n"
+        "\tFormat of character code is '?', 63, 0x3F (Unicode value), or g34 (glyph index).\n"
     "  -shapedesc <filename.txt>\n"
         "\tLoads text shape description from a file.\n"
     "  -stdin\n"
@@ -281,6 +296,7 @@ static const char *helpText =
     "  -svg <filename.svg>\n"
         "\tLoads the last vector path found in the specified SVG file.\n"
     "\n"
+    // Keep alphabetical order!
     "OPTIONS\n"
     "  -angle <angle>\n"
         "\tSpecifies the minimum angle between adjacent edges to be considered a corner. Append D for degrees.\n"
@@ -310,12 +326,21 @@ static const char *helpText =
         "\tDisplays this help.\n"
     "  -legacy\n"
         "\tUses the original (legacy) distance field algorithms.\n"
+#ifdef MSDFGEN_USE_SKIA
+    "  -nopreprocess\n"
+        "\tDisables path preprocessing which resolves self-intersections and overlapping contours.\n"
+#else
     "  -nooverlap\n"
         "\tDisables resolution of overlapping contours.\n"
     "  -noscanline\n"
         "\tDisables the scanline pass, which corrects the distance field's signs according to the selected fill rule.\n"
+#endif
     "  -o <filename>\n"
         "\tSets the output file name. The default value is \"output.png\".\n"
+#ifdef MSDFGEN_USE_SKIA
+    "  -overlap\n"
+        "\tSwitches to distance field generator with support for overlapping contours.\n"
+#endif
     "  -printmetrics\n"
         "\tPrints relevant metrics of the shape to the standard output.\n"
     "  -pxrange <range>\n"
@@ -323,9 +348,13 @@ static const char *helpText =
     "  -range <range>\n"
         "\tSets the width of the range between the lowest and highest signed distance in shape units.\n"
     "  -reverseorder\n"
-        "\tGenerates the distance field as if shape vertices were in reverse order.\n"
+        "\tGenerates the distance field as if the shape's vertices were in reverse order.\n"
     "  -scale <scale>\n"
         "\tSets the scale used to convert shape units to pixels.\n"
+#ifdef MSDFGEN_USE_SKIA
+    "  -scanline\n"
+        "\tPerforms an additional scanline pass to fix the signs of the distances.\n"
+#endif
     "  -seed <n>\n"
         "\tSets the random seed for edge coloring heuristic.\n"
     "  -size <width> <height>\n"
@@ -362,8 +391,15 @@ int main(int argc, const char * const *argv) {
         METRICS
     } mode = MULTI;
     bool legacyMode = false;
-    bool overlapSupport = true;
-    bool scanlinePass = true;
+    bool geometryPreproc = (
+        #ifdef MSDFGEN_USE_SKIA
+            true
+        #else
+            false
+        #endif
+    );
+    bool overlapSupport = !geometryPreproc;
+    bool scanlinePass = !geometryPreproc;
     FillRule fillRule = FILL_NONZERO;
     Format format = AUTO;
     const char *input = NULL;
@@ -477,11 +513,26 @@ int main(int argc, const char * const *argv) {
             argPos += 1;
             continue;
         }
+        ARG_CASE("-nopreprocess", 0) {
+            geometryPreproc = false;
+            argPos += 1;
+            continue;
+        }
+        ARG_CASE("-preprocess", 0) {
+            geometryPreproc = true;
+            argPos += 1;
+            continue;
+        }
         ARG_CASE("-nooverlap", 0) {
             overlapSupport = false;
             argPos += 1;
             continue;
         }
+        ARG_CASE("-overlap", 0) {
+            overlapSupport = true;
+            argPos += 1;
+            continue;
+        }
         ARG_CASE("-noscanline", 0) {
             scanlinePass = false;
             argPos += 1;
@@ -493,6 +544,7 @@ int main(int argc, const char * const *argv) {
             continue;
         }
         ARG_CASE("-fillrule", 1) {
+            scanlinePass = true;
             if (!strcmp(argv[argPos+1], "nonzero")) fillRule = FILL_NONZERO;
             else if (!strcmp(argv[argPos+1], "evenodd") || !strcmp(argv[argPos+1], "odd")) fillRule = FILL_ODD;
             else if (!strcmp(argv[argPos+1], "positive")) fillRule = FILL_POSITIVE;
@@ -749,6 +801,14 @@ int main(int argc, const char * const *argv) {
     // Validate and normalize shape
     if (!shape.validate())
         ABORT("The geometry of the loaded shape is invalid.");
+    if (geometryPreproc) {
+        #ifdef MSDFGEN_USE_SKIA
+            if (!resolveShapeGeometry(shape))
+                puts("Shape geometry preprocessing failed, skipping.");
+        #else
+            ABORT("Shape geometry preprocessing (-preprocess) is not available in this version because the Skia library is not present.");
+        #endif
+    }
     shape.normalize();
     if (yFlip)
         shape.inverseYAxis = !shape.inverseYAxis;

+ 4 - 1
msdfgen-ext.h

@@ -2,13 +2,15 @@
 #pragma once
 
 /*
- * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.7 (2020-03-07) - extensions
+ * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.8 (2020-10-17) - extensions
  * ----------------------------------------------------------------------------
  * A utility by Viktor Chlumsky, (c) 2014 - 2020
  *
  * The extension module provides ways to easily load input and save output using popular formats.
  *
  * Third party dependencies in extension module:
+ * - Skia by Google
+ *   (to resolve self-intersecting paths)
  * - FreeType 2
  *   (to load input font files)
  * - TinyXML 2 by Lee Thomason
@@ -18,6 +20,7 @@
  *
  */
 
+#include "ext/resolve-shape-geometry.h"
 #include "ext/save-png.h"
 #include "ext/import-svg.h"
 #include "ext/import-font.h"

+ 2 - 2
msdfgen.h

@@ -2,7 +2,7 @@
 #pragma once
 
 /*
- * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.7 (2020-03-07)
+ * MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR v1.8 (2020-10-17)
  * ---------------------------------------------------------------
  * A utility by Viktor Chlumsky, (c) 2014 - 2020
  *
@@ -32,7 +32,7 @@
 #include "core/save-tiff.h"
 #include "core/shape-description.h"
 
-#define MSDFGEN_VERSION "1.7"
+#define MSDFGEN_VERSION "1.8"
 
 namespace msdfgen {
 

+ 29 - 0
skia/LICENSE

@@ -0,0 +1,29 @@
+// Copyright (c) 2011 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------------------

+ 40 - 0
skia/include/android/SkAndroidFrameworkUtils.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAndroidFrameworkUtils_DEFINED
+#define SkAndroidFrameworkUtils_DEFINED
+
+#include "SkTypes.h"
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+
+class SkCanvas;
+
+/**
+ *  SkAndroidFrameworkUtils expose private APIs used only by Android framework.
+ */
+class SkAndroidFrameworkUtils {
+public:
+
+#if SK_SUPPORT_GPU
+    /**
+     *  clipWithStencil draws the current clip into a stencil buffer with reference value and mask
+     *  set to 0x1. This function works only on a GPU canvas.
+     *
+     *  @param  canvas A GPU canvas that has a non-empty clip.
+     *
+     *  @return true on success or false if clip is empty or not a GPU canvas.
+     */
+    static bool clipWithStencil(SkCanvas* canvas);
+#endif //SK_SUPPORT_GPU
+
+    static void SafetyNetLog(const char*);
+};
+
+#endif // SK_BUILD_FOR_ANDROID_ANDROID
+
+#endif // SkAndroidFrameworkUtils_DEFINED

+ 154 - 0
skia/include/android/SkAnimatedImage.h

@@ -0,0 +1,154 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnimatedImage_DEFINED
+#define SkAnimatedImage_DEFINED
+
+#include "SkBitmap.h"
+#include "SkCodecAnimation.h"
+#include "SkDrawable.h"
+#include "SkMatrix.h"
+#include "SkRect.h"
+
+class SkAndroidCodec;
+class SkPicture;
+
+/**
+ *  Thread unsafe drawable for drawing animated images (e.g. GIF).
+ */
+class SK_API SkAnimatedImage : public SkDrawable {
+public:
+    /**
+     *  Create an SkAnimatedImage from the SkAndroidCodec.
+     *
+     *  Returns null on failure to allocate pixels. On success, this will
+     *  decode the first frame.
+     *
+     *  @param scaledSize Size to draw the image, possibly requiring scaling.
+     *  @param cropRect Rectangle to crop to after scaling.
+     *  @param postProcess Picture to apply after scaling and cropping.
+     */
+    static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>,
+            SkISize scaledSize, SkIRect cropRect, sk_sp<SkPicture> postProcess);
+
+    /**
+     *  Simpler version that uses the default size, no cropping, and no postProcess.
+     */
+    static sk_sp<SkAnimatedImage> Make(std::unique_ptr<SkAndroidCodec>);
+
+    ~SkAnimatedImage() override;
+
+    /**
+     *  Reset the animation to the beginning.
+     */
+    void reset();
+
+    /**
+     *  Whether the animation completed.
+     *
+     *  Returns true after all repetitions are complete, or an error stops the
+     *  animation. Gets reset to false if the animation is restarted.
+     */
+    bool isFinished() const { return fFinished; }
+
+    /**
+     * Returned by decodeNextFrame and currentFrameDuration if the animation
+     * is not running.
+     */
+    static constexpr int kFinished = -1;
+
+    /**
+     *  Decode the next frame.
+     *
+     *  If the animation is on the last frame or has hit an error, returns
+     *  kFinished.
+     */
+    int decodeNextFrame();
+
+    /**
+     *  How long to display the current frame.
+     *
+     *  Useful for the first frame, for which decodeNextFrame is called
+     *  internally.
+     */
+    int currentFrameDuration() {
+        return fCurrentFrameDuration;
+    }
+
+    /**
+     *  Change the repetition count.
+     *
+     *  By default, the image will repeat the number of times indicated in the
+     *  encoded data.
+     *
+     *  Use SkCodec::kRepetitionCountInfinite for infinite, and 0 to show all
+     *  frames once and then stop.
+     */
+    void setRepetitionCount(int count);
+
+    /**
+     *  Return the currently set repetition count.
+     */
+    int getRepetitionCount() const {
+        return fRepetitionCount;
+    }
+
+protected:
+    SkRect onGetBounds() override;
+    void onDraw(SkCanvas*) override;
+
+private:
+    struct Frame {
+        SkBitmap fBitmap;
+        int      fIndex;
+        SkCodecAnimation::DisposalMethod fDisposalMethod;
+
+        // init() may have to create a new SkPixelRef, if the
+        // current one is already in use by another owner (e.g.
+        // an SkPicture). This determines whether to copy the
+        // existing one to the new one.
+        enum class OnInit {
+            // Restore the image from the old SkPixelRef to the
+            // new one.
+            kRestoreIfNecessary,
+            // No need to restore.
+            kNoRestore,
+        };
+
+        Frame();
+        bool init(const SkImageInfo& info, OnInit);
+        bool copyTo(Frame*) const;
+    };
+
+    std::unique_ptr<SkAndroidCodec> fCodec;
+    const SkISize                   fScaledSize;
+    const SkImageInfo               fDecodeInfo;
+    const SkIRect                   fCropRect;
+    const sk_sp<SkPicture>          fPostProcess;
+    const int                       fFrameCount;
+    const bool                      fSimple;     // no crop, scale, or postprocess
+    SkMatrix                        fMatrix;     // used only if !fSimple
+
+    bool                            fFinished;
+    int                             fCurrentFrameDuration;
+    Frame                           fDisplayFrame;
+    Frame                           fDecodingFrame;
+    Frame                           fRestoreFrame;
+    int                             fRepetitionCount;
+    int                             fRepetitionsCompleted;
+
+    SkAnimatedImage(std::unique_ptr<SkAndroidCodec>, SkISize scaledSize,
+            SkImageInfo decodeInfo, SkIRect cropRect, sk_sp<SkPicture> postProcess);
+    SkAnimatedImage(std::unique_ptr<SkAndroidCodec>);
+
+    int computeNextFrame(int current, bool* animationEnded);
+    double finish();
+
+    typedef SkDrawable INHERITED;
+};
+
+#endif // SkAnimatedImage_DEFINED

+ 29 - 0
skia/include/android/SkBRDAllocator.h

@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBRDAllocator_DEFINED
+#define SkBRDAllocator_DEFINED
+
+#include "SkBitmap.h"
+#include "SkCodec.h"
+
+/**
+ *  Abstract subclass of SkBitmap's allocator.
+ *  Allows the allocator to indicate if the memory it allocates
+ *  is zero initialized.
+ */
+class SkBRDAllocator : public SkBitmap::Allocator {
+public:
+
+    /**
+     *  Indicates if the memory allocated by this allocator is
+     *  zero initialized.
+     */
+    virtual SkCodec::ZeroInitialized zeroInit() const = 0;
+};
+
+#endif // SkBRDAllocator_DEFINED

+ 92 - 0
skia/include/android/SkBitmapRegionDecoder.h

@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBitmapRegionDecoder_DEFINED
+#define SkBitmapRegionDecoder_DEFINED
+
+#include "SkBitmap.h"
+#include "SkBRDAllocator.h"
+#include "SkEncodedImageFormat.h"
+#include "SkStream.h"
+
+/*
+ * This class aims to provide an interface to test multiple implementations of
+ * SkBitmapRegionDecoder.
+ */
+class SK_API SkBitmapRegionDecoder {
+public:
+
+    enum Strategy {
+        kAndroidCodec_Strategy, // Uses SkAndroidCodec for scaling and subsetting
+    };
+
+    /*
+     * @param data     Refs the data while this object exists, unrefs on destruction
+     * @param strategy Strategy used for scaling and subsetting
+     * @return         Tries to create an SkBitmapRegionDecoder, returns NULL on failure
+     */
+    static SkBitmapRegionDecoder* Create(sk_sp<SkData>, Strategy strategy);
+
+    /*
+     * @param stream   Takes ownership of the stream
+     * @param strategy Strategy used for scaling and subsetting
+     * @return         Tries to create an SkBitmapRegionDecoder, returns NULL on failure
+     */
+    static SkBitmapRegionDecoder* Create(
+            SkStreamRewindable* stream, Strategy strategy);
+
+    /*
+     * Decode a scaled region of the encoded image stream
+     *
+     * @param bitmap          Container for decoded pixels.  It is assumed that the pixels
+     *                        are initially unallocated and will be allocated by this function.
+     * @param allocator       Allocator for the pixels.  If this is NULL, the default
+     *                        allocator (HeapAllocator) will be used.
+     * @param desiredSubset   Subset of the original image to decode.
+     * @param sampleSize      An integer downscaling factor for the decode.
+     * @param colorType       Preferred output colorType.
+     *                        New implementations should return NULL if they do not support
+     *                        decoding to this color type.
+     *                        The old kOriginal_Strategy will decode to a default color type
+     *                        if this color type is unsupported.
+     * @param requireUnpremul If the image is not opaque, we will use this to determine the
+     *                        alpha type to use.
+     * @param prefColorSpace  If non-null and supported, this is the color space that we will
+     *                        decode into.  Otherwise, we will choose a default.
+     *
+     */
+    virtual bool decodeRegion(SkBitmap* bitmap, SkBRDAllocator* allocator,
+                              const SkIRect& desiredSubset, int sampleSize,
+                              SkColorType colorType, bool requireUnpremul,
+                              sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;
+
+    virtual SkEncodedImageFormat getEncodedFormat() = 0;
+
+    virtual SkColorType computeOutputColorType(SkColorType requestedColorType) = 0;
+
+    virtual sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
+            sk_sp<SkColorSpace> prefColorSpace = nullptr) = 0;
+
+
+    int width() const { return fWidth; }
+    int height() const { return fHeight; }
+
+    virtual ~SkBitmapRegionDecoder() {}
+
+protected:
+
+    SkBitmapRegionDecoder(int width, int height)
+        : fWidth(width)
+        , fHeight(height)
+    {}
+
+private:
+    const int fWidth;
+    const int fHeight;
+};
+
+#endif

+ 42 - 0
skia/include/atlastext/SkAtlasTextContext.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAtlasTextContext_DEFINED
+#define SkAtlasTextContext_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkAtlasTextRenderer;
+class SkInternalAtlasTextContext;
+
+SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(class SkInternalAtlasTextContext&);
+
+/**
+ * Class that Atlas Text client uses to register their SkAtlasTextRenderer implementation and
+ * to create one or more SkAtlasTextTargets (destination surfaces for text rendering).
+ */
+class SK_API SkAtlasTextContext : public SkRefCnt {
+public:
+    static sk_sp<SkAtlasTextContext> Make(sk_sp<SkAtlasTextRenderer>);
+
+    SkAtlasTextRenderer* renderer() const {
+        return SkGetAtlasTextRendererFromInternalContext(*fInternalContext);
+    }
+
+    SkInternalAtlasTextContext& internal() { return *fInternalContext; }
+
+private:
+    SkAtlasTextContext() = delete;
+    SkAtlasTextContext(const SkAtlasTextContext&) = delete;
+    SkAtlasTextContext& operator=(const SkAtlasTextContext&) = delete;
+
+    SkAtlasTextContext(sk_sp<SkAtlasTextRenderer>);
+
+    std::unique_ptr<SkInternalAtlasTextContext> fInternalContext;
+};
+
+#endif

+ 35 - 0
skia/include/atlastext/SkAtlasTextFont.h

@@ -0,0 +1,35 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAtlasTextFont_DEFINED
+#define SkAtlasTextFont_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkTypeface.h"
+
+/** Represents a font at a size. TODO: What else do we need here (skewX, scaleX, vertical, ...)? */
+class SK_API SkAtlasTextFont : public SkRefCnt {
+public:
+    static sk_sp<SkAtlasTextFont> Make(sk_sp<SkTypeface> typeface, SkScalar size) {
+        return sk_sp<SkAtlasTextFont>(new SkAtlasTextFont(std::move(typeface), size));
+    }
+
+    SkTypeface* typeface() const { return fTypeface.get(); }
+
+    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
+
+    SkScalar size() const { return fSize; }
+
+private:
+    SkAtlasTextFont(sk_sp<SkTypeface> typeface, SkScalar size)
+            : fTypeface(std::move(typeface)), fSize(size) {}
+
+    sk_sp<SkTypeface> fTypeface;
+    SkScalar fSize;
+};
+
+#endif

+ 72 - 0
skia/include/atlastext/SkAtlasTextRenderer.h

@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPoint3.h"
+#include "SkRefCnt.h"
+
+#ifndef SkAtlasTextRenderer_DEFINED
+#define SkAtlasTextRenderer_DEFINED
+
+/**
+ * This is the base class for a renderer implemented by the SkAtlasText client. The
+ * SkAtlasTextContext issues texture creations, deletions, uploads, and vertex draws to the
+ * renderer. The renderer must perform those actions in the order called to correctly render
+ * the text drawn to SkAtlasTextTargets.
+ */
+class SK_API SkAtlasTextRenderer : public SkRefCnt {
+public:
+    enum class AtlasFormat {
+        /** Unsigned normalized 8 bit single channel format. */
+        kA8
+    };
+
+    struct SDFVertex {
+        /** Position in device space (not normalized). The third component is w (not z). */
+        SkPoint3 fPosition;
+        /** Color, same value for all four corners of a glyph quad. */
+        uint32_t fColor;
+        /** Texture coordinate (in texel units, not normalized). */
+        int16_t fTextureCoordX;
+        int16_t fTextureCoordY;
+    };
+
+    virtual ~SkAtlasTextRenderer() = default;
+
+    /**
+     * Create a texture of the provided format with dimensions 'width' x 'height'
+     * and return a unique handle.
+     */
+    virtual void* createTexture(AtlasFormat, int width, int height) = 0;
+
+    /**
+     * Delete the texture with the passed handle.
+     */
+    virtual void deleteTexture(void* textureHandle) = 0;
+
+    /**
+     * Place the pixel data specified by 'data' in the texture with handle
+     * 'textureHandle' in the rectangle ['x', 'x' + 'width') x ['y', 'y' + 'height').
+     * 'rowBytes' specifies the byte offset between successive rows in 'data' and will always be
+     * a multiple of the number of bytes per pixel.
+     * The pixel format of data is the same as that of 'textureHandle'.
+     */
+    virtual void setTextureData(void* textureHandle, const void* data, int x, int y, int width,
+                                int height, size_t rowBytes) = 0;
+
+    /**
+     * Draws glyphs using SDFs. The SDF data resides in 'textureHandle'. The array
+     * 'vertices' provides interleaved device-space positions, colors, and
+     * texture coordinates. There are are 4 * 'quadCnt' entries in 'vertices'.
+     */
+    virtual void drawSDFGlyphs(void* targetHandle, void* textureHandle, const SDFVertex vertices[],
+                               int quadCnt) = 0;
+
+    /** Called when a SkAtlasTextureTarget is destroyed. */
+    virtual void targetDeleted(void* targetHandle) = 0;
+};
+
+#endif

+ 100 - 0
skia/include/atlastext/SkAtlasTextTarget.h

@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAtlasTextTarget_DEFINED
+#define SkAtlasTextTarget_DEFINED
+
+#include "SkDeque.h"
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+#include <memory>
+
+class SkAtlasTextContext;
+class SkAtlasTextFont;
+class SkMatrix;
+struct SkPoint;
+
+/** Represents a client-created renderable surface and is used to draw text into the surface. */
+class SK_API SkAtlasTextTarget {
+public:
+    virtual ~SkAtlasTextTarget();
+
+    /**
+     * Creates a text drawing target. ‘handle’ is used to identify this rendering surface when
+     * draws are flushed to the SkAtlasTextContext's SkAtlasTextRenderer.
+     */
+    static std::unique_ptr<SkAtlasTextTarget> Make(sk_sp<SkAtlasTextContext>,
+                                                   int width,
+                                                   int height,
+                                                   void* handle);
+
+    /**
+     * Enqueues a text draw in the target. The caller provides an array of glyphs and their
+     * positions. The meaning of 'color' here is interpreted by the client's SkAtlasTextRenderer
+     * when it actually renders the text.
+     */
+    virtual void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
+                          const SkAtlasTextFont&) = 0;
+
+    /** Issues all queued text draws to SkAtlasTextRenderer. */
+    virtual void flush() = 0;
+
+    int width() const { return fWidth; }
+    int height() const { return fHeight; }
+
+    void* handle() const { return fHandle; }
+
+    SkAtlasTextContext* context() const { return fContext.get(); }
+
+    /** Saves the current matrix in a stack. Returns the prior depth of the saved matrix stack. */
+    int save();
+    /** Pops the top matrix on the stack if the stack is not empty. */
+    void restore();
+    /**
+     * Pops the matrix stack until the stack depth is count. Does nothing if the depth is already
+     * less than count.
+     */
+    void restoreToCount(int count);
+
+    /** Pre-translates the current CTM. */
+    void translate(SkScalar dx, SkScalar dy);
+    /** Pre-scales the current CTM. */
+    void scale(SkScalar sx, SkScalar sy);
+    /** Pre-rotates the current CTM about the origin. */
+    void rotate(SkScalar degrees);
+    /** Pre-rotates the current CTM about the (px, py). */
+    void rotate(SkScalar degrees, SkScalar px, SkScalar py);
+    /** Pre-skews the current CTM. */
+    void skew(SkScalar sx, SkScalar sy);
+    /** Pre-concats the current CTM. */
+    void concat(const SkMatrix& matrix);
+
+protected:
+    SkAtlasTextTarget(sk_sp<SkAtlasTextContext>, int width, int height, void* handle);
+
+    const SkMatrix& ctm() const { return *static_cast<const SkMatrix*>(fMatrixStack.back()); }
+
+    void* const fHandle;
+    const sk_sp<SkAtlasTextContext> fContext;
+    const int fWidth;
+    const int fHeight;
+
+private:
+    SkDeque fMatrixStack;
+    int fSaveCnt;
+
+    SkMatrix* accessCTM() const {
+        return static_cast<SkMatrix*>(const_cast<void*>(fMatrixStack.back()));
+    }
+
+    SkAtlasTextTarget() = delete;
+    SkAtlasTextTarget(const SkAtlasTextContext&) = delete;
+    SkAtlasTextTarget& operator=(const SkAtlasTextContext&) = delete;
+};
+
+#endif

+ 159 - 0
skia/include/c/sk_canvas.h

@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_canvas_DEFINED
+#define sk_canvas_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Save the current matrix and clip on the canvas.  When the
+    balancing call to sk_canvas_restore() is made, the previous matrix
+    and clip are restored.
+*/
+SK_API void sk_canvas_save(sk_canvas_t*);
+/**
+    This behaves the same as sk_canvas_save(), but in addition it
+    allocates an offscreen surface. All drawing calls are directed
+    there, and only when the balancing call to sk_canvas_restore() is
+    made is that offscreen transfered to the canvas (or the previous
+    layer).
+
+    @param sk_rect_t* (may be null) This rect, if non-null, is used as
+                      a hint to limit the size of the offscreen, and
+                      thus drawing may be clipped to it, though that
+                      clipping is not guaranteed to happen. If exact
+                      clipping is desired, use sk_canvas_clip_rect().
+    @param sk_paint_t* (may be null) The paint is copied, and is applied
+                       to the offscreen when sk_canvas_restore() is
+                       called.
+*/
+SK_API void sk_canvas_save_layer(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+    This call balances a previous call to sk_canvas_save() or
+    sk_canvas_save_layer(), and is used to remove all modifications to
+    the matrix and clip state since the last save call.  It is an
+    error to call sk_canvas_restore() more times than save and
+    save_layer were called.
+*/
+SK_API void sk_canvas_restore(sk_canvas_t*);
+
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified translation.
+*/
+SK_API void sk_canvas_translate(sk_canvas_t*, float dx, float dy);
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified scale.
+*/
+SK_API void sk_canvas_scale(sk_canvas_t*, float sx, float sy);
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified rotation in degrees.
+*/
+SK_API void sk_canvas_rotate_degrees(sk_canvas_t*, float degrees);
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified rotation in radians.
+*/
+SK_API void sk_canvas_rotate_radians(sk_canvas_t*, float radians);
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified skew.
+*/
+SK_API void sk_canvas_skew(sk_canvas_t*, float sx, float sy);
+/**
+    Preconcat the current coordinate transformation matrix with the
+    specified matrix.
+*/
+SK_API void sk_canvas_concat(sk_canvas_t*, const sk_matrix_t*);
+
+/**
+    Modify the current clip with the specified rectangle.  The new
+    current clip will be the intersection of the old clip and the
+    rectange.
+*/
+SK_API void sk_canvas_clip_rect(sk_canvas_t*, const sk_rect_t*);
+/**
+    Modify the current clip with the specified path.  The new
+    current clip will be the intersection of the old clip and the
+    path.
+*/
+SK_API void sk_canvas_clip_path(sk_canvas_t*, const sk_path_t*);
+
+/**
+    Fill the entire canvas (restricted to the current clip) with the
+    specified paint.
+*/
+SK_API void sk_canvas_draw_paint(sk_canvas_t*, const sk_paint_t*);
+/**
+    Draw the specified rectangle using the specified paint. The
+    rectangle will be filled or stroked based on the style in the
+    paint.
+*/
+SK_API void sk_canvas_draw_rect(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+ *  Draw the circle centered at (cx, cy) with radius rad using the specified paint.
+ *  The circle will be filled or framed based on the style in the paint
+ */
+SK_API void sk_canvas_draw_circle(sk_canvas_t*, float cx, float cy, float rad, const sk_paint_t*);
+/**
+    Draw the specified oval using the specified paint. The oval will be
+    filled or framed based on the style in the paint
+*/
+SK_API void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*);
+/**
+    Draw the specified path using the specified paint. The path will be
+    filled or framed based on the style in the paint
+*/
+SK_API void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*);
+/**
+    Draw the specified image, with its top/left corner at (x,y), using
+    the specified paint, transformed by the current matrix.
+
+    @param sk_paint_t* (may be NULL) the paint used to draw the image.
+*/
+SK_API void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*,
+                                 float x, float y, const sk_paint_t*);
+/**
+    Draw the specified image, scaling and translating so that it fills
+    the specified dst rect. If the src rect is non-null, only that
+    subset of the image is transformed and drawn.
+
+    @param sk_paint_t* (may be NULL) The paint used to draw the image.
+*/
+SK_API void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*,
+                                      const sk_rect_t* src,
+                                      const sk_rect_t* dst, const sk_paint_t*);
+
+/**
+    Draw the picture into this canvas (replay the pciture's drawing commands).
+
+    @param sk_matrix_t* If non-null, apply that matrix to the CTM when
+                        drawing this picture. This is logically
+                        equivalent to: save, concat, draw_picture,
+                        restore.
+
+    @param sk_paint_t* If non-null, draw the picture into a temporary
+                       buffer, and then apply the paint's alpha,
+                       colorfilter, imagefilter, and xfermode to that
+                       buffer as it is drawn to the canvas.  This is
+                       logically equivalent to save_layer(paint),
+                       draw_picture, restore.
+*/
+SK_API void sk_canvas_draw_picture(sk_canvas_t*, const sk_picture_t*,
+                                   const sk_matrix_t*, const sk_paint_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 25 - 0
skia/include/c/sk_colorspace.h

@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_imageinfo_DEFINED
+#define sk_imageinfo_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+sk_colorspace_t* sk_colorspace_new_srgb();
+
+void sk_colorspace_ref(sk_colorspace_t*);
+void sk_colorspace_unref(sk_colorspace_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 70 - 0
skia/include/c/sk_data.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_data_DEFINED
+#define sk_data_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Returns a new empty sk_data_t.  This call must be balanced with a call to
+    sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_empty(void);
+/**
+    Returns a new sk_data_t by copying the specified source data.
+    This call must be balanced with a call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_with_copy(const void* src, size_t length);
+/**
+    Pass ownership of the given memory to a new sk_data_t, which will
+    call free() when the refernce count of the data goes to zero.  For
+    example:
+        size_t length = 1024;
+        void* buffer = malloc(length);
+        memset(buffer, 'X', length);
+        sk_data_t* data = sk_data_new_from_malloc(buffer, length);
+    This call must be balanced with a call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_from_malloc(const void* memory, size_t length);
+/**
+    Returns a new sk_data_t using a subset of the data in the
+    specified source sk_data_t.  This call must be balanced with a
+    call to sk_data_unref().
+*/
+SK_API sk_data_t* sk_data_new_subset(const sk_data_t* src, size_t offset, size_t length);
+
+/**
+    Increment the reference count on the given sk_data_t. Must be
+    balanced by a call to sk_data_unref().
+*/
+SK_API void sk_data_ref(const sk_data_t*);
+/**
+    Decrement the reference count. If the reference count is 1 before
+    the decrement, then release both the memory holding the sk_data_t
+    and the memory it is managing.  New sk_data_t are created with a
+    reference count of 1.
+*/
+SK_API void sk_data_unref(const sk_data_t*);
+
+/**
+    Returns the number of bytes stored.
+*/
+SK_API size_t sk_data_get_size(const sk_data_t*);
+/**
+    Returns the pointer to the data.
+ */
+SK_API const void* sk_data_get_data(const sk_data_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 71 - 0
skia/include/c/sk_image.h

@@ -0,0 +1,71 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_image_DEFINED
+#define sk_image_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+ *  Return a new image that has made a copy of the provided pixels, or NULL on failure.
+ *  Balance with a call to sk_image_unref().
+ */
+SK_API sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes);
+
+/**
+ *  If the specified data can be interpreted as a compressed image (e.g. PNG or JPEG) then this
+ *  returns an image. If the encoded data is not supported, returns NULL.
+ *
+ *  On success, the encoded data may be processed immediately, or it may be ref()'d for later
+ *  use.
+ */
+SK_API sk_image_t* sk_image_new_from_encoded(const sk_data_t* encoded, const sk_irect_t* subset);
+
+/**
+ *  Encode the image's pixels and return the result as a new PNG in a
+ *  sk_data_t, which the caller must manage: call sk_data_unref() when
+ *  they are done.
+ *
+ *  If the image type cannot be encoded, this will return NULL.
+ */
+SK_API sk_data_t* sk_image_encode(const sk_image_t*);
+
+/**
+ *  Increment the reference count on the given sk_image_t. Must be
+ *  balanced by a call to sk_image_unref().
+*/
+SK_API void sk_image_ref(const sk_image_t*);
+/**
+ *  Decrement the reference count. If the reference count is 1 before
+ *  the decrement, then release both the memory holding the sk_image_t
+ *  and the memory it is managing.  New sk_image_t are created with a
+    reference count of 1.
+*/
+SK_API void sk_image_unref(const sk_image_t*);
+
+/**
+ *  Return the width of the sk_image_t/
+ */
+SK_API int sk_image_get_width(const sk_image_t*);
+/**
+ *  Return the height of the sk_image_t/
+ */
+SK_API int sk_image_get_height(const sk_image_t*);
+
+/**
+ *  Returns a non-zero value unique among all images.
+ */
+SK_API uint32_t sk_image_get_unique_id(const sk_image_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 62 - 0
skia/include/c/sk_imageinfo.h

@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_imageinfo_DEFINED
+#define sk_imageinfo_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef enum {
+    UNKNOWN_SK_COLORTYPE,
+    RGBA_8888_SK_COLORTYPE,
+    BGRA_8888_SK_COLORTYPE,
+    ALPHA_8_SK_COLORTYPE,
+    GRAY_8_SK_COLORTYPE,
+    RGBA_F16_SK_COLORTYPE,
+    RGBA_F32_SK_COLORTYPE,
+} sk_colortype_t;
+
+typedef enum {
+    OPAQUE_SK_ALPHATYPE,
+    PREMUL_SK_ALPHATYPE,
+    UNPREMUL_SK_ALPHATYPE,
+} sk_alphatype_t;
+
+/**
+ *  Allocate a new imageinfo object. If colorspace is not null, it's owner-count will be
+ *  incremented automatically.
+ */
+sk_imageinfo_t* sk_imageinfo_new(int width, int height, sk_colortype_t ct, sk_alphatype_t at,
+                                 sk_colorspace_t* cs);
+
+/**
+ *  Free the imageinfo object. If it contains a reference to a colorspace, its owner-count will
+ *  be decremented automatically.
+ */
+void sk_imageinfo_delete(sk_imageinfo_t*);
+
+int32_t          sk_imageinfo_get_width(sk_imageinfo_t*);
+int32_t          sk_imageinfo_get_height(sk_imageinfo_t*);
+sk_colortype_t   sk_imageinfo_get_colortype(sk_imageinfo_t*);
+sk_alphatype_t   sk_imageinfo_get_alphatype(sk_imageinfo_t*);
+
+/**
+ *  Return the colorspace object reference contained in the imageinfo, or null if there is none.
+ *  Note: this does not modify the owner-count on the colorspace object. If the caller needs to
+ *  use the colorspace beyond the lifetime of the imageinfo, it should manually call
+ *  sk_colorspace_ref() (and then call unref() when it is done).
+ */
+sk_colorspace_t* sk_imageinfo_get_colorspace(sk_imageinfo_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 47 - 0
skia/include/c/sk_maskfilter.h

@@ -0,0 +1,47 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_maskfilter_DEFINED
+#define sk_maskfilter_DEFINED
+
+#include "sk_types.h"
+
+typedef enum {
+    NORMAL_SK_BLUR_STYLE,   //!< fuzzy inside and outside
+    SOLID_SK_BLUR_STYLE,    //!< solid inside, fuzzy outside
+    OUTER_SK_BLUR_STYLE,    //!< nothing inside, fuzzy outside
+    INNER_SK_BLUR_STYLE,    //!< fuzzy inside, nothing outside
+} sk_blurstyle_t;
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Increment the reference count on the given sk_maskfilter_t. Must be
+    balanced by a call to sk_maskfilter_unref().
+*/
+void sk_maskfilter_ref(sk_maskfilter_t*);
+/**
+    Decrement the reference count. If the reference count is 1 before
+    the decrement, then release both the memory holding the
+    sk_maskfilter_t and any other associated resources.  New
+    sk_maskfilter_t are created with a reference count of 1.
+*/
+void sk_maskfilter_unref(sk_maskfilter_t*);
+
+/**
+    Create a blur maskfilter.
+    @param sk_blurstyle_t The SkBlurStyle to use
+    @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
+*/
+sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 49 - 0
skia/include/c/sk_matrix.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_matrix_DEFINED
+#define sk_matrix_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/** Set the matrix to identity */
+void sk_matrix_set_identity(sk_matrix_t*);
+
+/** Set the matrix to translate by (tx, ty). */
+void sk_matrix_set_translate(sk_matrix_t*, float tx, float ty);
+/**
+    Preconcats the matrix with the specified translation.
+        M' = M * T(dx, dy)
+*/
+void sk_matrix_pre_translate(sk_matrix_t*, float tx, float ty);
+/**
+    Postconcats the matrix with the specified translation.
+        M' = T(dx, dy) * M
+*/
+void sk_matrix_post_translate(sk_matrix_t*, float tx, float ty);
+
+/** Set the matrix to scale by sx and sy. */
+void sk_matrix_set_scale(sk_matrix_t*, float sx, float sy);
+/**
+    Preconcats the matrix with the specified scale.
+        M' = M * S(sx, sy)
+*/
+void sk_matrix_pre_scale(sk_matrix_t*, float sx, float sy);
+/**
+    Postconcats the matrix with the specified scale.
+        M' = S(sx, sy) * M
+*/
+void sk_matrix_post_scale(sk_matrix_t*, float sx, float sy);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 145 - 0
skia/include/c/sk_paint.h

@@ -0,0 +1,145 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_paint_DEFINED
+#define sk_paint_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Create a new paint with default settings:
+        antialias : false
+        stroke : false
+        stroke width : 0.0f (hairline)
+        stroke miter : 4.0f
+        stroke cap : BUTT_SK_STROKE_CAP
+        stroke join : MITER_SK_STROKE_JOIN
+        color : opaque black
+        shader : NULL
+        maskfilter : NULL
+        xfermode_mode : SRCOVER_SK_XFERMODE_MODE
+*/
+SK_API sk_paint_t* sk_paint_new(void);
+/**
+    Release the memory storing the sk_paint_t and unref() all
+    associated objects.
+*/
+SK_API void sk_paint_delete(sk_paint_t*);
+
+/**
+    Return true iff the paint has antialiasing enabled.
+*/
+SK_API bool sk_paint_is_antialias(const sk_paint_t*);
+/**
+    Set to true to enable antialiasing, false to disable it on this
+    sk_paint_t.
+*/
+SK_API void sk_paint_set_antialias(sk_paint_t*, bool);
+
+/**
+    Return the paint's curent drawing color.
+*/
+SK_API sk_color_t sk_paint_get_color(const sk_paint_t*);
+/**
+    Set the paint's curent drawing color.
+*/
+SK_API void sk_paint_set_color(sk_paint_t*, sk_color_t);
+
+/* stroke settings */
+
+/**
+    Return true iff stroking is enabled rather than filling on this
+    sk_paint_t.
+*/
+SK_API bool sk_paint_is_stroke(const sk_paint_t*);
+/**
+    Set to true to enable stroking rather than filling with this
+    sk_paint_t.
+*/
+SK_API void sk_paint_set_stroke(sk_paint_t*, bool);
+
+/**
+    Return the width for stroking.  A value of 0 strokes in hairline mode.
+ */
+SK_API float sk_paint_get_stroke_width(const sk_paint_t*);
+/**
+   Set the width for stroking.  A value of 0 strokes in hairline mode
+   (always draw 1-pixel wide, regardless of the matrix).
+ */
+SK_API void sk_paint_set_stroke_width(sk_paint_t*, float width);
+
+/**
+    Return the paint's stroke miter value. This is used to control the
+    behavior of miter joins when the joins angle is sharp.
+*/
+SK_API float sk_paint_get_stroke_miter(const sk_paint_t*);
+/**
+   Set the paint's stroke miter value. This is used to control the
+   behavior of miter joins when the joins angle is sharp. This value
+   must be >= 0.
+*/
+SK_API void sk_paint_set_stroke_miter(sk_paint_t*, float miter);
+
+typedef enum {
+    BUTT_SK_STROKE_CAP,
+    ROUND_SK_STROKE_CAP,
+    SQUARE_SK_STROKE_CAP
+} sk_stroke_cap_t;
+
+/**
+    Return the paint's stroke cap type, controlling how the start and
+    end of stroked lines and paths are treated.
+*/
+SK_API sk_stroke_cap_t sk_paint_get_stroke_cap(const sk_paint_t*);
+/**
+    Set the paint's stroke cap type, controlling how the start and
+    end of stroked lines and paths are treated.
+*/
+SK_API void sk_paint_set_stroke_cap(sk_paint_t*, sk_stroke_cap_t);
+
+typedef enum {
+    MITER_SK_STROKE_JOIN,
+    ROUND_SK_STROKE_JOIN,
+    BEVEL_SK_STROKE_JOIN
+} sk_stroke_join_t;
+
+/**
+    Return the paint's stroke join type, specifies the treatment that
+    is applied to corners in paths and rectangles
+ */
+SK_API sk_stroke_join_t sk_paint_get_stroke_join(const sk_paint_t*);
+/**
+    Set the paint's stroke join type, specifies the treatment that
+    is applied to corners in paths and rectangles
+ */
+SK_API void sk_paint_set_stroke_join(sk_paint_t*, sk_stroke_join_t);
+
+/**
+ *  Set the paint's shader to the specified parameter. This will automatically call unref() on
+ *  any previous value, and call ref() on the new value.
+ */
+SK_API void sk_paint_set_shader(sk_paint_t*, sk_shader_t*);
+
+/**
+ *  Set the paint's maskfilter to the specified parameter. This will automatically call unref() on
+ *  any previous value, and call ref() on the new value.
+ */
+SK_API void sk_paint_set_maskfilter(sk_paint_t*, sk_maskfilter_t*);
+
+/**
+ *  Set the paint's xfermode to the specified parameter.
+ */
+SK_API void sk_paint_set_xfermode_mode(sk_paint_t*, sk_xfermode_mode_t);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 84 - 0
skia/include/c/sk_path.h

@@ -0,0 +1,84 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_path_DEFINED
+#define sk_path_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef enum {
+    CW_SK_PATH_DIRECTION,
+    CCW_SK_PATH_DIRECTION,
+} sk_path_direction_t;
+
+/** Create a new, empty path. */
+SK_API sk_path_t* sk_path_new(void);
+/** Release the memory used by a sk_path_t. */
+SK_API void sk_path_delete(sk_path_t*);
+
+/** Set the beginning of the next contour to the point (x,y). */
+SK_API void sk_path_move_to(sk_path_t*, float x, float y);
+/**
+    Add a line from the last point to the specified point (x,y). If no
+    sk_path_move_to() call has been made for this contour, the first
+    point is automatically set to (0,0).
+*/
+SK_API void sk_path_line_to(sk_path_t*, float x, float y);
+/**
+    Add a quadratic bezier from the last point, approaching control
+    point (x0,y0), and ending at (x1,y1). If no sk_path_move_to() call
+    has been made for this contour, the first point is automatically
+    set to (0,0).
+*/
+SK_API void sk_path_quad_to(sk_path_t*, float x0, float y0, float x1, float y1);
+/**
+    Add a conic curve from the last point, approaching control point
+    (x0,y01), and ending at (x1,y1) with weight w.  If no
+    sk_path_move_to() call has been made for this contour, the first
+    point is automatically set to (0,0).
+*/
+SK_API void sk_path_conic_to(sk_path_t*, float x0, float y0, float x1, float y1, float w);
+/**
+    Add a cubic bezier from the last point, approaching control points
+    (x0,y0) and (x1,y1), and ending at (x2,y2). If no
+    sk_path_move_to() call has been made for this contour, the first
+    point is automatically set to (0,0).
+*/
+SK_API void sk_path_cubic_to(sk_path_t*,
+                             float x0, float y0,
+                             float x1, float y1,
+                             float x2, float y2);
+/**
+   Close the current contour. If the current point is not equal to the
+   first point of the contour, a line segment is automatically added.
+*/
+SK_API void sk_path_close(sk_path_t*);
+
+/**
+    Add a closed rectangle contour to the path.
+*/
+SK_API void sk_path_add_rect(sk_path_t*, const sk_rect_t*, sk_path_direction_t);
+/**
+    Add a closed oval contour to the path
+*/
+SK_API void sk_path_add_oval(sk_path_t*, const sk_rect_t*, sk_path_direction_t);
+
+/**
+ *  If the path is empty, return false and set the rect parameter to [0, 0, 0, 0].
+ *  else return true and set the rect parameter to the bounds of the control-points
+ *  of the path.
+ */
+SK_API bool sk_path_get_bounds(const sk_path_t*, sk_rect_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 70 - 0
skia/include/c/sk_picture.h

@@ -0,0 +1,70 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_picture_DEFINED
+#define sk_picture_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Create a new sk_picture_recorder_t.  Its resources should be
+    released with a call to sk_picture_recorder_delete().
+*/
+sk_picture_recorder_t* sk_picture_recorder_new(void);
+/**
+    Release the memory and other resources used by this
+    sk_picture_recorder_t.
+*/
+void sk_picture_recorder_delete(sk_picture_recorder_t*);
+
+/**
+   Returns the canvas that records the drawing commands
+
+   @param sk_rect_t* the cull rect used when recording this
+                     picture. Any drawing the falls outside of this
+                     rect is undefined, and may be drawn or it may not.
+*/
+sk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t*, const sk_rect_t*);
+/**
+    Signal that the caller is done recording. This invalidates the
+    canvas returned by begin_recording. Ownership of the sk_picture_t
+    is passed to the caller, who must call sk_picture_unref() when
+    they are done using it.  The returned picture is immutable.
+*/
+sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t*);
+
+/**
+    Increment the reference count on the given sk_picture_t. Must be
+    balanced by a call to sk_picture_unref().
+*/
+void sk_picture_ref(sk_picture_t*);
+/**
+    Decrement the reference count. If the reference count is 1 before
+    the decrement, then release both the memory holding the
+    sk_picture_t and any resouces it may be managing.  New
+    sk_picture_t are created with a reference count of 1.
+*/
+void sk_picture_unref(sk_picture_t*);
+
+/**
+    Returns a non-zero value unique among all pictures.
+ */
+uint32_t sk_picture_get_unique_id(sk_picture_t*);
+
+/**
+    Return the cull rect specified when this picture was recorded.
+*/
+sk_rect_t sk_picture_get_bounds(sk_picture_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 143 - 0
skia/include/c/sk_shader.h

@@ -0,0 +1,143 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_shader_DEFINED
+#define sk_shader_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+void sk_shader_ref(sk_shader_t*);
+void sk_shader_unref(sk_shader_t*);
+
+typedef enum {
+    CLAMP_SK_SHADER_TILEMODE,
+    REPEAT_SK_SHADER_TILEMODE,
+    MIRROR_SK_SHADER_TILEMODE,
+} sk_shader_tilemode_t;
+
+/**
+    Returns a shader that generates a linear gradient between the two
+    specified points.
+
+    @param points The start and end points for the gradient.
+    @param colors The array[count] of colors, to be distributed between
+                  the two points
+    @param colorPos May be NULL. array[count] of SkScalars, or NULL, of
+                    the relative position of each corresponding color
+                    in the colors array. If this is NULL, the the
+                    colors are distributed evenly between the start
+                    and end point.  If this is not null, the values
+                    must begin with 0, end with 1.0, and intermediate
+                    values must be strictly increasing.
+    @param colorCount Must be >=2. The number of colors (and pos if not
+                      NULL) entries.
+    @param mode The tiling mode
+*/
+sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t points[2],
+                                           const sk_color_t colors[],
+                                           const float colorPos[],
+                                           int colorCount,
+                                           sk_shader_tilemode_t tileMode,
+                                           const sk_matrix_t* localMatrix);
+
+
+/**
+    Returns a shader that generates a radial gradient given the center
+    and radius.
+
+    @param center The center of the circle for this gradient
+    @param radius Must be positive. The radius of the circle for this
+                  gradient
+    @param colors The array[count] of colors, to be distributed
+                  between the center and edge of the circle
+    @param colorPos May be NULL. The array[count] of the relative
+                    position of each corresponding color in the colors
+                    array. If this is NULL, the the colors are
+                    distributed evenly between the center and edge of
+                    the circle.  If this is not null, the values must
+                    begin with 0, end with 1.0, and intermediate
+                    values must be strictly increasing.
+    @param count Must be >= 2. The number of colors (and pos if not
+                 NULL) entries
+    @param tileMode The tiling mode
+    @param localMatrix May be NULL
+*/
+sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center,
+                                           float radius,
+                                           const sk_color_t colors[],
+                                           const float colorPos[],
+                                           int colorCount,
+                                           sk_shader_tilemode_t tileMode,
+                                           const sk_matrix_t* localMatrix);
+
+/**
+    Returns a shader that generates a sweep gradient given a center.
+
+    @param center The coordinates of the center of the sweep
+    @param colors The array[count] of colors, to be distributed around
+                  the center.
+    @param colorPos May be NULL. The array[count] of the relative
+                    position of each corresponding color in the colors
+                    array. If this is NULL, the the colors are
+                    distributed evenly between the center and edge of
+                    the circle.  If this is not null, the values must
+                    begin with 0, end with 1.0, and intermediate
+                    values must be strictly increasing.
+    @param colorCount Must be >= 2. The number of colors (and pos if
+                      not NULL) entries
+    @param localMatrix May be NULL
+*/
+sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center,
+                                          const sk_color_t colors[],
+                                          const float colorPos[],
+                                          int colorCount,
+                                          const sk_matrix_t* localMatrix);
+
+/**
+    Returns a shader that generates a conical gradient given two circles, or
+    returns NULL if the inputs are invalid. The gradient interprets the
+    two circles according to the following HTML spec.
+    http://dev.w3.org/html5/2dcontext/#dom-context-2d-createradialgradient
+
+    Returns a shader that generates a sweep gradient given a center.
+
+    @param start, startRadius Defines the first circle.
+    @param end, endRadius Defines the first circle.
+    @param colors The array[count] of colors, to be distributed between
+                  the two circles.
+    @param colorPos May be NULL. The array[count] of the relative
+                    position of each corresponding color in the colors
+                    array. If this is NULL, the the colors are
+                    distributed evenly between the two circles.  If
+                    this is not null, the values must begin with 0,
+                    end with 1.0, and intermediate values must be
+                    strictly increasing.
+    @param colorCount Must be >= 2. The number of colors (and pos if
+                      not NULL) entries
+    @param tileMode The tiling mode
+    @param localMatrix May be NULL
+
+*/
+sk_shader_t* sk_shader_new_two_point_conical_gradient(
+        const sk_point_t* start,
+        float startRadius,
+        const sk_point_t* end,
+        float endRadius,
+        const sk_color_t colors[],
+        const float colorPos[],
+        int colorCount,
+        sk_shader_tilemode_t tileMode,
+        const sk_matrix_t* localMatrix);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 73 - 0
skia/include/c/sk_surface.h

@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_surface_DEFINED
+#define sk_surface_DEFINED
+
+#include "sk_types.h"
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+/**
+    Return a new surface, with the memory for the pixels automatically
+    allocated.  If the requested surface cannot be created, or the
+    request is not a supported configuration, NULL will be returned.
+
+    @param sk_imageinfo_t* Specify the width, height, color type, and
+                           alpha type for the surface.
+
+    @param sk_surfaceprops_t* If not NULL, specify additional non-default
+                              properties of the surface.
+*/
+SK_API sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*, const sk_surfaceprops_t*);
+
+/**
+    Create a new surface which will draw into the specified pixels
+    with the specified rowbytes.  If the requested surface cannot be
+    created, or the request is not a supported configuration, NULL
+    will be returned.
+
+    @param sk_imageinfo_t* Specify the width, height, color type, and
+                           alpha type for the surface.
+    @param void* pixels Specify the location in memory where the
+                        destination pixels are.  This memory must
+                        outlast this surface.
+     @param size_t rowBytes Specify the difference, in bytes, between
+                           each adjacent row.  Should be at least
+                           (width * sizeof(one pixel)).
+    @param sk_surfaceprops_t* If not NULL, specify additional non-default
+                              properties of the surface.
+*/
+SK_API sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*,
+                                                  void* pixels, size_t rowBytes,
+                                                  const sk_surfaceprops_t* props);
+
+/**
+    Decrement the reference count. If the reference count is 1 before
+    the decrement, then release both the memory holding the
+    sk_surface_t and any pixel memory it may be managing.  New
+    sk_surface_t are created with a reference count of 1.
+*/
+SK_API void sk_surface_unref(sk_surface_t*);
+
+/**
+ *  Return the canvas associated with this surface. Note: the canvas is owned by the surface,
+ *  so the returned object is only valid while the owning surface is valid.
+ */
+SK_API sk_canvas_t* sk_surface_get_canvas(sk_surface_t*);
+
+/**
+ *  Call sk_image_unref() when the returned image is no longer used.
+ */
+SK_API sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*);
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 256 - 0
skia/include/c/sk_types.h

@@ -0,0 +1,256 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL EXPERIMENTAL
+// DO NOT USE -- FOR INTERNAL TESTING ONLY
+
+#ifndef sk_types_DEFINED
+#define sk_types_DEFINED
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+    #define SK_C_PLUS_PLUS_BEGIN_GUARD    extern "C" {
+    #define SK_C_PLUS_PLUS_END_GUARD      }
+#else
+    #include <stdbool.h>
+    #define SK_C_PLUS_PLUS_BEGIN_GUARD
+    #define SK_C_PLUS_PLUS_END_GUARD
+#endif
+
+#if !defined(SK_API)
+    #if defined(SKIA_DLL)
+        #if defined(_MSC_VER)
+            #if SKIA_IMPLEMENTATION
+                #define SK_API __declspec(dllexport)
+            #else
+                #define SK_API __declspec(dllimport)
+            #endif
+        #else
+            #define SK_API __attribute__((visibility("default")))
+        #endif
+    #else
+        #define SK_API
+    #endif
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+SK_C_PLUS_PLUS_BEGIN_GUARD
+
+typedef uint32_t sk_color_t;
+
+/* This macro assumes all arguments are >=0 and <=255. */
+#define sk_color_set_argb(a, r, g, b)   (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define sk_color_get_a(c)               (((c) >> 24) & 0xFF)
+#define sk_color_get_r(c)               (((c) >> 16) & 0xFF)
+#define sk_color_get_g(c)               (((c) >>  8) & 0xFF)
+#define sk_color_get_b(c)               (((c) >>  0) & 0xFF)
+
+typedef enum {
+    INTERSECT_SK_CLIPTYPE,
+    DIFFERENCE_SK_CLIPTYPE,
+} sk_cliptype_t;
+
+typedef enum {
+    UNKNOWN_SK_PIXELGEOMETRY,
+    RGB_H_SK_PIXELGEOMETRY,
+    BGR_H_SK_PIXELGEOMETRY,
+    RGB_V_SK_PIXELGEOMETRY,
+    BGR_V_SK_PIXELGEOMETRY,
+} sk_pixelgeometry_t;
+
+typedef struct {
+    sk_pixelgeometry_t pixelGeometry;
+} sk_surfaceprops_t;
+
+typedef struct {
+    float   x;
+    float   y;
+} sk_point_t;
+
+typedef struct {
+    int32_t left;
+    int32_t top;
+    int32_t right;
+    int32_t bottom;
+} sk_irect_t;
+
+typedef struct {
+    float   left;
+    float   top;
+    float   right;
+    float   bottom;
+} sk_rect_t;
+
+/**
+    The sk_matrix_t struct holds a 3x3 perspective matrix for
+    transforming coordinates:
+
+        (X,Y) = T[M]((x,y))
+        X = (M[0] * x + M[1] * y + M[2]) / (M[6] * x + M[7] * y + M[8]);
+        Y = (M[3] * x + M[4] * y + M[5]) / (M[6] * x + M[7] * y + M[8]);
+
+    Therefore, the identity matrix is
+
+        sk_matrix_t identity = {{1, 0, 0,
+                                 0, 1, 0,
+                                 0, 0, 1}};
+
+    A matrix that scales by sx and sy is:
+
+        sk_matrix_t scale = {{sx, 0,  0,
+                              0,  sy, 0,
+                              0,  0,  1}};
+
+    A matrix that translates by tx and ty is:
+
+        sk_matrix_t translate = {{1, 0, tx,
+                                  0, 1, ty,
+                                  0, 0, 1}};
+
+    A matrix that rotates around the origin by A radians:
+
+        sk_matrix_t rotate = {{cos(A), -sin(A), 0,
+                               sin(A),  cos(A), 0,
+                               0,       0,      1}};
+
+    Two matrixes can be concatinated by:
+
+         void concat_matrices(sk_matrix_t* dst,
+                             const sk_matrix_t* matrixU,
+                             const sk_matrix_t* matrixV) {
+            const float* u = matrixU->mat;
+            const float* v = matrixV->mat;
+            sk_matrix_t result = {{
+                    u[0] * v[0] + u[1] * v[3] + u[2] * v[6],
+                    u[0] * v[1] + u[1] * v[4] + u[2] * v[7],
+                    u[0] * v[2] + u[1] * v[5] + u[2] * v[8],
+                    u[3] * v[0] + u[4] * v[3] + u[5] * v[6],
+                    u[3] * v[1] + u[4] * v[4] + u[5] * v[7],
+                    u[3] * v[2] + u[4] * v[5] + u[5] * v[8],
+                    u[6] * v[0] + u[7] * v[3] + u[8] * v[6],
+                    u[6] * v[1] + u[7] * v[4] + u[8] * v[7],
+                    u[6] * v[2] + u[7] * v[5] + u[8] * v[8]
+            }};
+            *dst = result;
+        }
+*/
+typedef struct {
+    float   mat[9];
+} sk_matrix_t;
+
+/**
+    A sk_canvas_t encapsulates all of the state about drawing into a
+    destination This includes a reference to the destination itself,
+    and a stack of matrix/clip values.
+*/
+typedef struct sk_canvas_t sk_canvas_t;
+/**
+    A sk_data_ holds an immutable data buffer.
+*/
+typedef struct sk_data_t sk_data_t;
+/**
+    A sk_image_t is an abstraction for drawing a rectagle of pixels.
+    The content of the image is always immutable, though the actual
+    storage may change, if for example that image can be re-created via
+    encoded data or other means.
+*/
+typedef struct sk_image_t sk_image_t;
+
+/**
+ *  Describes the color components. See ICC Profiles.
+ */
+typedef struct sk_colorspace_t sk_colorspace_t;
+
+/**
+ *  Describes an image buffer : width, height, pixel type, colorspace, etc.
+ */
+typedef struct sk_imageinfo_t sk_imageinfo_t;
+
+/**
+    A sk_maskfilter_t is an object that perform transformations on an
+    alpha-channel mask before drawing it; it may be installed into a
+    sk_paint_t.  Each time a primitive is drawn, it is first
+    scan-converted into a alpha mask, which os handed to the
+    maskfilter, which may create a new mask is to render into the
+    destination.
+ */
+typedef struct sk_maskfilter_t sk_maskfilter_t;
+/**
+    A sk_paint_t holds the style and color information about how to
+    draw geometries, text and bitmaps.
+*/
+typedef struct sk_paint_t sk_paint_t;
+/**
+    A sk_path_t encapsulates compound (multiple contour) geometric
+    paths consisting of straight line segments, quadratic curves, and
+    cubic curves.
+*/
+typedef struct sk_path_t sk_path_t;
+/**
+    A sk_picture_t holds recorded canvas drawing commands to be played
+    back at a later time.
+*/
+typedef struct sk_picture_t sk_picture_t;
+/**
+    A sk_picture_recorder_t holds a sk_canvas_t that records commands
+    to create a sk_picture_t.
+*/
+typedef struct sk_picture_recorder_t sk_picture_recorder_t;
+/**
+    A sk_shader_t specifies the source color(s) for what is being drawn. If a
+    paint has no shader, then the paint's color is used. If the paint
+    has a shader, then the shader's color(s) are use instead, but they
+    are modulated by the paint's alpha.
+*/
+typedef struct sk_shader_t sk_shader_t;
+/**
+    A sk_surface_t holds the destination for drawing to a canvas. For
+    raster drawing, the destination is an array of pixels in memory.
+    For GPU drawing, the destination is a texture or a framebuffer.
+*/
+typedef struct sk_surface_t sk_surface_t;
+
+typedef enum {
+    CLEAR_SK_XFERMODE_MODE,
+    SRC_SK_XFERMODE_MODE,
+    DST_SK_XFERMODE_MODE,
+    SRCOVER_SK_XFERMODE_MODE,
+    DSTOVER_SK_XFERMODE_MODE,
+    SRCIN_SK_XFERMODE_MODE,
+    DSTIN_SK_XFERMODE_MODE,
+    SRCOUT_SK_XFERMODE_MODE,
+    DSTOUT_SK_XFERMODE_MODE,
+    SRCATOP_SK_XFERMODE_MODE,
+    DSTATOP_SK_XFERMODE_MODE,
+    XOR_SK_XFERMODE_MODE,
+    PLUS_SK_XFERMODE_MODE,
+    MODULATE_SK_XFERMODE_MODE,
+    SCREEN_SK_XFERMODE_MODE,
+    OVERLAY_SK_XFERMODE_MODE,
+    DARKEN_SK_XFERMODE_MODE,
+    LIGHTEN_SK_XFERMODE_MODE,
+    COLORDODGE_SK_XFERMODE_MODE,
+    COLORBURN_SK_XFERMODE_MODE,
+    HARDLIGHT_SK_XFERMODE_MODE,
+    SOFTLIGHT_SK_XFERMODE_MODE,
+    DIFFERENCE_SK_XFERMODE_MODE,
+    EXCLUSION_SK_XFERMODE_MODE,
+    MULTIPLY_SK_XFERMODE_MODE,
+    HUE_SK_XFERMODE_MODE,
+    SATURATION_SK_XFERMODE_MODE,
+    COLOR_SK_XFERMODE_MODE,
+    LUMINOSITY_SK_XFERMODE_MODE,
+} sk_xfermode_mode_t;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+SK_C_PLUS_PLUS_END_GUARD
+
+#endif

+ 287 - 0
skia/include/codec/SkAndroidCodec.h

@@ -0,0 +1,287 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAndroidCodec_DEFINED
+#define SkAndroidCodec_DEFINED
+
+#include "SkCodec.h"
+#include "SkEncodedImageFormat.h"
+#include "SkStream.h"
+#include "SkTypes.h"
+
+/**
+ *  Abstract interface defining image codec functionality that is necessary for
+ *  Android.
+ */
+class SK_API SkAndroidCodec : SkNoncopyable {
+public:
+    enum class ExifOrientationBehavior {
+        /**
+         *  Ignore any exif orientation markers in the data.
+         *
+         *  getInfo's width and height will match the header of the image, and
+         *  no processing will be done to match the marker.
+         */
+        kIgnore,
+
+        /**
+         *  Respect the exif orientation marker.
+         *
+         *  getInfo's width and height will represent what they should be after
+         *  applying the orientation. For example, if the marker specifies a
+         *  rotation by 90 degrees, they will be swapped relative to the header.
+         *  getAndroidPixels will apply the orientation as well.
+         */
+        kRespect,
+    };
+
+    /**
+     *  Pass ownership of an SkCodec to a newly-created SkAndroidCodec.
+     */
+    static std::unique_ptr<SkAndroidCodec> MakeFromCodec(std::unique_ptr<SkCodec>,
+            ExifOrientationBehavior = ExifOrientationBehavior::kIgnore);
+
+    /**
+     *  If this stream represents an encoded image that we know how to decode,
+     *  return an SkAndroidCodec that can decode it. Otherwise return NULL.
+     *
+     *  The SkPngChunkReader handles unknown chunks in PNGs.
+     *  See SkCodec.h for more details.
+     *
+     *  If NULL is returned, the stream is deleted immediately. Otherwise, the
+     *  SkCodec takes ownership of it, and will delete it when done with it.
+     *
+     *  ExifOrientationBehavior is set to kIgnore.
+     */
+    static std::unique_ptr<SkAndroidCodec> MakeFromStream(std::unique_ptr<SkStream>,
+                                                          SkPngChunkReader* = nullptr);
+
+    /**
+     *  If this data represents an encoded image that we know how to decode,
+     *  return an SkAndroidCodec that can decode it. Otherwise return NULL.
+     *
+     *  The SkPngChunkReader handles unknown chunks in PNGs.
+     *  See SkCodec.h for more details.
+     *
+     *  ExifOrientationBehavior is set to kIgnore.
+     */
+    static std::unique_ptr<SkAndroidCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
+
+    virtual ~SkAndroidCodec();
+
+    const SkImageInfo& getInfo() const { return fInfo; }
+
+    /**
+     *  Format of the encoded data.
+     */
+    SkEncodedImageFormat getEncodedFormat() const { return fCodec->getEncodedFormat(); }
+
+    /**
+     *  @param requestedColorType Color type requested by the client
+     *
+     *  |requestedColorType| may be overriden.  We will default to kF16
+     *  for high precision images.
+     *
+     *  In the general case, if it is possible to decode to
+     *  |requestedColorType|, this returns |requestedColorType|.
+     *  Otherwise, this returns a color type that is an appropriate
+     *  match for the the encoded data.
+     */
+    SkColorType computeOutputColorType(SkColorType requestedColorType);
+
+    /**
+     *  @param requestedUnpremul  Indicates if the client requested
+     *                            unpremultiplied output
+     *
+     *  Returns the appropriate alpha type to decode to.  If the image
+     *  has alpha, the value of requestedUnpremul will be honored.
+     */
+    SkAlphaType computeOutputAlphaType(bool requestedUnpremul);
+
+    /**
+     *  @param outputColorType Color type that the client will decode to.
+     *  @param prefColorSpace  Preferred color space to decode to.
+     *                         This may not return |prefColorSpace| for a couple reasons.
+     *                         (1) Android Principles: 565 must be sRGB, F16 must be
+     *                             linear sRGB, transfer function must be parametric.
+     *                         (2) Codec Limitations: F16 requires a linear color space.
+     *
+     *  Returns the appropriate color space to decode to.
+     */
+    sk_sp<SkColorSpace> computeOutputColorSpace(SkColorType outputColorType,
+                                                sk_sp<SkColorSpace> prefColorSpace = nullptr);
+
+    /**
+     *  Compute the appropriate sample size to get to |size|.
+     *
+     *  @param size As an input parameter, the desired output size of
+     *      the decode. As an output parameter, the smallest sampled size
+     *      larger than the input.
+     *  @return the sample size to set AndroidOptions::fSampleSize to decode
+     *      to the output |size|.
+     */
+    int computeSampleSize(SkISize* size) const;
+
+    /**
+     *  Returns the dimensions of the scaled output image, for an input
+     *  sampleSize.
+     *
+     *  When the sample size divides evenly into the original dimensions, the
+     *  scaled output dimensions will simply be equal to the original
+     *  dimensions divided by the sample size.
+     *
+     *  When the sample size does not divide even into the original
+     *  dimensions, the codec may round up or down, depending on what is most
+     *  efficient to decode.
+     *
+     *  Finally, the codec will always recommend a non-zero output, so the output
+     *  dimension will always be one if the sampleSize is greater than the
+     *  original dimension.
+     */
+    SkISize getSampledDimensions(int sampleSize) const;
+
+    /**
+     *  Return (via desiredSubset) a subset which can decoded from this codec,
+     *  or false if the input subset is invalid.
+     *
+     *  @param desiredSubset in/out parameter
+     *                       As input, a desired subset of the original bounds
+     *                       (as specified by getInfo).
+     *                       As output, if true is returned, desiredSubset may
+     *                       have been modified to a subset which is
+     *                       supported. Although a particular change may have
+     *                       been made to desiredSubset to create something
+     *                       supported, it is possible other changes could
+     *                       result in a valid subset.  If false is returned,
+     *                       desiredSubset's value is undefined.
+     *  @return true         If the input desiredSubset is valid.
+     *                       desiredSubset may be modified to a subset
+     *                       supported by the codec.
+     *          false        If desiredSubset is invalid (NULL or not fully
+     *                       contained within the image).
+     */
+    bool getSupportedSubset(SkIRect* desiredSubset) const;
+    // TODO: Rename SkCodec::getValidSubset() to getSupportedSubset()
+
+    /**
+     *  Returns the dimensions of the scaled, partial output image, for an
+     *  input sampleSize and subset.
+     *
+     *  @param sampleSize Factor to scale down by.
+     *  @param subset     Must be a valid subset of the original image
+     *                    dimensions and a subset supported by SkAndroidCodec.
+     *                    getSubset() can be used to obtain a subset supported
+     *                    by SkAndroidCodec.
+     *  @return           Size of the scaled partial image.  Or zero size
+     *                    if either of the inputs is invalid.
+     */
+    SkISize getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const;
+
+    /**
+     *  Additional options to pass to getAndroidPixels().
+     */
+    // FIXME: It's a bit redundant to name these AndroidOptions when this class is already
+    //        called SkAndroidCodec.  On the other hand, it's may be a bit confusing to call
+    //        these Options when SkCodec has a slightly different set of Options.  Maybe these
+    //        should be DecodeOptions or SamplingOptions?
+    struct AndroidOptions {
+        AndroidOptions()
+            : fZeroInitialized(SkCodec::kNo_ZeroInitialized)
+            , fSubset(nullptr)
+            , fSampleSize(1)
+        {}
+
+        /**
+         *  Indicates is destination pixel memory is zero initialized.
+         *
+         *  The default is SkCodec::kNo_ZeroInitialized.
+         */
+        SkCodec::ZeroInitialized fZeroInitialized;
+
+        /**
+         *  If not NULL, represents a subset of the original image to decode.
+         *
+         *  Must be within the bounds returned by getInfo().
+         *
+         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP, the top and left
+         *  values must be even.
+         *
+         *  The default is NULL, meaning a decode of the entire image.
+         */
+        SkIRect* fSubset;
+
+        /**
+         *  The client may provide an integer downscale factor for the decode.
+         *  The codec may implement this downscaling by sampling or another
+         *  method if it is more efficient.
+         *
+         *  The default is 1, representing no downscaling.
+         */
+        int fSampleSize;
+    };
+
+    /**
+     *  Decode into the given pixels, a block of memory of size at
+     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
+     *  bytesPerPixel)
+     *
+     *  Repeated calls to this function should give the same results,
+     *  allowing the PixelRef to be immutable.
+     *
+     *  @param info A description of the format (config, size)
+     *         expected by the caller.  This can simply be identical
+     *         to the info returned by getInfo().
+     *
+     *         This contract also allows the caller to specify
+     *         different output-configs, which the implementation can
+     *         decide to support or not.
+     *
+     *         A size that does not match getInfo() implies a request
+     *         to scale or subset. If the codec cannot perform this
+     *         scaling or subsetting, it will return an error code.
+     *
+     *  The AndroidOptions object is also used to specify any requested scaling or subsetting
+     *  using options->fSampleSize and options->fSubset. If NULL, the defaults (as specified above
+     *  for AndroidOptions) are used.
+     *
+     *  @return Result kSuccess, or another value explaining the type of failure.
+     */
+    // FIXME: It's a bit redundant to name this getAndroidPixels() when this class is already
+    //        called SkAndroidCodec.  On the other hand, it's may be a bit confusing to call
+    //        this getPixels() when it is a slightly different API than SkCodec's getPixels().
+    //        Maybe this should be decode() or decodeSubset()?
+    SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+            const AndroidOptions* options);
+
+    /**
+     *  Simplified version of getAndroidPixels() where we supply the default AndroidOptions as
+     *  specified above for AndroidOptions. It will not perform any scaling or subsetting.
+     */
+    SkCodec::Result getAndroidPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
+
+    SkCodec::Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+        return this->getAndroidPixels(info, pixels, rowBytes);
+    }
+
+    SkCodec* codec() const { return fCodec.get(); }
+
+protected:
+    SkAndroidCodec(SkCodec*, ExifOrientationBehavior = ExifOrientationBehavior::kIgnore);
+
+    virtual SkISize onGetSampledDimensions(int sampleSize) const = 0;
+
+    virtual bool onGetSupportedSubset(SkIRect* desiredSubset) const = 0;
+
+    virtual SkCodec::Result onGetAndroidPixels(const SkImageInfo& info, void* pixels,
+            size_t rowBytes, const AndroidOptions& options) = 0;
+
+private:
+    const SkImageInfo               fInfo;
+    const ExifOrientationBehavior   fOrientationBehavior;
+    std::unique_ptr<SkCodec>        fCodec;
+};
+#endif // SkAndroidCodec_DEFINED

+ 921 - 0
skia/include/codec/SkCodec.h

@@ -0,0 +1,921 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCodec_DEFINED
+#define SkCodec_DEFINED
+
+#include "../private/SkNoncopyable.h"
+#include "../private/SkTemplates.h"
+#include "../private/SkEncodedInfo.h"
+#include "SkCodecAnimation.h"
+#include "SkColor.h"
+#include "SkEncodedImageFormat.h"
+#include "SkEncodedOrigin.h"
+#include "SkImageInfo.h"
+#include "SkPixmap.h"
+#include "SkSize.h"
+#include "SkStream.h"
+#include "SkTypes.h"
+#include "SkYUVASizeInfo.h"
+
+#include <vector>
+
+class SkColorSpace;
+class SkData;
+class SkFrameHolder;
+class SkPngChunkReader;
+class SkSampler;
+
+namespace DM {
+class CodecSrc;
+class ColorCodecSrc;
+}
+
+/**
+ *  Abstraction layer directly on top of an image codec.
+ */
+class SK_API SkCodec : SkNoncopyable {
+public:
+    /**
+     *  Minimum number of bytes that must be buffered in SkStream input.
+     *
+     *  An SkStream passed to NewFromStream must be able to use this many
+     *  bytes to determine the image type. Then the same SkStream must be
+     *  passed to the correct decoder to read from the beginning.
+     *
+     *  This can be accomplished by implementing peek() to support peeking
+     *  this many bytes, or by implementing rewind() to be able to rewind()
+     *  after reading this many bytes.
+     */
+    static constexpr size_t MinBufferedBytesNeeded() { return 32; }
+
+    /**
+     *  Error codes for various SkCodec methods.
+     */
+    enum Result {
+        /**
+         *  General return value for success.
+         */
+        kSuccess,
+        /**
+         *  The input is incomplete. A partial image was generated.
+         */
+        kIncompleteInput,
+        /**
+         *  Like kIncompleteInput, except the input had an error.
+         *
+         *  If returned from an incremental decode, decoding cannot continue,
+         *  even with more data.
+         */
+        kErrorInInput,
+        /**
+         *  The generator cannot convert to match the request, ignoring
+         *  dimensions.
+         */
+        kInvalidConversion,
+        /**
+         *  The generator cannot scale to requested size.
+         */
+        kInvalidScale,
+        /**
+         *  Parameters (besides info) are invalid. e.g. NULL pixels, rowBytes
+         *  too small, etc.
+         */
+        kInvalidParameters,
+        /**
+         *  The input did not contain a valid image.
+         */
+        kInvalidInput,
+        /**
+         *  Fulfilling this request requires rewinding the input, which is not
+         *  supported for this input.
+         */
+        kCouldNotRewind,
+        /**
+         *  An internal error, such as OOM.
+         */
+        kInternalError,
+        /**
+         *  This method is not implemented by this codec.
+         *  FIXME: Perhaps this should be kUnsupported?
+         */
+        kUnimplemented,
+    };
+
+    /**
+     *  Readable string representing the error code.
+     */
+    static const char* ResultToString(Result);
+
+    /**
+     *  If this stream represents an encoded image that we know how to decode,
+     *  return an SkCodec that can decode it. Otherwise return NULL.
+     *
+     *  As stated above, this call must be able to peek or read
+     *  MinBufferedBytesNeeded to determine the correct format, and then start
+     *  reading from the beginning. First it will attempt to peek, and it
+     *  assumes that if less than MinBufferedBytesNeeded bytes (but more than
+     *  zero) are returned, this is because the stream is shorter than this,
+     *  so falling back to reading would not provide more data. If peek()
+     *  returns zero bytes, this call will instead attempt to read(). This
+     *  will require that the stream can be rewind()ed.
+     *
+     *  If Result is not NULL, it will be set to either kSuccess if an SkCodec
+     *  is returned or a reason for the failure if NULL is returned.
+     *
+     *  If SkPngChunkReader is not NULL, take a ref and pass it to libpng if
+     *  the image is a png.
+     *
+     *  If the SkPngChunkReader is not NULL then:
+     *      If the image is not a PNG, the SkPngChunkReader will be ignored.
+     *      If the image is a PNG, the SkPngChunkReader will be reffed.
+     *      If the PNG has unknown chunks, the SkPngChunkReader will be used
+     *      to handle these chunks.  SkPngChunkReader will be called to read
+     *      any unknown chunk at any point during the creation of the codec
+     *      or the decode.  Note that if SkPngChunkReader fails to read a
+     *      chunk, this could result in a failure to create the codec or a
+     *      failure to decode the image.
+     *      If the PNG does not contain unknown chunks, the SkPngChunkReader
+     *      will not be used or modified.
+     *
+     *  If NULL is returned, the stream is deleted immediately. Otherwise, the
+     *  SkCodec takes ownership of it, and will delete it when done with it.
+     */
+    static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result* = nullptr,
+                                                   SkPngChunkReader* = nullptr);
+
+    /**
+     *  If this data represents an encoded image that we know how to decode,
+     *  return an SkCodec that can decode it. Otherwise return NULL.
+     *
+     *  If the SkPngChunkReader is not NULL then:
+     *      If the image is not a PNG, the SkPngChunkReader will be ignored.
+     *      If the image is a PNG, the SkPngChunkReader will be reffed.
+     *      If the PNG has unknown chunks, the SkPngChunkReader will be used
+     *      to handle these chunks.  SkPngChunkReader will be called to read
+     *      any unknown chunk at any point during the creation of the codec
+     *      or the decode.  Note that if SkPngChunkReader fails to read a
+     *      chunk, this could result in a failure to create the codec or a
+     *      failure to decode the image.
+     *      If the PNG does not contain unknown chunks, the SkPngChunkReader
+     *      will not be used or modified.
+     */
+    static std::unique_ptr<SkCodec> MakeFromData(sk_sp<SkData>, SkPngChunkReader* = nullptr);
+
+    virtual ~SkCodec();
+
+    /**
+     *  Return a reasonable SkImageInfo to decode into.
+     */
+    SkImageInfo getInfo() const { return fEncodedInfo.makeImageInfo(); }
+
+    SkISize dimensions() const { return {fEncodedInfo.width(), fEncodedInfo.height()}; }
+    SkIRect bounds() const {
+        return SkIRect::MakeWH(fEncodedInfo.width(), fEncodedInfo.height());
+    }
+
+    /**
+     *  Returns the image orientation stored in the EXIF data.
+     *  If there is no EXIF data, or if we cannot read the EXIF data, returns kTopLeft.
+     */
+    SkEncodedOrigin getOrigin() const { return fOrigin; }
+
+    /**
+     *  Return a size that approximately supports the desired scale factor.
+     *  The codec may not be able to scale efficiently to the exact scale
+     *  factor requested, so return a size that approximates that scale.
+     *  The returned value is the codec's suggestion for the closest valid
+     *  scale that it can natively support
+     */
+    SkISize getScaledDimensions(float desiredScale) const {
+        // Negative and zero scales are errors.
+        SkASSERT(desiredScale > 0.0f);
+        if (desiredScale <= 0.0f) {
+            return SkISize::Make(0, 0);
+        }
+
+        // Upscaling is not supported. Return the original size if the client
+        // requests an upscale.
+        if (desiredScale >= 1.0f) {
+            return this->dimensions();
+        }
+        return this->onGetScaledDimensions(desiredScale);
+    }
+
+    /**
+     *  Return (via desiredSubset) a subset which can decoded from this codec,
+     *  or false if this codec cannot decode subsets or anything similar to
+     *  desiredSubset.
+     *
+     *  @param desiredSubset In/out parameter. As input, a desired subset of
+     *      the original bounds (as specified by getInfo). If true is returned,
+     *      desiredSubset may have been modified to a subset which is
+     *      supported. Although a particular change may have been made to
+     *      desiredSubset to create something supported, it is possible other
+     *      changes could result in a valid subset.
+     *      If false is returned, desiredSubset's value is undefined.
+     *  @return true if this codec supports decoding desiredSubset (as
+     *      returned, potentially modified)
+     */
+    bool getValidSubset(SkIRect* desiredSubset) const {
+        return this->onGetValidSubset(desiredSubset);
+    }
+
+    /**
+     *  Format of the encoded data.
+     */
+    SkEncodedImageFormat getEncodedFormat() const { return this->onGetEncodedFormat(); }
+
+    /**
+     *  Whether or not the memory passed to getPixels is zero initialized.
+     */
+    enum ZeroInitialized {
+        /**
+         *  The memory passed to getPixels is zero initialized. The SkCodec
+         *  may take advantage of this by skipping writing zeroes.
+         */
+        kYes_ZeroInitialized,
+        /**
+         *  The memory passed to getPixels has not been initialized to zero,
+         *  so the SkCodec must write all zeroes to memory.
+         *
+         *  This is the default. It will be used if no Options struct is used.
+         */
+        kNo_ZeroInitialized,
+    };
+
+    /**
+     *  Additional options to pass to getPixels.
+     */
+    struct Options {
+        Options()
+            : fZeroInitialized(kNo_ZeroInitialized)
+            , fSubset(nullptr)
+            , fFrameIndex(0)
+            , fPriorFrame(kNoFrame)
+        {}
+
+        ZeroInitialized            fZeroInitialized;
+        /**
+         *  If not NULL, represents a subset of the original image to decode.
+         *  Must be within the bounds returned by getInfo().
+         *  If the EncodedFormat is SkEncodedImageFormat::kWEBP (the only one which
+         *  currently supports subsets), the top and left values must be even.
+         *
+         *  In getPixels and incremental decode, we will attempt to decode the
+         *  exact rectangular subset specified by fSubset.
+         *
+         *  In a scanline decode, it does not make sense to specify a subset
+         *  top or subset height, since the client already controls which rows
+         *  to get and which rows to skip.  During scanline decodes, we will
+         *  require that the subset top be zero and the subset height be equal
+         *  to the full height.  We will, however, use the values of
+         *  subset left and subset width to decode partial scanlines on calls
+         *  to getScanlines().
+         */
+        const SkIRect*             fSubset;
+
+        /**
+         *  The frame to decode.
+         *
+         *  Only meaningful for multi-frame images.
+         */
+        int                        fFrameIndex;
+
+        /**
+         *  If not kNoFrame, the dst already contains the prior frame at this index.
+         *
+         *  Only meaningful for multi-frame images.
+         *
+         *  If fFrameIndex needs to be blended with a prior frame (as reported by
+         *  getFrameInfo[fFrameIndex].fRequiredFrame), the client can set this to
+         *  any non-kRestorePrevious frame in [fRequiredFrame, fFrameIndex) to
+         *  indicate that that frame is already in the dst. Options.fZeroInitialized
+         *  is ignored in this case.
+         *
+         *  If set to kNoFrame, the codec will decode any necessary required frame(s) first.
+         */
+        int                        fPriorFrame;
+    };
+
+    /**
+     *  Decode into the given pixels, a block of memory of size at
+     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
+     *  bytesPerPixel)
+     *
+     *  Repeated calls to this function should give the same results,
+     *  allowing the PixelRef to be immutable.
+     *
+     *  @param info A description of the format (config, size)
+     *         expected by the caller.  This can simply be identical
+     *         to the info returned by getInfo().
+     *
+     *         This contract also allows the caller to specify
+     *         different output-configs, which the implementation can
+     *         decide to support or not.
+     *
+     *         A size that does not match getInfo() implies a request
+     *         to scale. If the generator cannot perform this scale,
+     *         it will return kInvalidScale.
+     *
+     *         If the info contains a non-null SkColorSpace, the codec
+     *         will perform the appropriate color space transformation.
+     *         If the caller passes in the same color space that was
+     *         reported by the codec, the color space transformation is
+     *         a no-op.
+     *
+     *  If a scanline decode is in progress, scanline mode will end, requiring the client to call
+     *  startScanlineDecode() in order to return to decoding scanlines.
+     *
+     *  @return Result kSuccess, or another value explaining the type of failure.
+     */
+    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const Options*);
+
+    /**
+     *  Simplified version of getPixels() that uses the default Options.
+     */
+    Result getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+        return this->getPixels(info, pixels, rowBytes, nullptr);
+    }
+
+    Result getPixels(const SkPixmap& pm, const Options* opts = nullptr) {
+        return this->getPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), opts);
+    }
+
+    /**
+     *  If decoding to YUV is supported, this returns true.  Otherwise, this
+     *  returns false and does not modify any of the parameters.
+     *
+     *  @param sizeInfo   Output parameter indicating the sizes and required
+     *                    allocation widths of the Y, U, V, and A planes. Given current codec
+     *                    limitations the size of the A plane will always be 0 and the Y, U, V
+     *                    channels will always be planar.
+     *  @param colorSpace Output parameter.  If non-NULL this is set to kJPEG,
+     *                    otherwise this is ignored.
+     */
+    bool queryYUV8(SkYUVASizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
+        if (nullptr == sizeInfo) {
+            return false;
+        }
+
+        bool result = this->onQueryYUV8(sizeInfo, colorSpace);
+        if (result) {
+            for (int i = 0; i <= 2; ++i) {
+                SkASSERT(sizeInfo->fSizes[i].fWidth > 0 && sizeInfo->fSizes[i].fHeight > 0 &&
+                         sizeInfo->fWidthBytes[i] > 0);
+            }
+            SkASSERT(!sizeInfo->fSizes[3].fWidth &&
+                     !sizeInfo->fSizes[3].fHeight &&
+                     !sizeInfo->fWidthBytes[3]);
+        }
+        return result;
+    }
+
+    /**
+     *  Returns kSuccess, or another value explaining the type of failure.
+     *  This always attempts to perform a full decode.  If the client only
+     *  wants size, it should call queryYUV8().
+     *
+     *  @param sizeInfo   Needs to exactly match the values returned by the
+     *                    query, except the WidthBytes may be larger than the
+     *                    recommendation (but not smaller).
+     *  @param planes     Memory for each of the Y, U, and V planes.
+     */
+    Result getYUV8Planes(const SkYUVASizeInfo& sizeInfo, void* planes[SkYUVASizeInfo::kMaxCount]) {
+        if (!planes || !planes[0] || !planes[1] || !planes[2]) {
+            return kInvalidInput;
+        }
+        SkASSERT(!planes[3]); // TODO: is this a fair assumption?
+
+        if (!this->rewindIfNeeded()) {
+            return kCouldNotRewind;
+        }
+
+        return this->onGetYUV8Planes(sizeInfo, planes);
+    }
+
+    /**
+     *  Prepare for an incremental decode with the specified options.
+     *
+     *  This may require a rewind.
+     *
+     *  @param dstInfo Info of the destination. If the dimensions do not match
+     *      those of getInfo, this implies a scale.
+     *  @param dst Memory to write to. Needs to be large enough to hold the subset,
+     *      if present, or the full image as described in dstInfo.
+     *  @param options Contains decoding options, including if memory is zero
+     *      initialized and whether to decode a subset.
+     *  @return Enum representing success or reason for failure.
+     */
+    Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+            const Options*);
+
+    Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
+        return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr);
+    }
+
+    /**
+     *  Start/continue the incremental decode.
+     *
+     *  Not valid to call before calling startIncrementalDecode().
+     *
+     *  After the first call, should only be called again if more data has been
+     *  provided to the source SkStream.
+     *
+     *  Unlike getPixels and getScanlines, this does not do any filling. This is
+     *  left up to the caller, since they may be skipping lines or continuing the
+     *  decode later. In the latter case, they may choose to initialize all lines
+     *  first, or only initialize the remaining lines after the first call.
+     *
+     *  @param rowsDecoded Optional output variable returning the total number of
+     *      lines initialized. Only meaningful if this method returns kIncompleteInput.
+     *      Otherwise the implementation may not set it.
+     *      Note that some implementations may have initialized this many rows, but
+     *      not necessarily finished those rows (e.g. interlaced PNG). This may be
+     *      useful for determining what rows the client needs to initialize.
+     *  @return kSuccess if all lines requested in startIncrementalDecode have
+     *      been completely decoded. kIncompleteInput otherwise.
+     */
+    Result incrementalDecode(int* rowsDecoded = nullptr) {
+        if (!fStartedIncrementalDecode) {
+            return kInvalidParameters;
+        }
+        return this->onIncrementalDecode(rowsDecoded);
+    }
+
+    /**
+     * The remaining functions revolve around decoding scanlines.
+     */
+
+    /**
+     *  Prepare for a scanline decode with the specified options.
+     *
+     *  After this call, this class will be ready to decode the first scanline.
+     *
+     *  This must be called in order to call getScanlines or skipScanlines.
+     *
+     *  This may require rewinding the stream.
+     *
+     *  Not all SkCodecs support this.
+     *
+     *  @param dstInfo Info of the destination. If the dimensions do not match
+     *      those of getInfo, this implies a scale.
+     *  @param options Contains decoding options, including if memory is zero
+     *      initialized.
+     *  @return Enum representing success or reason for failure.
+     */
+    Result startScanlineDecode(const SkImageInfo& dstInfo, const Options* options);
+
+    /**
+     *  Simplified version of startScanlineDecode() that uses the default Options.
+     */
+    Result startScanlineDecode(const SkImageInfo& dstInfo) {
+        return this->startScanlineDecode(dstInfo, nullptr);
+    }
+
+    /**
+     *  Write the next countLines scanlines into dst.
+     *
+     *  Not valid to call before calling startScanlineDecode().
+     *
+     *  @param dst Must be non-null, and large enough to hold countLines
+     *      scanlines of size rowBytes.
+     *  @param countLines Number of lines to write.
+     *  @param rowBytes Number of bytes per row. Must be large enough to hold
+     *      a scanline based on the SkImageInfo used to create this object.
+     *  @return the number of lines successfully decoded.  If this value is
+     *      less than countLines, this will fill the remaining lines with a
+     *      default value.
+     */
+    int getScanlines(void* dst, int countLines, size_t rowBytes);
+
+    /**
+     *  Skip count scanlines.
+     *
+     *  Not valid to call before calling startScanlineDecode().
+     *
+     *  The default version just calls onGetScanlines and discards the dst.
+     *  NOTE: If skipped lines are the only lines with alpha, this default
+     *  will make reallyHasAlpha return true, when it could have returned
+     *  false.
+     *
+     *  @return true if the scanlines were successfully skipped
+     *          false on failure, possible reasons for failure include:
+     *              An incomplete input image stream.
+     *              Calling this function before calling startScanlineDecode().
+     *              If countLines is less than zero or so large that it moves
+     *                  the current scanline past the end of the image.
+     */
+    bool skipScanlines(int countLines);
+
+    /**
+     *  The order in which rows are output from the scanline decoder is not the
+     *  same for all variations of all image types.  This explains the possible
+     *  output row orderings.
+     */
+    enum SkScanlineOrder {
+        /*
+         * By far the most common, this indicates that the image can be decoded
+         * reliably using the scanline decoder, and that rows will be output in
+         * the logical order.
+         */
+        kTopDown_SkScanlineOrder,
+
+        /*
+         * This indicates that the scanline decoder reliably outputs rows, but
+         * they will be returned in reverse order.  If the scanline format is
+         * kBottomUp, the nextScanline() API can be used to determine the actual
+         * y-coordinate of the next output row, but the client is not forced
+         * to take advantage of this, given that it's not too tough to keep
+         * track independently.
+         *
+         * For full image decodes, it is safe to get all of the scanlines at
+         * once, since the decoder will handle inverting the rows as it
+         * decodes.
+         *
+         * For subset decodes and sampling, it is simplest to get and skip
+         * scanlines one at a time, using the nextScanline() API.  It is
+         * possible to ask for larger chunks at a time, but this should be used
+         * with caution.  As with full image decodes, the decoder will handle
+         * inverting the requested rows, but rows will still be delivered
+         * starting from the bottom of the image.
+         *
+         * Upside down bmps are an example.
+         */
+        kBottomUp_SkScanlineOrder,
+    };
+
+    /**
+     *  An enum representing the order in which scanlines will be returned by
+     *  the scanline decoder.
+     *
+     *  This is undefined before startScanlineDecode() is called.
+     */
+    SkScanlineOrder getScanlineOrder() const { return this->onGetScanlineOrder(); }
+
+    /**
+     *  Returns the y-coordinate of the next row to be returned by the scanline
+     *  decoder.
+     *
+     *  This will equal fCurrScanline, except in the case of strangely
+     *  encoded image types (bottom-up bmps).
+     *
+     *  Results are undefined when not in scanline decoding mode.
+     */
+    int nextScanline() const { return this->outputScanline(fCurrScanline); }
+
+    /**
+     *  Returns the output y-coordinate of the row that corresponds to an input
+     *  y-coordinate.  The input y-coordinate represents where the scanline
+     *  is located in the encoded data.
+     *
+     *  This will equal inputScanline, except in the case of strangely
+     *  encoded image types (bottom-up bmps, interlaced gifs).
+     */
+    int outputScanline(int inputScanline) const;
+
+    /**
+     *  Return the number of frames in the image.
+     *
+     *  May require reading through the stream.
+     */
+    int getFrameCount() {
+        return this->onGetFrameCount();
+    }
+
+    // Sentinel value used when a frame index implies "no frame":
+    // - FrameInfo::fRequiredFrame set to this value means the frame
+    //   is independent.
+    // - Options::fPriorFrame set to this value means no (relevant) prior frame
+    //   is residing in dst's memory.
+    static constexpr int kNoFrame = -1;
+
+    // This transitional definition was added in August 2018, and will eventually be removed.
+#ifdef SK_LEGACY_SKCODEC_NONE_ENUM
+    static constexpr int kNone = kNoFrame;
+#endif
+
+    /**
+     *  Information about individual frames in a multi-framed image.
+     */
+    struct FrameInfo {
+        /**
+         *  The frame that this frame needs to be blended with, or
+         *  kNoFrame if this frame is independent.
+         *
+         *  Note that this is the *earliest* frame that can be used
+         *  for blending. Any frame from [fRequiredFrame, i) can be
+         *  used, unless its fDisposalMethod is kRestorePrevious.
+         */
+        int fRequiredFrame;
+
+        /**
+         *  Number of milliseconds to show this frame.
+         */
+        int fDuration;
+
+        /**
+         *  Whether the end marker for this frame is contained in the stream.
+         *
+         *  Note: this does not guarantee that an attempt to decode will be complete.
+         *  There could be an error in the stream.
+         */
+        bool fFullyReceived;
+
+        /**
+         *  This is conservative; it will still return non-opaque if e.g. a
+         *  color index-based frame has a color with alpha but does not use it.
+         */
+        SkAlphaType fAlphaType;
+
+        /**
+         *  How this frame should be modified before decoding the next one.
+         */
+        SkCodecAnimation::DisposalMethod fDisposalMethod;
+    };
+
+    /**
+     *  Return info about a single frame.
+     *
+     *  Only supported by multi-frame images. Does not read through the stream,
+     *  so it should be called after getFrameCount() to parse any frames that
+     *  have not already been parsed.
+     */
+    bool getFrameInfo(int index, FrameInfo* info) const {
+        if (index < 0) {
+            return false;
+        }
+        return this->onGetFrameInfo(index, info);
+    }
+
+    /**
+     *  Return info about all the frames in the image.
+     *
+     *  May require reading through the stream to determine info about the
+     *  frames (including the count).
+     *
+     *  As such, future decoding calls may require a rewind.
+     *
+     *  For still (non-animated) image codecs, this will return an empty vector.
+     */
+    std::vector<FrameInfo> getFrameInfo();
+
+    static constexpr int kRepetitionCountInfinite = -1;
+
+    /**
+     *  Return the number of times to repeat, if this image is animated. This number does not
+     *  include the first play through of each frame. For example, a repetition count of 4 means
+     *  that each frame is played 5 times and then the animation stops.
+     *
+     *  It can return kRepetitionCountInfinite, a negative number, meaning that the animation
+     *  should loop forever.
+     *
+     *  May require reading the stream to find the repetition count.
+     *
+     *  As such, future decoding calls may require a rewind.
+     *
+     *  For still (non-animated) image codecs, this will return 0.
+     */
+    int getRepetitionCount() {
+        return this->onGetRepetitionCount();
+    }
+
+protected:
+    const SkEncodedInfo& getEncodedInfo() const { return fEncodedInfo; }
+
+    using XformFormat = skcms_PixelFormat;
+
+    SkCodec(SkEncodedInfo&&,
+            XformFormat srcFormat,
+            std::unique_ptr<SkStream>,
+            SkEncodedOrigin = kTopLeft_SkEncodedOrigin);
+
+    virtual SkISize onGetScaledDimensions(float /*desiredScale*/) const {
+        // By default, scaling is not supported.
+        return this->dimensions();
+    }
+
+    // FIXME: What to do about subsets??
+    /**
+     *  Subclasses should override if they support dimensions other than the
+     *  srcInfo's.
+     */
+    virtual bool onDimensionsSupported(const SkISize&) {
+        return false;
+    }
+
+    virtual SkEncodedImageFormat onGetEncodedFormat() const = 0;
+
+    /**
+     * @param rowsDecoded When the encoded image stream is incomplete, this function
+     *                    will return kIncompleteInput and rowsDecoded will be set to
+     *                    the number of scanlines that were successfully decoded.
+     *                    This will allow getPixels() to fill the uninitialized memory.
+     */
+    virtual Result onGetPixels(const SkImageInfo& info,
+                               void* pixels, size_t rowBytes, const Options&,
+                               int* rowsDecoded) = 0;
+
+    virtual bool onQueryYUV8(SkYUVASizeInfo*, SkYUVColorSpace*) const {
+        return false;
+    }
+
+    virtual Result onGetYUV8Planes(const SkYUVASizeInfo&,
+                                   void*[SkYUVASizeInfo::kMaxCount] /*planes*/) {
+        return kUnimplemented;
+    }
+
+    virtual bool onGetValidSubset(SkIRect* /*desiredSubset*/) const {
+        // By default, subsets are not supported.
+        return false;
+    }
+
+    /**
+     *  If the stream was previously read, attempt to rewind.
+     *
+     *  If the stream needed to be rewound, call onRewind.
+     *  @returns true if the codec is at the right position and can be used.
+     *      false if there was a failure to rewind.
+     *
+     *  This is called by getPixels(), getYUV8Planes(), startIncrementalDecode() and
+     *  startScanlineDecode(). Subclasses may call if they need to rewind at another time.
+     */
+    bool SK_WARN_UNUSED_RESULT rewindIfNeeded();
+
+    /**
+     *  Called by rewindIfNeeded, if the stream needed to be rewound.
+     *
+     *  Subclasses should do any set up needed after a rewind.
+     */
+    virtual bool onRewind() {
+        return true;
+    }
+
+    /**
+     * Get method for the input stream
+     */
+    SkStream* stream() {
+        return fStream.get();
+    }
+
+    /**
+     *  The remaining functions revolve around decoding scanlines.
+     */
+
+    /**
+     *  Most images types will be kTopDown and will not need to override this function.
+     */
+    virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
+
+    const SkImageInfo& dstInfo() const { return fDstInfo; }
+
+    const Options& options() const { return fOptions; }
+
+    /**
+     *  Returns the number of scanlines that have been decoded so far.
+     *  This is unaffected by the SkScanlineOrder.
+     *
+     *  Returns -1 if we have not started a scanline decode.
+     */
+    int currScanline() const { return fCurrScanline; }
+
+    virtual int onOutputScanline(int inputScanline) const;
+
+    /**
+     *  Return whether we can convert to dst.
+     *
+     *  Will be called for the appropriate frame, prior to initializing the colorXform.
+     */
+    virtual bool conversionSupported(const SkImageInfo& dst, bool srcIsOpaque,
+                                     bool needsColorXform);
+
+    // Some classes never need a colorXform e.g.
+    // - ICO uses its embedded codec's colorXform
+    // - WBMP is just Black/White
+    virtual bool usesColorXform() const { return true; }
+    void applyColorXform(void* dst, const void* src, int count) const;
+
+    bool colorXform() const { return fXformTime != kNo_XformTime; }
+    bool xformOnDecode() const { return fXformTime == kDecodeRow_XformTime; }
+
+    virtual int onGetFrameCount() {
+        return 1;
+    }
+
+    virtual bool onGetFrameInfo(int, FrameInfo*) const {
+        return false;
+    }
+
+    virtual int onGetRepetitionCount() {
+        return 0;
+    }
+
+private:
+    const SkEncodedInfo                fEncodedInfo;
+    const XformFormat                  fSrcXformFormat;
+    std::unique_ptr<SkStream>          fStream;
+    bool                               fNeedsRewind;
+    const SkEncodedOrigin              fOrigin;
+
+    SkImageInfo                        fDstInfo;
+    Options                            fOptions;
+
+    enum XformTime {
+        kNo_XformTime,
+        kPalette_XformTime,
+        kDecodeRow_XformTime,
+    };
+    XformTime                          fXformTime;
+    XformFormat                        fDstXformFormat; // Based on fDstInfo.
+    skcms_ICCProfile                   fDstProfile;
+    skcms_AlphaFormat                  fDstXformAlphaFormat;
+
+    // Only meaningful during scanline decodes.
+    int                                fCurrScanline;
+
+    bool                               fStartedIncrementalDecode;
+
+    bool initializeColorXform(const SkImageInfo& dstInfo, SkEncodedInfo::Alpha, bool srcIsOpaque);
+
+    /**
+     *  Return whether these dimensions are supported as a scale.
+     *
+     *  The codec may choose to cache the information about scale and subset.
+     *  Either way, the same information will be passed to onGetPixels/onStart
+     *  on success.
+     *
+     *  This must return true for a size returned from getScaledDimensions.
+     */
+    bool dimensionsSupported(const SkISize& dim) {
+        return dim == this->dimensions() || this->onDimensionsSupported(dim);
+    }
+
+    /**
+     *  For multi-framed images, return the object with information about the frames.
+     */
+    virtual const SkFrameHolder* getFrameHolder() const {
+        return nullptr;
+    }
+
+    /**
+     *  Check for a valid Options.fFrameIndex, and decode prior frames if necessary.
+     */
+    Result handleFrameIndex(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&);
+
+    // Methods for scanline decoding.
+    virtual Result onStartScanlineDecode(const SkImageInfo& /*dstInfo*/,
+            const Options& /*options*/) {
+        return kUnimplemented;
+    }
+
+    virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
+            const Options&) {
+        return kUnimplemented;
+    }
+
+    virtual Result onIncrementalDecode(int*) {
+        return kUnimplemented;
+    }
+
+
+    virtual bool onSkipScanlines(int /*countLines*/) { return false; }
+
+    virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
+
+    /**
+     * On an incomplete decode, getPixels() and getScanlines() will call this function
+     * to fill any uinitialized memory.
+     *
+     * @param dstInfo        Contains the destination color type
+     *                       Contains the destination alpha type
+     *                       Contains the destination width
+     *                       The height stored in this info is unused
+     * @param dst            Pointer to the start of destination pixel memory
+     * @param rowBytes       Stride length in destination pixel memory
+     * @param zeroInit       Indicates if memory is zero initialized
+     * @param linesRequested Number of lines that the client requested
+     * @param linesDecoded   Number of lines that were successfully decoded
+     */
+    void fillIncompleteImage(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+            ZeroInitialized zeroInit, int linesRequested, int linesDecoded);
+
+    /**
+     *  Return an object which will allow forcing scanline decodes to sample in X.
+     *
+     *  May create a sampler, if one is not currently being used. Otherwise, does
+     *  not affect ownership.
+     *
+     *  Only valid during scanline decoding or incremental decoding.
+     */
+    virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
+
+    friend class DM::CodecSrc;  // for fillIncompleteImage
+    friend class SkSampledCodec;
+    friend class SkIcoCodec;
+    friend class SkAndroidCodec; // for fEncodedInfo
+};
+#endif // SkCodec_DEFINED

+ 43 - 0
skia/include/codec/SkCodecAnimation.h

@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCodecAnimation_DEFINED
+#define SkCodecAnimation_DEFINED
+
+namespace SkCodecAnimation {
+    /**
+     *  This specifies how the next frame is based on this frame.
+     *
+     *  Names are based on the GIF 89a spec.
+     *
+     *  The numbers correspond to values in a GIF.
+     */
+    enum class DisposalMethod {
+        /**
+         *  The next frame should be drawn on top of this one.
+         *
+         *  In a GIF, a value of 0 (not specified) is also treated as Keep.
+         */
+        kKeep               = 1,
+
+        /**
+         *  Similar to Keep, except the area inside this frame's rectangle
+         *  should be cleared to the BackGround color (transparent) before
+         *  drawing the next frame.
+         */
+        kRestoreBGColor     = 2,
+
+        /**
+         *  The next frame should be drawn on top of the previous frame - i.e.
+         *  disregarding this one.
+         *
+         *  In a GIF, a value of 4 is also treated as RestorePrevious.
+         */
+        kRestorePrevious    = 3,
+    };
+};
+#endif // SkCodecAnimation_DEFINED

+ 23 - 0
skia/include/codec/SkEncodedOrigin.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEncodedOrigin_DEFINED
+#define SkEncodedOrigin_DEFINED
+// These values match the orientation www.exif.org/Exif2-2.PDF.
+enum SkEncodedOrigin {
+    kTopLeft_SkEncodedOrigin     = 1, // Default
+    kTopRight_SkEncodedOrigin    = 2, // Reflected across y-axis
+    kBottomRight_SkEncodedOrigin = 3, // Rotated 180
+    kBottomLeft_SkEncodedOrigin  = 4, // Reflected across x-axis
+    kLeftTop_SkEncodedOrigin     = 5, // Reflected across x-axis, Rotated 90 CCW
+    kRightTop_SkEncodedOrigin    = 6, // Rotated 90 CW
+    kRightBottom_SkEncodedOrigin = 7, // Reflected across x-axis, Rotated 90 CW
+    kLeftBottom_SkEncodedOrigin  = 8, // Rotated 90 CCW
+    kDefault_SkEncodedOrigin     = kTopLeft_SkEncodedOrigin,
+    kLast_SkEncodedOrigin        = kLeftBottom_SkEncodedOrigin,
+};
+#endif // SkEncodedOrigin_DEFINED

+ 130 - 0
skia/include/config/SkUserConfig.h

@@ -0,0 +1,130 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkUserConfig_DEFINED
+#define SkUserConfig_DEFINED
+
+/*  SkTypes.h, the root of the public header files, does the following trick:
+
+    #include "SkPreConfig.h"
+    #include "SkUserConfig.h"
+    #include "SkPostConfig.h"
+
+    SkPreConfig.h runs first, and it is responsible for initializing certain
+    skia defines.
+
+    SkPostConfig.h runs last, and its job is to just check that the final
+    defines are consistent (i.e. that we don't have mutually conflicting
+    defines).
+
+    SkUserConfig.h (this file) runs in the middle. It gets to change or augment
+    the list of flags initially set in preconfig, and then postconfig checks
+    that everything still makes sense.
+
+    Below are optional defines that add, subtract, or change default behavior
+    in Skia. Your port can locally edit this file to enable/disable flags as
+    you choose, or these can be delared on your command line (i.e. -Dfoo).
+
+    By default, this include file will always default to having all of the flags
+    commented out, so including it will have no effect.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*  Skia has lots of debug-only code. Often this is just null checks or other
+    parameter checking, but sometimes it can be quite intrusive (e.g. check that
+    each 32bit pixel is in premultiplied form). This code can be very useful
+    during development, but will slow things down in a shipping product.
+
+    By default, these mutually exclusive flags are defined in SkPreConfig.h,
+    based on the presence or absence of NDEBUG, but that decision can be changed
+    here.
+ */
+//#define SK_DEBUG
+//#define SK_RELEASE
+
+/*  Skia has certain debug-only code that is extremely intensive even for debug
+    builds.  This code is useful for diagnosing specific issues, but is not
+    generally applicable, therefore it must be explicitly enabled to avoid
+    the performance impact. By default these flags are undefined, but can be
+    enabled by uncommenting them below.
+ */
+//#define SK_DEBUG_GLYPH_CACHE
+//#define SK_DEBUG_PATH
+
+/*  preconfig will have attempted to determine the endianness of the system,
+    but you can change these mutually exclusive flags here.
+ */
+//#define SK_CPU_BENDIAN
+//#define SK_CPU_LENDIAN
+
+/*  Most compilers use the same bit endianness for bit flags in a byte as the
+    system byte endianness, and this is the default. If for some reason this
+    needs to be overridden, specify which of the mutually exclusive flags to
+    use. For example, some atom processors in certain configurations have big
+    endian byte order but little endian bit orders.
+*/
+//#define SK_UINT8_BITFIELD_BENDIAN
+//#define SK_UINT8_BITFIELD_LENDIAN
+
+
+/*  To write debug messages to a console, skia will call SkDebugf(...) following
+    printf conventions (e.g. const char* format, ...). If you want to redirect
+    this to something other than printf, define yours here
+ */
+//#define SkDebugf(...)  MyFunction(__VA_ARGS__)
+
+/*
+ *  To specify a different default font cache limit, define this. If this is
+ *  undefined, skia will use a built-in value.
+ */
+//#define SK_DEFAULT_FONT_CACHE_LIMIT   (1024 * 1024)
+
+/*
+ *  To specify the default size of the image cache, undefine this and set it to
+ *  the desired value (in bytes). SkGraphics.h as a runtime API to set this
+ *  value as well. If this is undefined, a built-in value will be used.
+ */
+//#define SK_DEFAULT_IMAGE_CACHE_LIMIT (1024 * 1024)
+
+/*  Define this to set the upper limit for text to support LCD. Values that
+    are very large increase the cost in the font cache and draw slower, without
+    improving readability. If this is undefined, Skia will use its default
+    value (e.g. 48)
+ */
+//#define SK_MAX_SIZE_FOR_LCDTEXT     48
+
+/*  Change the ordering to work in X windows.
+ */
+#ifdef SK_SAMPLES_FOR_X
+        #define SK_R32_SHIFT    16
+        #define SK_G32_SHIFT    8
+        #define SK_B32_SHIFT    0
+        #define SK_A32_SHIFT    24
+#endif
+
+
+/* Determines whether to build code that supports the GPU backend. Some classes
+   that are not GPU-specific, such as SkShader subclasses, have optional code
+   that is used allows them to interact with the GPU backend. If you'd like to
+   omit this code set SK_SUPPORT_GPU to 0. This also allows you to omit the gpu
+   directories from your include search path when you're not building the GPU
+   backend. Defaults to 1 (build the GPU code).
+ */
+//#define SK_SUPPORT_GPU 1
+
+/* Skia makes use of histogram logging macros to trace the frequency of
+ * events. By default, Skia provides no-op versions of these macros.
+ * Skia consumers can provide their own definitions of these macros to
+ * integrate with their histogram collection backend.
+ */
+//#define SK_HISTOGRAM_BOOLEAN(name, value)
+//#define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)
+
+#endif

+ 50 - 0
skia/include/core/SkAnnotation.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkAnnotation_DEFINED
+#define SkAnnotation_DEFINED
+
+#include "SkTypes.h"
+
+class SkData;
+struct SkPoint;
+struct SkRect;
+class SkCanvas;
+
+/**
+ *  Annotate the canvas by associating the specified URL with the
+ *  specified rectangle (in local coordinates, just like drawRect).
+ *
+ *  If the backend of this canvas does not support annotations, this call is
+ *  safely ignored.
+ *
+ *  The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateRectWithURL(SkCanvas*, const SkRect&, SkData*);
+
+/**
+ *  Annotate the canvas by associating a name with the specified point.
+ *
+ *  If the backend of this canvas does not support annotations, this call is
+ *  safely ignored.
+ *
+ *  The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateNamedDestination(SkCanvas*, const SkPoint&, SkData*);
+
+/**
+ *  Annotate the canvas by making the specified rectangle link to a named
+ *  destination.
+ *
+ *  If the backend of this canvas does not support annotations, this call is
+ *  safely ignored.
+ *
+ *  The caller is responsible for managing its ownership of the SkData.
+ */
+SK_API void SkAnnotateLinkToDestination(SkCanvas*, const SkRect&, SkData*);
+
+#endif

+ 31 - 0
skia/include/core/SkBBHFactory.h

@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBBHFactory_DEFINED
+#define SkBBHFactory_DEFINED
+
+#include "SkTypes.h"
+class SkBBoxHierarchy;
+struct SkRect;
+
+class SK_API SkBBHFactory {
+public:
+    /**
+     *  Allocate a new SkBBoxHierarchy. Return NULL on failure.
+     */
+    virtual SkBBoxHierarchy* operator()(const SkRect& bounds) const = 0;
+    virtual ~SkBBHFactory() {}
+};
+
+class SK_API SkRTreeFactory : public SkBBHFactory {
+public:
+    SkBBoxHierarchy* operator()(const SkRect& bounds) const override;
+private:
+    typedef SkBBHFactory INHERITED;
+};
+
+#endif

+ 1195 - 0
skia/include/core/SkBitmap.h

@@ -0,0 +1,1195 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkBitmap.h and docs/SkBitmap_Reference.bmh
+   on 2018-09-13 13:59:55. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkBitmap_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkBitmap_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkBitmap.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkBitmap_DEFINED
+#define SkBitmap_DEFINED
+
+#include "SkColor.h"
+#include "SkImageInfo.h"
+#include "SkPixmap.h"
+#include "SkPoint.h"
+#include "SkRefCnt.h"
+
+struct SkMask;
+struct SkIRect;
+struct SkRect;
+class SkPaint;
+class SkPixelRef;
+class SkString;
+
+/** \class SkBitmap
+    SkBitmap describes a two-dimensional raster pixel array. SkBitmap is built on
+    SkImageInfo, containing integer width and height, SkColorType and SkAlphaType
+    describing the pixel format, and SkColorSpace describing the range of colors.
+    SkBitmap points to SkPixelRef, which describes the physical array of pixels.
+    SkImageInfo bounds may be located anywhere fully inside SkPixelRef bounds.
+
+    SkBitmap can be drawn using SkCanvas. SkBitmap can be a drawing destination for SkCanvas
+    draw member functions. SkBitmap flexibility as a pixel container limits some
+    optimizations available to the target platform.
+
+    If pixel array is primarily read-only, use SkImage for better performance.
+    If pixel array is primarily written to, use SkSurface for better performance.
+
+    Declaring SkBitmap const prevents altering SkImageInfo: the SkBitmap height, width,
+    and so on cannot change. It does not affect SkPixelRef: a caller may write its
+    pixels. Declaring SkBitmap const affects SkBitmap configuration, not its contents.
+
+    SkBitmap is not thread safe. Each thread must have its own copy of SkBitmap fields,
+    although threads may share the underlying pixel array.
+*/
+class SK_API SkBitmap {
+public:
+    class SK_API Allocator;
+
+    /** Creates an empty SkBitmap without pixels, with kUnknown_SkColorType,
+        kUnknown_SkAlphaType, and with a width and height of zero. SkPixelRef origin is
+        set to (0, 0). SkBitmap is not volatile.
+
+        Use setInfo() to associate SkColorType, SkAlphaType, width, and height
+        after SkBitmap has been created.
+
+        @return  empty SkBitmap
+    */
+    SkBitmap();
+
+    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
+        allocated, so both bitmaps reference the same pixels.
+
+        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef
+        @return     copy of src
+    */
+    SkBitmap(const SkBitmap& src);
+
+    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
+        SkBitmap.
+
+        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef
+        @return     copy of src
+    */
+    SkBitmap(SkBitmap&& src);
+
+    /** Decrements SkPixelRef reference count, if SkPixelRef is not nullptr.
+    */
+    ~SkBitmap();
+
+    /** Copies settings from src to returned SkBitmap. Shares pixels if src has pixels
+        allocated, so both bitmaps reference the same pixels.
+
+        @param src  SkBitmap to copy SkImageInfo, and share SkPixelRef
+        @return     copy of src
+    */
+    SkBitmap& operator=(const SkBitmap& src);
+
+    /** Copies settings from src to returned SkBitmap. Moves ownership of src pixels to
+        SkBitmap.
+
+        @param src  SkBitmap to copy SkImageInfo, and reassign SkPixelRef
+        @return     copy of src
+    */
+    SkBitmap& operator=(SkBitmap&& src);
+
+    /** Swaps the fields of the two bitmaps.
+
+        @param other  SkBitmap exchanged with original
+    */
+    void swap(SkBitmap& other);
+
+    /** Returns a constant reference to the SkPixmap holding the SkBitmap pixel
+        address, row bytes, and SkImageInfo.
+
+        @return  reference to SkPixmap describing this SkBitmap
+    */
+    const SkPixmap& pixmap() const { return fPixmap; }
+
+    /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.
+
+        @return  reference to SkImageInfo
+    */
+    const SkImageInfo& info() const { return fPixmap.info(); }
+
+    /** Returns pixel count in each row. Should be equal or less than
+        rowBytes() / info().bytesPerPixel().
+
+        May be less than pixelRef().width(). Will not exceed pixelRef().width() less
+        pixelRefOrigin().fX.
+
+        @return  pixel width in SkImageInfo
+    */
+    int width() const { return fPixmap.width(); }
+
+    /** Returns pixel row count.
+
+        Maybe be less than pixelRef().height(). Will not exceed pixelRef().height() less
+        pixelRefOrigin().fY.
+
+        @return  pixel height in SkImageInfo
+    */
+    int height() const { return fPixmap.height(); }
+
+    /** Returns SkColorType, one of:
+        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+        kGray_8_SkColorType, kRGBA_F16_SkColorType.
+
+        @return  SkColorType in SkImageInfo
+    */
+    SkColorType colorType() const { return fPixmap.colorType(); }
+
+    /** Returns SkAlphaType, one of:
+        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+        kUnpremul_SkAlphaType.
+
+        @return  SkAlphaType in SkImageInfo
+    */
+    SkAlphaType alphaType() const { return fPixmap.alphaType(); }
+
+    /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
+        reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+        immutable.
+
+        @return  SkColorSpace in SkImageInfo, or nullptr
+    */
+    SkColorSpace* colorSpace() const { return fPixmap.colorSpace(); }
+
+    /** Returns smart pointer to SkColorSpace, the range of colors, associated with
+        SkImageInfo. The smart pointer tracks the number of objects sharing this
+        SkColorSpace reference so the memory is released when the owners destruct.
+
+        The returned SkColorSpace is immutable.
+
+        @return  SkColorSpace in SkImageInfo wrapped in a smart pointer
+    */
+    sk_sp<SkColorSpace> refColorSpace() const { return fPixmap.info().refColorSpace(); }
+
+    /** Returns number of bytes per pixel required by SkColorType.
+        Returns zero if colorType( is kUnknown_SkColorType.
+
+        @return  bytes in pixel
+    */
+    int bytesPerPixel() const { return fPixmap.info().bytesPerPixel(); }
+
+    /** Returns number of pixels that fit on row. Should be greater than or equal to
+        width().
+
+        @return  maximum pixels per row
+    */
+    int rowBytesAsPixels() const { return fPixmap.rowBytesAsPixels(); }
+
+    /** Returns bit shift converting row bytes to row pixels.
+        Returns zero for kUnknown_SkColorType.
+
+        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+    */
+    int shiftPerPixel() const { return fPixmap.shiftPerPixel(); }
+
+    /** Returns true if either width() or height() are zero.
+
+        Does not check if SkPixelRef is nullptr; call drawsNothing() to check width(),
+        height(), and SkPixelRef.
+
+        @return  true if dimensions do not enclose area
+    */
+    bool empty() const { return fPixmap.info().isEmpty(); }
+
+    /** Returns true if SkPixelRef is nullptr.
+
+        Does not check if width() or height() are zero; call drawsNothing() to check
+        width(), height(), and SkPixelRef.
+
+        @return  true if no SkPixelRef is associated
+    */
+    bool isNull() const { return nullptr == fPixelRef; }
+
+    /** Returns true if width() or height() are zero, or if SkPixelRef is nullptr.
+        If true, SkBitmap has no effect when drawn or drawn into.
+
+        @return  true if drawing has no effect
+    */
+    bool drawsNothing() const {
+        return this->empty() || this->isNull();
+    }
+
+    /** Returns row bytes, the interval from one pixel row to the next. Row bytes
+        is at least as large as: width() * info().bytesPerPixel().
+
+        Returns zero if colorType() is kUnknown_SkColorType, or if row bytes supplied to
+        setInfo() is not large enough to hold a row of pixels.
+
+        @return  byte length of pixel row
+    */
+    size_t rowBytes() const { return fPixmap.rowBytes(); }
+
+    /** Sets SkAlphaType, if alphaType is compatible with SkColorType.
+        Returns true unless alphaType is kUnknown_SkAlphaType and current SkAlphaType
+        is not kUnknown_SkAlphaType.
+
+        Returns true if SkColorType is kUnknown_SkColorType. alphaType is ignored, and
+        SkAlphaType remains kUnknown_SkAlphaType.
+
+        Returns true if SkColorType is kRGB_565_SkColorType or kGray_8_SkColorType.
+        alphaType is ignored, and SkAlphaType remains kOpaque_SkAlphaType.
+
+        If SkColorType is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: returns true unless
+        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
+        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored.
+
+        If SkColorType is kAlpha_8_SkColorType, returns true unless
+        alphaType is kUnknown_SkAlphaType and SkAlphaType is not kUnknown_SkAlphaType.
+        If SkAlphaType is kUnknown_SkAlphaType, alphaType is ignored. If alphaType is
+        kUnpremul_SkAlphaType, it is treated as kPremul_SkAlphaType.
+
+        This changes SkAlphaType in SkPixelRef; all bitmaps sharing SkPixelRef
+        are affected.
+
+        @param alphaType  one of:
+                          kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                          kUnpremul_SkAlphaType
+        @return           true if SkAlphaType is set
+    */
+    bool setAlphaType(SkAlphaType alphaType);
+
+    /** Returns pixel address, the base address corresponding to the pixel origin.
+
+        @return  pixel address
+    */
+    void* getPixels() const { return fPixmap.writable_addr(); }
+
+    /** Returns minimum memory required for pixel storage.
+        Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
+        Returns zero if result does not fit in size_t.
+        Returns zero if height() or width() is 0.
+        Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.
+
+        @return  size in bytes of image buffer
+    */
+    size_t computeByteSize() const { return fPixmap.computeByteSize(); }
+
+    /** Returns true if pixels can not change.
+
+        Most immutable SkBitmap checks trigger an assert only on debug builds.
+
+        @return  true if pixels are immutable
+    */
+    bool isImmutable() const;
+
+    /** Sets internal flag to mark SkBitmap as immutable. Once set, pixels can not change.
+        Any other bitmap sharing the same SkPixelRef are also marked as immutable.
+        Once SkPixelRef is marked immutable, the setting cannot be cleared.
+
+        Writing to immutable SkBitmap pixels triggers an assert on debug builds.
+    */
+    void setImmutable();
+
+    /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
+        alpha value is implicitly or explicitly 1.0. If true, and all pixels are
+        not opaque, Skia may draw incorrectly.
+
+        Does not check if SkColorType allows alpha, or if any pixel value has
+        transparency.
+
+        @return  true if SkImageInfo SkAlphaType is kOpaque_SkAlphaType
+    */
+    bool isOpaque() const {
+        return SkAlphaTypeIsOpaque(this->alphaType());
+    }
+
+    /** Provides a hint to caller that pixels should not be cached. Only true if
+        setIsVolatile() has been called to mark as volatile.
+
+        Volatile state is not shared by other bitmaps sharing the same SkPixelRef.
+
+        @return  true if marked volatile
+    */
+    bool isVolatile() const;
+
+    /** Sets if pixels should be read from SkPixelRef on every access. SkBitmap are not
+        volatile by default; a GPU back end may upload pixel values expecting them to be
+        accessed repeatedly. Marking temporary SkBitmap as volatile provides a hint to
+        SkBaseDevice that the SkBitmap pixels should not be cached. This can
+        improve performance by avoiding overhead and reducing resource
+        consumption on SkBaseDevice.
+
+        @param isVolatile  true if backing pixels are temporary
+    */
+    void setIsVolatile(bool isVolatile);
+
+    /** Resets to its initial state; all fields are set to zero, as if SkBitmap had
+        been initialized by SkBitmap().
+
+        Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
+        kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.
+
+        If SkPixelRef is allocated, its reference count is decreased by one, releasing
+        its memory if SkBitmap is the sole owner.
+    */
+    void reset();
+
+    /** Returns true if all pixels are opaque. SkColorType determines how pixels
+        are encoded, and whether pixel describes alpha. Returns true for SkColorType
+        without alpha in each pixel; for other SkColorType, returns true if all
+        pixels have alpha values equivalent to 1.0 or greater.
+
+        For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
+        returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
+        kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
+        For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
+        For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
+        greater.
+
+        Returns false for kUnknown_SkColorType.
+
+        @param bm  SkBitmap to check
+        @return    true if all pixels have opaque values or SkColorType is opaque
+    */
+    static bool ComputeIsOpaque(const SkBitmap& bm) {
+        return bm.pixmap().computeIsOpaque();
+    }
+
+    /** Returns SkRect { 0, 0, width(), height() }.
+
+        @param bounds  container for floating point rectangle
+    */
+    void getBounds(SkRect* bounds) const;
+
+    /** Returns SkIRect { 0, 0, width(), height() }.
+
+        @param bounds  container for integral rectangle
+    */
+    void getBounds(SkIRect* bounds) const;
+
+    /** Returns SkIRect { 0, 0, width(), height() }.
+
+        @return  integral rectangle from origin to width() and height()
+    */
+    SkIRect bounds() const { return fPixmap.info().bounds(); }
+
+    /** Returns SkISize { width(), height() }.
+
+        @return  integral size of width() and height()
+    */
+    SkISize dimensions() const { return fPixmap.info().dimensions(); }
+
+    /** Returns the bounds of this bitmap, offset by its SkPixelRef origin.
+
+        @return  bounds within SkPixelRef bounds
+    */
+    SkIRect getSubset() const {
+        SkIPoint origin = this->pixelRefOrigin();
+        return SkIRect::MakeXYWH(origin.x(), origin.y(), this->width(), this->height());
+    }
+
+    /** Sets width, height, SkAlphaType, SkColorType, SkColorSpace, and optional
+        rowBytes. Frees pixels, and returns true if successful.
+
+        imageInfo.alphaType() may be altered to a value permitted by imageInfo.colorSpace().
+        If imageInfo.colorType() is kUnknown_SkColorType, imageInfo.alphaType() is
+        set to kUnknown_SkAlphaType.
+        If imageInfo.colorType() is kAlpha_8_SkColorType and imageInfo.alphaType() is
+        kUnpremul_SkAlphaType, imageInfo.alphaType() is replaced by kPremul_SkAlphaType.
+        If imageInfo.colorType() is kRGB_565_SkColorType or kGray_8_SkColorType,
+        imageInfo.alphaType() is set to kOpaque_SkAlphaType.
+        If imageInfo.colorType() is kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+        kBGRA_8888_SkColorType, or kRGBA_F16_SkColorType: imageInfo.alphaType() remains
+        unchanged.
+
+        rowBytes must equal or exceed imageInfo.minRowBytes(). If imageInfo.colorSpace() is
+        kUnknown_SkColorType, rowBytes is ignored and treated as zero; for all other
+        SkColorSpace values, rowBytes of zero is treated as imageInfo.minRowBytes().
+
+        Calls reset() and returns false if:
+        - rowBytes exceeds 31 bits
+        - imageInfo.width() is negative
+        - imageInfo.height() is negative
+        - rowBytes is positive and less than imageInfo.width() times imageInfo.bytesPerPixel()
+
+        @param imageInfo  contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param rowBytes   imageInfo.minRowBytes() or larger; or zero
+        @return           true if SkImageInfo set successfully
+    */
+    bool setInfo(const SkImageInfo& imageInfo, size_t rowBytes = 0);
+
+    /** \enum SkBitmap::AllocFlags
+        AllocFlags provides the option to zero pixel memory when allocated.
+    */
+    enum AllocFlags {
+        kZeroPixels_AllocFlag = 1 << 0, //!< zero pixel memory
+    };
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory. If flags is kZeroPixels_AllocFlag, memory is zeroed.
+
+        Returns false and calls reset() if SkImageInfo could not be set, or memory could
+        not be allocated, or memory could not optionally be zeroed.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc(), if flags is zero, and calloc(), if flags is
+        kZeroPixels_AllocFlag.
+
+        flags set to kZeroPixels_AllocFlag offers equal or better performance than
+        subsequently calling eraseColor() with SK_ColorTRANSPARENT.
+
+        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param flags  kZeroPixels_AllocFlag, or zero
+        @return       true if pixels allocation is successful
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocPixelsFlags(const SkImageInfo& info, uint32_t flags);
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory. If flags is kZeroPixels_AllocFlag, memory is zeroed.
+
+        Aborts execution if SkImageInfo could not be set, or memory could
+        not be allocated, or memory could not optionally
+        be zeroed. Abort steps may be provided by the user at compile time by defining
+        SK_ABORT.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc(), if flags is zero, and calloc(), if flags is
+        kZeroPixels_AllocFlag.
+
+        flags set to kZeroPixels_AllocFlag offers equal or better performance than
+        subsequently calling eraseColor() with SK_ColorTRANSPARENT.
+
+        @param info   contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param flags  kZeroPixels_AllocFlag, or zero
+    */
+    void allocPixelsFlags(const SkImageInfo& info, uint32_t flags) {
+        SkASSERT_RELEASE(this->tryAllocPixelsFlags(info, flags));
+    }
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
+        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.
+
+        Returns false and calls reset() if SkImageInfo could not be set, or memory could
+        not be allocated.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc().
+
+        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param rowBytes  size of pixel row or larger; may be zero
+        @return          true if pixel storage is allocated
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info, size_t rowBytes);
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory. rowBytes must equal or exceed info.width() times info.bytesPerPixel(),
+        or equal zero. Pass in zero for rowBytes to compute the minimum valid value.
+
+        Aborts execution if SkImageInfo could not be set, or memory could
+        not be allocated. Abort steps may be provided by
+        the user at compile time by defining SK_ABORT.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc().
+
+        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param rowBytes  size of pixel row or larger; may be zero
+    */
+    void allocPixels(const SkImageInfo& info, size_t rowBytes) {
+        SkASSERT_RELEASE(this->tryAllocPixels(info, rowBytes));
+    }
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory.
+
+        Returns false and calls reset() if SkImageInfo could not be set, or memory could
+        not be allocated.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc().
+
+        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @return      true if pixel storage is allocated
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocPixels(const SkImageInfo& info) {
+        return this->tryAllocPixels(info, info.minRowBytes());
+    }
+
+    /** Sets SkImageInfo to info following the rules in setInfo() and allocates pixel
+        memory.
+
+        Aborts execution if SkImageInfo could not be set, or memory could
+        not be allocated. Abort steps may be provided by
+        the user at compile time by defining SK_ABORT.
+
+        On most platforms, allocating pixel memory may succeed even though there is
+        not sufficient memory to hold pixels; allocation does not take place
+        until the pixels are written to. The actual behavior depends on the platform
+        implementation of malloc().
+
+        @param info  contains width, height, SkAlphaType, SkColorType, SkColorSpace
+    */
+    void allocPixels(const SkImageInfo& info) {
+        this->allocPixels(info, info.minRowBytes());
+    }
+
+    /** Sets SkImageInfo to width, height, and native color type; and allocates
+        pixel memory. If isOpaque is true, sets SkImageInfo to kOpaque_SkAlphaType;
+        otherwise, sets to kPremul_SkAlphaType.
+
+        Calls reset() and returns false if width exceeds 29 bits or is negative,
+        or height is negative.
+
+        Returns false if allocation fails.
+
+        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
+        the platform. SkBitmap drawn to output device skips converting its pixel format.
+
+        @param width     pixel column count; must be zero or greater
+        @param height    pixel row count; must be zero or greater
+        @param isOpaque  true if pixels do not have transparency
+        @return          true if pixel storage is allocated
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocN32Pixels(int width, int height, bool isOpaque = false) {
+        SkImageInfo info = SkImageInfo::MakeN32(width, height,
+                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+        return this->tryAllocPixels(info);
+    }
+
+    /** Sets SkImageInfo to width, height, and the native color type; and allocates
+        pixel memory. If isOpaque is true, sets SkImageInfo to kPremul_SkAlphaType;
+        otherwise, sets to kOpaque_SkAlphaType.
+
+        Aborts if width exceeds 29 bits or is negative, or height is negative, or
+        allocation fails. Abort steps may be provided by the user at compile time by
+        defining SK_ABORT.
+
+        Use to create SkBitmap that matches SkPMColor, the native pixel arrangement on
+        the platform. SkBitmap drawn to output device skips converting its pixel format.
+
+        @param width     pixel column count; must be zero or greater
+        @param height    pixel row count; must be zero or greater
+        @param isOpaque  true if pixels do not have transparency
+    */
+    void allocN32Pixels(int width, int height, bool isOpaque = false) {
+        SkImageInfo info = SkImageInfo::MakeN32(width, height,
+                                            isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+        this->allocPixels(info);
+    }
+
+    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
+        containing pixels and rowBytes. releaseProc, if not nullptr, is called
+        immediately on failure or when pixels are no longer referenced. context may be
+        nullptr.
+
+        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
+        calls releaseProc if present, calls reset(), and returns false.
+
+        Otherwise, if pixels equals nullptr: sets SkImageInfo, calls releaseProc if
+        present, returns true.
+
+        If SkImageInfo is set, pixels is not nullptr, and releaseProc is not nullptr:
+        when pixels are no longer referenced, calls releaseProc with pixels and context
+        as parameters.
+
+        @param info         contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param pixels       address or pixel storage; may be nullptr
+        @param rowBytes     size of pixel row or larger
+        @param releaseProc  function called when pixels can be deleted; may be nullptr
+        @param context      caller state passed to releaseProc; may be nullptr
+        @return             true if SkImageInfo is set to info
+    */
+    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
+                       void (*releaseProc)(void* addr, void* context), void* context);
+
+    /** Sets SkImageInfo to info following the rules in setInfo(), and creates SkPixelRef
+        containing pixels and rowBytes.
+
+        If SkImageInfo could not be set, or rowBytes is less than info.minRowBytes():
+        calls reset(), and returns false.
+
+        Otherwise, if pixels equals nullptr: sets SkImageInfo, returns true.
+
+        Caller must ensure that pixels are valid for the lifetime of SkBitmap and SkPixelRef.
+
+        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param pixels    address or pixel storage; may be nullptr
+        @param rowBytes  size of pixel row or larger
+        @return          true if SkImageInfo is set to info
+    */
+    bool installPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
+        return this->installPixels(info, pixels, rowBytes, nullptr, nullptr);
+    }
+
+    /** Sets SkImageInfo to pixmap.info() following the rules in setInfo(), and creates
+        SkPixelRef containing pixmap.addr() and pixmap.rowBytes().
+
+        If SkImageInfo could not be set, or pixmap.rowBytes() is less than
+        SkImageInfo::minRowBytes(): calls reset(), and returns false.
+
+        Otherwise, if pixmap.addr() equals nullptr: sets SkImageInfo, returns true.
+
+        Caller must ensure that pixmap is valid for the lifetime of SkBitmap and SkPixelRef.
+
+        @param pixmap  SkImageInfo, pixel address, and rowBytes()
+        @return        true if SkImageInfo was set to pixmap.info()
+    */
+    bool installPixels(const SkPixmap& pixmap);
+
+    /** Deprecated.
+    */
+    bool installMaskPixels(const SkMask& mask);
+
+    /** Replaces SkPixelRef with pixels, preserving SkImageInfo and rowBytes().
+        Sets SkPixelRef origin to (0, 0).
+
+        If pixels is nullptr, or if info().colorType() equals kUnknown_SkColorType;
+        release reference to SkPixelRef, and set SkPixelRef to nullptr.
+
+        Caller is responsible for handling ownership pixel memory for the lifetime
+        of SkBitmap and SkPixelRef.
+
+        @param pixels  address of pixel storage, managed by caller
+    */
+    void setPixels(void* pixels);
+
+    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
+        The allocation size is determined by SkImageInfo width, height, and SkColorType.
+
+        Returns false if info().colorType() is kUnknown_SkColorType, or allocation fails.
+
+        @return  true if the allocation succeeds
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocPixels() {
+        return this->tryAllocPixels((Allocator*)nullptr);
+    }
+
+    /** Allocates pixel memory with HeapAllocator, and replaces existing SkPixelRef.
+        The allocation size is determined by SkImageInfo width, height, and SkColorType.
+
+        Aborts if info().colorType() is kUnknown_SkColorType, or allocation fails.
+        Abort steps may be provided by the user at compile
+        time by defining SK_ABORT.
+    */
+    void allocPixels() {
+        this->allocPixels((Allocator*)nullptr);
+    }
+
+    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
+        The allocation size is determined by SkImageInfo width, height, and SkColorType.
+        If allocator is nullptr, use HeapAllocator instead.
+
+        Returns false if Allocator::allocPixelRef return false.
+
+        @param allocator  instance of SkBitmap::Allocator instantiation
+        @return           true if custom allocator reports success
+    */
+    bool SK_WARN_UNUSED_RESULT tryAllocPixels(Allocator* allocator);
+
+    /** Allocates pixel memory with allocator, and replaces existing SkPixelRef.
+        The allocation size is determined by SkImageInfo width, height, and SkColorType.
+        If allocator is nullptr, use HeapAllocator instead.
+
+        Aborts if Allocator::allocPixelRef return false. Abort steps may be provided by
+        the user at compile time by defining SK_ABORT.
+
+        @param allocator  instance of SkBitmap::Allocator instantiation
+    */
+    void allocPixels(Allocator* allocator) {
+        SkASSERT_RELEASE(this->tryAllocPixels(allocator));
+    }
+
+    /** Returns SkPixelRef, which contains: pixel base address; its dimensions; and
+        rowBytes(), the interval from one row to the next. Does not change SkPixelRef
+        reference count. SkPixelRef may be shared by multiple bitmaps.
+        If SkPixelRef has not been set, returns nullptr.
+
+        @return  SkPixelRef, or nullptr
+    */
+    SkPixelRef* pixelRef() const { return fPixelRef.get(); }
+
+    /** Returns origin of pixels within SkPixelRef. SkBitmap bounds is always contained
+        by SkPixelRef bounds, which may be the same size or larger. Multiple SkBitmap
+        can share the same SkPixelRef, where each SkBitmap has different bounds.
+
+        The returned origin added to SkBitmap dimensions equals or is smaller than the
+        SkPixelRef dimensions.
+
+        Returns (0, 0) if SkPixelRef is nullptr.
+
+        @return  pixel origin within SkPixelRef
+    */
+    SkIPoint pixelRefOrigin() const;
+
+    /** Replaces pixelRef and origin in SkBitmap.  dx and dy specify the offset
+        within the SkPixelRef pixels for the top-left corner of the bitmap.
+
+        Asserts in debug builds if dx or dy are out of range. Pins dx and dy
+        to legal range in release builds.
+
+        The caller is responsible for ensuring that the pixels match the
+        SkColorType and SkAlphaType in SkImageInfo.
+
+        @param pixelRef  SkPixelRef describing pixel address and rowBytes()
+        @param dx        column offset in SkPixelRef for bitmap origin
+        @param dy        row offset in SkPixelRef for bitmap origin
+    */
+    void setPixelRef(sk_sp<SkPixelRef> pixelRef, int dx, int dy);
+
+    /** Returns true if SkBitmap is can be drawn.
+
+        @return  true if getPixels() is not nullptr
+    */
+    bool readyToDraw() const {
+        return this->getPixels() != nullptr;
+    }
+
+    /** Returns a unique value corresponding to the pixels in SkPixelRef.
+        Returns a different value after notifyPixelsChanged() has been called.
+        Returns zero if SkPixelRef is nullptr.
+
+        Determines if pixels have changed since last examined.
+
+        @return  unique value for pixels in SkPixelRef
+    */
+    uint32_t getGenerationID() const;
+
+    /** Marks that pixels in SkPixelRef have changed. Subsequent calls to
+        getGenerationID() return a different value.
+    */
+    void notifyPixelsChanged() const;
+
+    /** Replaces pixel values with c. All pixels contained by bounds() are affected.
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
+        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
+        then RGB is ignored.
+
+        @param c  unpremultiplied color
+    */
+    void eraseColor(SkColor c) const;
+
+    /** Replaces pixel values with unpremultiplied color built from a, r, g, and b.
+        All pixels contained by bounds() are affected.
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then a
+        is ignored; r, g, and b are treated as opaque. If colorType() is kAlpha_8_SkColorType,
+        then r, g, and b are ignored.
+
+        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
+        @param r  amount of red, from no red (0) to full red (255)
+        @param g  amount of green, from no green (0) to full green (255)
+        @param b  amount of blue, from no blue (0) to full blue (255)
+    */
+    void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const {
+        this->eraseColor(SkColorSetARGB(a, r, g, b));
+    }
+
+    /** Replaces pixel values inside area with c. If area does not intersect bounds(),
+        call has no effect.
+
+        If the colorType() is kGray_8_SkColorType or kRGB_565_SkColorType, then alpha
+        is ignored; RGB is treated as opaque. If colorType() is kAlpha_8_SkColorType,
+        then RGB is ignored.
+
+        @param c     unpremultiplied color
+        @param area  rectangle to fill
+    */
+    void erase(SkColor c, const SkIRect& area) const;
+
+    /** Deprecated.
+    */
+    void eraseArea(const SkIRect& area, SkColor c) const {
+        this->erase(c, area);
+    }
+
+    /** Returns pixel at (x, y) as unpremultiplied color.
+        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined; and returns undefined values or may crash if
+        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
+        pixel address is nullptr.
+
+        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
+        conversion to unpremultiplied color; original pixel data may have additional
+        precision.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   pixel converted to unpremultiplied color
+    */
+    SkColor getColor(int x, int y) const {
+        return this->pixmap().getColor(x, y);
+    }
+
+    /** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
+        This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
+        (and more precise if the pixels store more than 8 bits per component).
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   alpha converted to normalized float
+     */
+    float getAlphaf(int x, int y) const {
+        return this->pixmap().getAlphaf(x, y);
+    }
+
+    /** Returns pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y, or kUnknown_SkColorType,
+        trigger an assert() if built with SK_DEBUG defined. Returns nullptr if
+        SkColorType is kUnknown_SkColorType, or SkPixelRef is nullptr.
+
+        Performs a lookup of pixel size; for better performance, call
+        one of: getAddr8(), getAddr16(), or getAddr32().
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   generic pointer to pixel
+    */
+    void* getAddr(int x, int y) const;
+
+    /** Returns address at (x, y).
+
+        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+        - SkPixelRef is nullptr
+        - bytesPerPixel() is not four
+        - x is negative, or not less than width()
+        - y is negative, or not less than height()
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   unsigned 32-bit pointer to pixel at (x, y)
+    */
+    inline uint32_t* getAddr32(int x, int y) const;
+
+    /** Returns address at (x, y).
+
+        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+        - SkPixelRef is nullptr
+        - bytesPerPixel() is not two
+        - x is negative, or not less than width()
+        - y is negative, or not less than height()
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   unsigned 16-bit pointer to pixel at (x, y)
+    */
+    inline uint16_t* getAddr16(int x, int y) const;
+
+    /** Returns address at (x, y).
+
+        Input is not validated. Triggers an assert() if built with SK_DEBUG defined and:
+        - SkPixelRef is nullptr
+        - bytesPerPixel() is not one
+        - x is negative, or not less than width()
+        - y is negative, or not less than height()
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   unsigned 8-bit pointer to pixel at (x, y)
+    */
+    inline uint8_t* getAddr8(int x, int y) const;
+
+    /** Shares SkPixelRef with dst. Pixels are not copied; SkBitmap and dst point
+        to the same pixels; dst bounds() are set to the intersection of subset
+        and the original bounds().
+
+        subset may be larger than bounds(). Any area outside of bounds() is ignored.
+
+        Any contents of dst are discarded. isVolatile() setting is copied to dst.
+        dst is set to colorType(), alphaType(), and colorSpace().
+
+        Return false if:
+        - dst is nullptr
+        - SkPixelRef is nullptr
+        - subset does not intersect bounds()
+
+        @param dst     SkBitmap set to subset
+        @param subset  rectangle of pixels to reference
+        @return        true if dst is replaced by subset
+    */
+    bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
+
+    /** Copies a SkRect of pixels from SkBitmap to dstPixels. Copy starts at (srcX, srcY),
+        and does not exceed SkBitmap (width(), height()).
+
+        dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
+        destination. dstRowBytes specifics the gap from one destination row to the next.
+        Returns true if pixels are copied. Returns false if:
+        - dstInfo has no address
+        - dstRowBytes is less than dstInfo.minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+        If SkBitmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+        If SkBitmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+        match. If SkBitmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false if width() or height() is zero or negative.
+        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().
+
+        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
+        @param dstPixels    destination pixel storage
+        @param dstRowBytes  destination row length
+        @param srcX         column index whose absolute value is less than width()
+        @param srcY         row index whose absolute value is less than height()
+        @return             true if pixels are copied to dstPixels
+    */
+    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+                    int srcX, int srcY) const;
+
+    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (srcX, srcY), and
+        does not exceed SkBitmap (width(), height()).
+
+        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+        and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+        row to the next. Returns true if pixels are copied. Returns false if:
+        - dst pixel storage equals nullptr
+        - dst.rowBytes is less than SkImageInfo::minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false if width() or height() is zero or negative.
+        Returns false if abs(srcX) >= Bitmap width(), or if abs(srcY) >= Bitmap height().
+
+        @param dst   destination SkPixmap: SkImageInfo, pixels, row bytes
+        @param srcX  column index whose absolute value is less than width()
+        @param srcY  row index whose absolute value is less than height()
+        @return      true if pixels are copied to dst
+    */
+    bool readPixels(const SkPixmap& dst, int srcX, int srcY) const;
+
+    /** Copies a SkRect of pixels from SkBitmap to dst. Copy starts at (0, 0), and
+        does not exceed SkBitmap (width(), height()).
+
+        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+        and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+        row to the next. Returns true if pixels are copied. Returns false if:
+        - dst pixel storage equals nullptr
+        - dst.rowBytes is less than SkImageInfo::minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+        If SkBitmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+        If SkBitmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+        match. If SkBitmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        @param dst  destination SkPixmap: SkImageInfo, pixels, row bytes
+        @return     true if pixels are copied to dst
+    */
+    bool readPixels(const SkPixmap& dst) const {
+        return this->readPixels(dst, 0, 0);
+    }
+
+    /** Copies a SkRect of pixels from src. Copy starts at (dstX, dstY), and does not exceed
+        (src.width(), src.height()).
+
+        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+        and row bytes of source. src.rowBytes() specifics the gap from one source
+        row to the next. Returns true if pixels are copied. Returns false if:
+        - src pixel storage equals nullptr
+        - src.rowBytes is less than SkImageInfo::minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
+        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
+        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
+        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        dstX and dstY may be negative to copy only top or left of source. Returns
+        false if width() or height() is zero or negative.
+        Returns false if abs(dstX) >= Bitmap width(), or if abs(dstY) >= Bitmap height().
+
+        @param src   source SkPixmap: SkImageInfo, pixels, row bytes
+        @param dstX  column index whose absolute value is less than width()
+        @param dstY  row index whose absolute value is less than height()
+        @return      true if src pixels are copied to SkBitmap
+    */
+    bool writePixels(const SkPixmap& src, int dstX, int dstY);
+
+    /** Copies a SkRect of pixels from src. Copy starts at (0, 0), and does not exceed
+        (src.width(), src.height()).
+
+        src specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+        and row bytes of source. src.rowBytes() specifics the gap from one source
+        row to the next. Returns true if pixels are copied. Returns false if:
+        - src pixel storage equals nullptr
+        - src.rowBytes is less than SkImageInfo::minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkBitmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; src SkColorType must match.
+        If SkBitmap colorType() is kGray_8_SkColorType, src SkColorSpace must match.
+        If SkBitmap alphaType() is kOpaque_SkAlphaType, src SkAlphaType must
+        match. If SkBitmap colorSpace() is nullptr, src SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        @param src  source SkPixmap: SkImageInfo, pixels, row bytes
+        @return     true if src pixels are copied to SkBitmap
+    */
+    bool writePixels(const SkPixmap& src) {
+        return this->writePixels(src, 0, 0);
+    }
+
+    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+        or dst pixels cannot be allocated.
+
+        Uses HeapAllocator to reserve memory for dst SkPixelRef.
+
+        @param dst  holds SkPixelRef to fill with alpha layer
+        @return     true if alpha layer was constructed in dst SkPixelRef
+    */
+    bool extractAlpha(SkBitmap* dst) const {
+        return this->extractAlpha(dst, nullptr, nullptr, nullptr);
+    }
+
+    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+        or dst pixels cannot be allocated.
+
+        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
+        generates mask alpha from SkBitmap. Uses HeapAllocator to reserve memory for dst
+        SkPixelRef. Sets offset to top-left position for dst for alignment with SkBitmap;
+        (0, 0) unless SkMaskFilter generates mask.
+
+        @param dst     holds SkPixelRef to fill with alpha layer
+        @param paint   holds optional SkMaskFilter; may be nullptr
+        @param offset  top-left position for dst; may be nullptr
+        @return        true if alpha layer was constructed in dst SkPixelRef
+    */
+    bool extractAlpha(SkBitmap* dst, const SkPaint* paint,
+                      SkIPoint* offset) const {
+        return this->extractAlpha(dst, paint, nullptr, offset);
+    }
+
+    /** Sets dst to alpha described by pixels. Returns false if dst cannot be written to
+        or dst pixels cannot be allocated.
+
+        If paint is not nullptr and contains SkMaskFilter, SkMaskFilter
+        generates mask alpha from SkBitmap. allocator may reference a custom allocation
+        class or be set to nullptr to use HeapAllocator. Sets offset to top-left
+        position for dst for alignment with SkBitmap; (0, 0) unless SkMaskFilter generates
+        mask.
+
+        @param dst        holds SkPixelRef to fill with alpha layer
+        @param paint      holds optional SkMaskFilter; may be nullptr
+        @param allocator  function to reserve memory for SkPixelRef; may be nullptr
+        @param offset     top-left position for dst; may be nullptr
+        @return           true if alpha layer was constructed in dst SkPixelRef
+    */
+    bool extractAlpha(SkBitmap* dst, const SkPaint* paint, Allocator* allocator,
+                      SkIPoint* offset) const;
+
+    /** Copies SkBitmap pixel address, row bytes, and SkImageInfo to pixmap, if address
+        is available, and returns true. If pixel address is not available, return
+        false and leave pixmap unchanged.
+
+        pixmap contents become invalid on any future change to SkBitmap.
+
+        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
+        @return        true if SkBitmap has direct access to pixels
+    */
+    bool peekPixels(SkPixmap* pixmap) const;
+
+    /** Asserts if internal values are illegal or inconsistent. Only available if
+        SK_DEBUG is defined at compile time.
+    */
+    SkDEBUGCODE(void validate() const;)
+
+    /** \class SkBitmap::Allocator
+        Abstract subclass of HeapAllocator.
+    */
+    class Allocator : public SkRefCnt {
+    public:
+
+        /** Allocates the pixel memory for the bitmap, given its dimensions and
+            SkColorType. Returns true on success, where success means either setPixels()
+            or setPixelRef() was called.
+
+            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output
+            @return        true if SkPixelRef was allocated
+        */
+        virtual bool allocPixelRef(SkBitmap* bitmap) = 0;
+    private:
+        typedef SkRefCnt INHERITED;
+    };
+
+    /** \class SkBitmap::HeapAllocator
+        Subclass of SkBitmap::Allocator that returns a SkPixelRef that allocates its pixel
+        memory from the heap. This is the default SkBitmap::Allocator invoked by
+        allocPixels().
+    */
+    class HeapAllocator : public Allocator {
+    public:
+
+        /** Allocates the pixel memory for the bitmap, given its dimensions and
+            SkColorType. Returns true on success, where success means either setPixels()
+            or setPixelRef() was called.
+
+            @param bitmap  SkBitmap containing SkImageInfo as input, and SkPixelRef as output
+            @return        true if pixels are allocated
+        */
+        bool allocPixelRef(SkBitmap* bitmap) override;
+    };
+
+private:
+    enum Flags {
+        kImageIsVolatile_Flag   = 0x02,
+    };
+
+    sk_sp<SkPixelRef>   fPixelRef;
+    SkPixmap            fPixmap;
+    uint8_t             fFlags;
+
+    friend class SkReadBuffer;        // unflatten
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
+    SkASSERT(fPixmap.addr());
+    return fPixmap.writable_addr32(x, y);
+}
+
+inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
+    SkASSERT(fPixmap.addr());
+    return fPixmap.writable_addr16(x, y);
+}
+
+inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
+    SkASSERT(fPixmap.addr());
+    return fPixmap.writable_addr8(x, y);
+}
+
+#endif

+ 75 - 0
skia/include/core/SkBlendMode.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkBlendMode.h and docs/SkBlendMode_Reference.bmh
+   on 2018-07-13 08:15:10. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkBlendMode_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkBlendMode_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkBlendMode.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkBlendMode_DEFINED
+#define SkBlendMode_DEFINED
+
+#include "SkTypes.h"
+
+enum class SkBlendMode {
+    kClear,                           //!< replaces destination with zero: fully transparent
+    kSrc,                             //!< replaces destination
+    kDst,                             //!< preserves destination
+    kSrcOver,                         //!< source over destination
+    kDstOver,                         //!< destination over source
+    kSrcIn,                           //!< source trimmed inside destination
+    kDstIn,                           //!< destination trimmed by source
+    kSrcOut,                          //!< source trimmed outside destination
+    kDstOut,                          //!< destination trimmed outside source
+    kSrcATop,                         //!< source inside destination blended with destination
+    kDstATop,                         //!< destination inside source blended with source
+    kXor,                             //!< each of source and destination trimmed outside the other
+    kPlus,                            //!< sum of colors
+    kModulate,                        //!< product of premultiplied colors; darkens destination
+    kScreen,                //!< multiply inverse of pixels, inverting result; brightens destination
+    kLastCoeffMode     = kScreen,     //!< last porter duff blend mode
+    kOverlay,                         //!< multiply or screen, depending on destination
+    kDarken,                          //!< darker of source and destination
+    kLighten,                         //!< lighter of source and destination
+    kColorDodge,                      //!< brighten destination to reflect source
+    kColorBurn,                       //!< darken destination to reflect source
+    kHardLight,                       //!< multiply or screen, depending on source
+    kSoftLight,                       //!< lighten or darken, depending on source
+    kDifference,                      //!< subtract darker from lighter with higher contrast
+    kExclusion,                       //!< subtract darker from lighter with lower contrast
+    kMultiply,                        //!< multiply source with destination, darkening image
+    kLastSeparableMode = kMultiply,   //!< last blend mode operating separately on components
+    kHue,                           //!< hue of source with saturation and luminosity of destination
+    kSaturation,                    //!< saturation of source with hue and luminosity of destination
+    kColor,                         //!< hue and saturation of source with luminosity of destination
+    kLuminosity,                    //!< luminosity of source with hue and saturation of destination
+    kLastMode          = kLuminosity, //!< last valid value
+};
+
+/** Returns name of blendMode as null-terminated C string.
+
+    @param blendMode  one of:
+                      SkBlendMode::kClear, SkBlendMode::kSrc, SkBlendMode::kDst,
+                      SkBlendMode::kSrcOver, SkBlendMode::kDstOver, SkBlendMode::kSrcIn,
+                      SkBlendMode::kDstIn, SkBlendMode::kSrcOut, SkBlendMode::kDstOut,
+                      SkBlendMode::kSrcATop, SkBlendMode::kDstATop, SkBlendMode::kXor,
+                      SkBlendMode::kPlus, SkBlendMode::kModulate, SkBlendMode::kScreen,
+                      SkBlendMode::kOverlay, SkBlendMode::kDarken, SkBlendMode::kLighten,
+                      SkBlendMode::kColorDodge, SkBlendMode::kColorBurn, SkBlendMode::kHardLight,
+                      SkBlendMode::kSoftLight, SkBlendMode::kDifference, SkBlendMode::kExclusion,
+                      SkBlendMode::kMultiply, SkBlendMode::kHue, SkBlendMode::kSaturation,
+                      SkBlendMode::kColor, SkBlendMode::kLuminosity
+    @return           C string
+*/
+SK_API const char* SkBlendMode_Name(SkBlendMode blendMode);
+
+#endif

+ 22 - 0
skia/include/core/SkBlurTypes.h

@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkBlurTypes_DEFINED
+#define SkBlurTypes_DEFINED
+
+#include "SkTypes.h"
+
+enum SkBlurStyle : int {
+    kNormal_SkBlurStyle,  //!< fuzzy inside and outside
+    kSolid_SkBlurStyle,   //!< solid inside, fuzzy outside
+    kOuter_SkBlurStyle,   //!< nothing inside, fuzzy outside
+    kInner_SkBlurStyle,   //!< fuzzy inside, nothing outside
+
+    kLastEnum_SkBlurStyle = kInner_SkBlurStyle,
+};
+
+#endif

+ 2779 - 0
skia/include/core/SkCanvas.h

@@ -0,0 +1,2779 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkCanvas.h and docs/SkCanvas_Reference.bmh
+   on 2018-08-28 10:32:58. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkCanvas_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkCanvas_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkCanvas.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkCanvas_DEFINED
+#define SkCanvas_DEFINED
+
+#include "../private/SkMacros.h"
+#include "SkBlendMode.h"
+#include "SkClipOp.h"
+#include "SkDeque.h"
+#include "SkPaint.h"
+#include "SkRasterHandleAllocator.h"
+#include "SkSurfaceProps.h"
+#include "SkVertices.h"
+
+class GrContext;
+class GrRenderTargetContext;
+class SkAndroidFrameworkUtils;
+class SkBaseDevice;
+class SkBitmap;
+class SkData;
+class SkDraw;
+class SkDrawable;
+struct SkDrawShadowRec;
+class SkFont;
+class SkGlyphRunBuilder;
+class SkImage;
+class SkImageFilter;
+class SkMetaData;
+class SkPath;
+class SkPicture;
+class SkPixmap;
+class SkRegion;
+class SkRRect;
+struct SkRSXform;
+class SkSurface;
+class SkSurface_Base;
+class SkTextBlob;
+
+/** \class SkCanvas
+    SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed.
+    SkCanvas contains a stack of SkMatrix and clip values.
+
+    SkCanvas and SkPaint together provide the state to draw into SkSurface or SkBaseDevice.
+    Each SkCanvas draw call transforms the geometry of the object by the concatenation of all
+    SkMatrix values in the stack. The transformed geometry is clipped by the intersection
+    of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing
+    state such as color, SkTypeface, text size, stroke width, SkShader and so on.
+
+    To draw to a pixel-based destination, create raster surface or GPU surface.
+    Request SkCanvas from SkSurface to obtain the interface to draw.
+    SkCanvas generated by raster surface draws to memory visible to the CPU.
+    SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.
+
+    To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder.
+    SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the
+    destination.
+
+    SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.
+    This approach may be deprecated in the future.
+*/
+class SK_API SkCanvas {
+    enum PrivateSaveLayerFlags {
+        kDontClipToLayer_PrivateSaveLayerFlag   = 1U << 31,
+    };
+
+public:
+
+    /** Allocates raster SkCanvas that will draw directly into pixels.
+
+        SkCanvas is returned if all parameters are valid.
+        Valid parameters include:
+        info dimensions are zero or positive;
+        info contains SkColorType and SkAlphaType supported by raster surface;
+        pixels is not nullptr;
+        rowBytes is zero or large enough to contain info width pixels of SkColorType.
+
+        Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
+        If rowBytes is greater than zero, it must be equal to or greater than
+        info width times bytes required for SkColorType.
+
+        Pixel buffer size should be info height times computed rowBytes.
+        Pixels are not initialized.
+        To access pixels after drawing, call flush() or peekPixels().
+
+        @param info      width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface;
+                         width, or height, or both, may be zero
+        @param pixels    pointer to destination pixels buffer
+        @param rowBytes  interval from one SkSurface row to the next, or zero
+        @param props     LCD striping orientation and setting for device independent fonts;
+                         may be nullptr
+        @return          SkCanvas if all parameters are valid; otherwise, nullptr
+    */
+    static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
+                                                      size_t rowBytes,
+                                                      const SkSurfaceProps* props = nullptr);
+
+    /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas
+        calls draw into pixels.
+        SkColorType is set to kN32_SkColorType.
+        SkAlphaType is set to kPremul_SkAlphaType.
+        To access pixels after drawing, call flush() or peekPixels().
+
+        SkCanvas is returned if all parameters are valid.
+        Valid parameters include:
+        width and height are zero or positive;
+        pixels is not nullptr;
+        rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
+
+        Pass zero for rowBytes to compute rowBytes from width and size of pixel.
+        If rowBytes is greater than zero, it must be equal to or greater than
+        width times bytes required for SkColorType.
+
+        Pixel buffer size should be height times rowBytes.
+
+        @param width     pixel column count on raster surface created; must be zero or greater
+        @param height    pixel row count on raster surface created; must be zero or greater
+        @param pixels    pointer to destination pixels buffer; buffer size should be height
+                         times rowBytes
+        @param rowBytes  interval from one SkSurface row to the next, or zero
+        @return          SkCanvas if all parameters are valid; otherwise, nullptr
+    */
+    static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
+                                                         size_t rowBytes) {
+        return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
+    }
+
+    /** Creates an empty SkCanvas with no backing device or pixels, with
+        a width and height of zero.
+
+        @return  empty SkCanvas
+    */
+    SkCanvas();
+
+    /** Creates SkCanvas of the specified dimensions without a SkSurface.
+        Used by subclasses with custom implementations for draw member functions.
+
+        If props equals nullptr, SkSurfaceProps are created with
+        SkSurfaceProps::InitType settings, which choose the pixel striping
+        direction and order. Since a platform may dynamically change its direction when
+        the device is rotated, and since a platform may have multiple monitors with
+        different characteristics, it is best not to rely on this legacy behavior.
+
+        @param width   zero or greater
+        @param height  zero or greater
+        @param props   LCD striping orientation and setting for device independent fonts;
+                       may be nullptr
+        @return        SkCanvas placeholder with dimensions
+    */
+    SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
+
+    /** Deprecated.
+    */
+    explicit SkCanvas(sk_sp<SkBaseDevice> device);
+
+    /** Constructs a canvas that draws into bitmap.
+        Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed SkSurface.
+
+        SkBitmap is copied so that subsequently editing bitmap will not affect
+        constructed SkCanvas.
+
+        May be deprecated in the future.
+
+        @param bitmap  width, height, SkColorType, SkAlphaType, and pixel
+                       storage of raster surface
+        @return        SkCanvas that can be used to draw into bitmap
+    */
+    explicit SkCanvas(const SkBitmap& bitmap);
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    /** Private.
+     */
+    enum class ColorBehavior {
+        kLegacy, //!< placeholder
+    };
+
+    /** Private. For use by Android framework only.
+
+        @param bitmap    specifies a bitmap for the canvas to draw into
+        @param behavior  specializes this constructor; value is unused
+        @return          SkCanvas that can be used to draw into bitmap
+    */
+    SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
+#endif
+
+    /** Constructs a canvas that draws into bitmap.
+        Use props to match the device characteristics, like LCD striping.
+
+        bitmap is copied so that subsequently editing bitmap will not affect
+        constructed SkCanvas.
+
+        @param bitmap  width, height, SkColorType, SkAlphaType,
+                       and pixel storage of raster surface
+        @param props   order and orientation of RGB striping; and whether to use
+                       device independent fonts
+        @return        SkCanvas that can be used to draw into bitmap
+    */
+    SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
+
+    /** Draws saved layers, if any.
+        Frees up resources used by SkCanvas.
+    */
+    virtual ~SkCanvas();
+
+    /** Returns storage to associate additional data with the canvas.
+        The storage is freed when SkCanvas is deleted.
+
+        @return  storage that can be read from and written to
+    */
+    SkMetaData& getMetaData();
+
+    /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or
+        GPU surface, returned SkColorType is set to kUnknown_SkColorType.
+
+        @return  dimensions and SkColorType of SkCanvas
+    */
+    SkImageInfo imageInfo() const;
+
+    /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or
+        GPU surface, and returns true. Otherwise, returns false and leave props unchanged.
+
+        @param props  storage for writable SkSurfaceProps
+        @return       true if SkSurfaceProps was copied
+    */
+    bool getProps(SkSurfaceProps* props) const;
+
+    /** Triggers the immediate execution of all pending draw operations.
+        If SkCanvas is associated with GPU surface, resolves all pending GPU operations.
+        If SkCanvas is associated with raster surface, has no effect; raster draw
+        operations are never deferred.
+    */
+    void flush();
+
+    /** Gets the size of the base or root layer in global canvas coordinates. The
+        origin of the base layer is always (0,0). The area available for drawing may be
+        smaller (due to clipping or saveLayer).
+
+        @return  integral width and height of base layer
+    */
+    virtual SkISize getBaseLayerSize() const;
+
+    /** Creates SkSurface matching info and props, and associates it with SkCanvas.
+        Returns nullptr if no match found.
+
+        If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas
+        does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps.
+
+        @param info   width, height, SkColorType, SkAlphaType, and SkColorSpace
+        @param props  SkSurfaceProps to match; may be nullptr to match SkCanvas
+        @return       SkSurface matching info and props, or nullptr if no match is available
+    */
+    sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
+
+    /** Returns GPU context of the GPU surface associated with SkCanvas.
+
+        @return  GPU context, if available; nullptr otherwise
+    */
+    virtual GrContext* getGrContext();
+
+    /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels
+        can be read directly. The returned address is only valid
+        while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call
+        may invalidate the returned address and other returned values.
+
+        If pixels are inaccessible, info, rowBytes, and origin are unchanged.
+
+        @param info      storage for writable pixels' SkImageInfo; may be nullptr
+        @param rowBytes  storage for writable pixels' row bytes; may be nullptr
+        @param origin    storage for SkCanvas top layer origin, its top-left corner;
+                         may be nullptr
+        @return          address of pixels, or nullptr if inaccessible
+    */
+    void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);
+
+    /** Returns custom context that tracks the SkMatrix and clip.
+
+        Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed
+        by the host platform user interface. The custom context returned is generated by
+        SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
+        the drawing destination.
+
+        @return  context of custom allocation
+    */
+    SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
+
+    /** Returns true if SkCanvas has direct access to its pixels.
+
+        Pixels are readable when SkBaseDevice is raster. Pixels are not readable when SkCanvas
+        is returned from GPU surface, returned by SkDocument::beginPage, returned by
+        SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class
+        like SkDebugCanvas.
+
+        pixmap is valid only while SkCanvas is in scope and unchanged. Any
+        SkCanvas or SkSurface call may invalidate the pixmap values.
+
+        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
+        @return        true if SkCanvas has direct access to pixels
+    */
+    bool peekPixels(SkPixmap* pixmap);
+
+    /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are
+        ignored.
+
+        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+        Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
+        Copies each readable pixel intersecting both rectangles, without scaling,
+        converting to dstInfo.colorType() and dstInfo.alphaType() if required.
+
+        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+        class like SkDebugCanvas.
+
+        The destination pixel storage must be allocated by the caller.
+
+        Pixel values are converted only if SkColorType and SkAlphaType
+        do not match. Only pixels within both source and destination rectangles
+        are copied. dstPixels contents outside SkRect intersection are unchanged.
+
+        Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+        Does not copy, and returns false if:
+        - Source and destination rectangles do not intersect.
+        - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().
+        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+        - dstRowBytes is too small to contain one row of pixels.
+
+        @param dstInfo      width, height, SkColorType, and SkAlphaType of dstPixels
+        @param dstPixels    storage for pixels; dstInfo.height() times dstRowBytes, or larger
+        @param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger
+        @param srcX         offset into readable pixels on x-axis; may be negative
+        @param srcY         offset into readable pixels on y-axis; may be negative
+        @return             true if pixels were copied
+    */
+    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+                    int srcX, int srcY);
+
+    /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are
+        ignored.
+
+        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+        Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()).
+        Copies each readable pixel intersecting both rectangles, without scaling,
+        converting to pixmap.colorType() and pixmap.alphaType() if required.
+
+        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+        class like SkDebugCanvas.
+
+        Caller must allocate pixel storage in pixmap if needed.
+
+        Pixel values are converted only if SkColorType and SkAlphaType
+        do not match. Only pixels within both source and destination SkRect
+        are copied. pixmap pixels contents outside SkRect intersection are unchanged.
+
+        Pass negative values for srcX or srcY to offset pixels across or down pixmap.
+
+        Does not copy, and returns false if:
+        - Source and destination rectangles do not intersect.
+        - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType().
+        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+        - SkPixmap pixels could not be allocated.
+        - pixmap.rowBytes() is too small to contain one row of pixels.
+
+        @param pixmap  storage for pixels copied from SkCanvas
+        @param srcX    offset into readable pixels on x-axis; may be negative
+        @param srcY    offset into readable pixels on y-axis; may be negative
+        @return        true if pixels were copied
+    */
+    bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
+
+    /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are
+        ignored.
+
+        Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+        Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+        Copies each readable pixel intersecting both rectangles, without scaling,
+        converting to bitmap.colorType() and bitmap.alphaType() if required.
+
+        Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+        Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+        class like SkDebugCanvas.
+
+        Caller must allocate pixel storage in bitmap if needed.
+
+        SkBitmap values are converted only if SkColorType and SkAlphaType
+        do not match. Only pixels within both source and destination rectangles
+        are copied. SkBitmap pixels outside SkRect intersection are unchanged.
+
+        Pass negative values for srcX or srcY to offset pixels across or down bitmap.
+
+        Does not copy, and returns false if:
+        - Source and destination rectangles do not intersect.
+        - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType().
+        - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+        - bitmap pixels could not be allocated.
+        - bitmap.rowBytes() is too small to contain one row of pixels.
+
+        @param bitmap  storage for pixels copied from SkCanvas
+        @param srcX    offset into readable pixels on x-axis; may be negative
+        @param srcY    offset into readable pixels on y-axis; may be negative
+        @return        true if pixels were copied
+    */
+    bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
+
+    /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+        Source SkRect corners are (0, 0) and (info.width(), info.height()).
+        Destination SkRect corners are (x, y) and
+        (imageInfo().width(), imageInfo().height()).
+
+        Copies each readable pixel intersecting both rectangles, without scaling,
+        converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+        Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+        Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+        class like SkDebugCanvas.
+
+        Pixel values are converted only if SkColorType and SkAlphaType
+        do not match. Only pixels within both source and destination rectangles
+        are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+        Pass negative values for x or y to offset pixels to the left or
+        above SkCanvas pixels.
+
+        Does not copy, and returns false if:
+        - Source and destination rectangles do not intersect.
+        - pixels could not be converted to SkCanvas imageInfo().colorType() or
+        imageInfo().alphaType().
+        - SkCanvas pixels are not writable; for instance, SkCanvas is document-based.
+        - rowBytes is too small to contain one row of pixels.
+
+        @param info      width, height, SkColorType, and SkAlphaType of pixels
+        @param pixels    pixels to copy, of size info.height() times rowBytes, or larger
+        @param rowBytes  size of one row of pixels; info.width() times pixel size, or larger
+        @param x         offset into SkCanvas writable pixels on x-axis; may be negative
+        @param y         offset into SkCanvas writable pixels on y-axis; may be negative
+        @return          true if pixels were written to SkCanvas
+    */
+    bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
+
+    /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+        Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+
+        Destination SkRect corners are (x, y) and
+        (imageInfo().width(), imageInfo().height()).
+
+        Copies each readable pixel intersecting both rectangles, without scaling,
+        converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+        Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+        Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+        returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+        class like SkDebugCanvas.
+
+        Pixel values are converted only if SkColorType and SkAlphaType
+        do not match. Only pixels within both source and destination rectangles
+        are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+        Pass negative values for x or y to offset pixels to the left or
+        above SkCanvas pixels.
+
+        Does not copy, and returns false if:
+        - Source and destination rectangles do not intersect.
+        - bitmap does not have allocated pixels.
+        - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or
+        imageInfo().alphaType().
+        - SkCanvas pixels are not writable; for instance, SkCanvas is document based.
+        - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.
+
+        @param bitmap  contains pixels copied to SkCanvas
+        @param x       offset into SkCanvas writable pixels on x-axis; may be negative
+        @param y       offset into SkCanvas writable pixels on y-axis; may be negative
+        @return        true if pixels were written to SkCanvas
+    */
+    bool writePixels(const SkBitmap& bitmap, int x, int y);
+
+    /** Saves SkMatrix and clip.
+        Calling restore() discards changes to SkMatrix and clip,
+        restoring the SkMatrix and clip to their state when save() was called.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(),
+        and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion().
+
+        Saved SkCanvas state is put on a stack; multiple calls to save() should be balance
+        by an equal number of calls to restore().
+
+        Call restoreToCount() with result to restore this and subsequent saves.
+
+        @return  depth of saved stack
+    */
+    int save();
+
+    /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+        Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+        clipPath(), clipRegion().
+
+        SkRect bounds suggests but does not define the SkBitmap size. To clip drawing to
+        a specific rectangle, use clipRect().
+
+        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+        SkBlendMode when restore() is called.
+
+        Call restoreToCount() with returned value to restore this and subsequent saves.
+
+        @param bounds  hint to limit the size of the layer; may be nullptr
+        @param paint   graphics state for layer; may be nullptr
+        @return        depth of saved stack
+    */
+    int saveLayer(const SkRect* bounds, const SkPaint* paint);
+
+    /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+        Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+        clipPath(), clipRegion().
+
+        SkRect bounds suggests but does not define the layer size. To clip drawing to
+        a specific rectangle, use clipRect().
+
+        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+        SkBlendMode when restore() is called.
+
+        Call restoreToCount() with returned value to restore this and subsequent saves.
+
+        @param bounds  hint to limit the size of layer; may be nullptr
+        @param paint   graphics state for layer; may be nullptr
+        @return        depth of saved stack
+    */
+    int saveLayer(const SkRect& bounds, const SkPaint* paint) {
+        return this->saveLayer(&bounds, paint);
+    }
+
+    /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+        LCD text is preserved when the layer is drawn to the prior layer.
+
+        Calling restore() discards changes to SkMatrix and clip, and draws layer.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+        clipPath(), clipRegion().
+
+        SkRect bounds suggests but does not define the layer size. To clip drawing to
+        a specific rectangle, use clipRect().
+
+        Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+        SkBlendMode when restore() is called.
+
+        Call restoreToCount() with returned value to restore this and subsequent saves.
+
+        Draw text on an opaque background so that LCD text blends correctly with the
+        prior layer. LCD text drawn on a background with transparency may result in
+        incorrect blending.
+
+        @param bounds  hint to limit the size of layer; may be nullptr
+        @param paint   graphics state for layer; may be nullptr
+        @return        depth of saved stack
+    */
+    int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
+
+    /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+        Calling restore() discards changes to SkMatrix and clip,
+        and blends layer with alpha opacity onto prior layer.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+        clipPath(), clipRegion().
+
+        SkRect bounds suggests but does not define layer size. To clip drawing to
+        a specific rectangle, use clipRect().
+
+        alpha of zero is fully transparent, 255 is fully opaque.
+
+        Call restoreToCount() with returned value to restore this and subsequent saves.
+
+        @param bounds  hint to limit the size of layer; may be nullptr
+        @param alpha   opacity of layer
+        @return        depth of saved stack
+    */
+    int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
+
+    /** \enum SkCanvas::SaveLayerFlagsSet
+        SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
+        defining how layer allocated by saveLayer() operates. It may be set to zero,
+        kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
+    */
+    enum SaveLayerFlagsSet {
+        kPreserveLCDText_SaveLayerFlag  = 1 << 1, //!< creates layer for LCD text
+        kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents
+        kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag =
+                                          1 << 3, //!< experimental: do not use
+
+#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
+        kDontClipToLayer_Legacy_SaveLayerFlag =
+           kDontClipToLayer_PrivateSaveLayerFlag, //!< deprecated
+#endif
+    };
+
+    typedef uint32_t SaveLayerFlags;
+
+    /** \struct SkCanvas::SaveLayerRec
+        SaveLayerRec contains the state used to create the layer.
+    */
+    struct SaveLayerRec {
+
+        /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
+
+            @return  empty SaveLayerRec
+        */
+        SaveLayerRec() {}
+
+        /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
+
+            @param bounds          layer dimensions; may be nullptr
+            @param paint           applied to layer when overlaying prior layer; may be nullptr
+            @param saveLayerFlags  SaveLayerRec options to modify layer
+            @return                SaveLayerRec with empty fBackdrop
+        */
+        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
+            : fBounds(bounds)
+            , fPaint(paint)
+            , fSaveLayerFlags(saveLayerFlags)
+        {}
+
+        /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
+
+            @param bounds          layer dimensions; may be nullptr
+            @param paint           applied to layer when overlaying prior layer;
+                                   may be nullptr
+            @param backdrop        prior layer copied with SkImageFilter; may be nullptr
+            @param saveLayerFlags  SaveLayerRec options to modify layer
+            @return                SaveLayerRec fully specified
+        */
+        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+                     SaveLayerFlags saveLayerFlags)
+            : fBounds(bounds)
+            , fPaint(paint)
+            , fBackdrop(backdrop)
+            , fSaveLayerFlags(saveLayerFlags)
+        {}
+
+        /** Experimental. Not ready for general use.
+            Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
+            clipMatrix uses alpha channel of image, transformed by clipMatrix, to clip
+            layer when drawn to SkCanvas.
+
+            Implementation is not complete; has no effect if SkBaseDevice is GPU-backed.
+
+            @param bounds          layer dimensions; may be nullptr
+            @param paint           graphics state applied to layer when overlaying prior
+                                   layer; may be nullptr
+            @param backdrop        prior layer copied with SkImageFilter;
+                                   may be nullptr
+            @param clipMask        clip applied to layer; may be nullptr
+            @param clipMatrix      matrix applied to clipMask; may be nullptr to use
+                                   identity matrix
+            @param saveLayerFlags  SaveLayerRec options to modify layer
+            @return                SaveLayerRec fully specified
+        */
+        SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+                     const SkImage* clipMask, const SkMatrix* clipMatrix,
+                     SaveLayerFlags saveLayerFlags)
+            : fBounds(bounds)
+            , fPaint(paint)
+            , fBackdrop(backdrop)
+            , fClipMask(clipMask)
+            , fClipMatrix(clipMatrix)
+            , fSaveLayerFlags(saveLayerFlags)
+        {}
+
+        /** hints at layer size limit */
+        const SkRect*        fBounds         = nullptr;
+
+        /** modifies overlay */
+        const SkPaint*       fPaint          = nullptr;
+
+        /** applies SkImageFilter to prior layer */
+        const SkImageFilter* fBackdrop       = nullptr;
+
+        /** clips layer with mask alpha */
+        const SkImage*       fClipMask       = nullptr;
+
+        /** transforms mask alpha used to clip */
+        const SkMatrix*      fClipMatrix     = nullptr;
+
+        /** preserves LCD text, creates with prior layer contents */
+        SaveLayerFlags       fSaveLayerFlags = 0;
+    };
+
+    /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+        Calling restore() discards changes to SkMatrix and clip,
+        and blends SkBitmap with alpha opacity onto the prior layer.
+
+        SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+        setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+        clipPath(), clipRegion().
+
+        SaveLayerRec contains the state used to create the layer.
+
+        Call restoreToCount() with returned value to restore this and subsequent saves.
+
+        @param layerRec  layer state
+        @return          depth of save state stack
+    */
+    int saveLayer(const SaveLayerRec& layerRec);
+
+    /** Removes changes to SkMatrix and clip since SkCanvas state was
+        last saved. The state is removed from the stack.
+
+        Does nothing if the stack is empty.
+    */
+    void restore();
+
+    /** Returns the number of saved states, each containing: SkMatrix and clip.
+        Equals the number of save() calls less the number of restore() calls plus one.
+        The save count of a new canvas is one.
+
+        @return  depth of save state stack
+    */
+    int getSaveCount() const;
+
+    /** Restores state to SkMatrix and clip values when save(), saveLayer(),
+        saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount.
+
+        Does nothing if saveCount is greater than state stack count.
+        Restores state to initial values if saveCount is less than or equal to one.
+
+        @param saveCount  depth of state stack to restore
+    */
+    void restoreToCount(int saveCount);
+
+    /** Translates SkMatrix by dx along the x-axis and dy along the y-axis.
+
+        Mathematically, replaces SkMatrix with a translation matrix
+        premultiplied with SkMatrix.
+
+        This has the effect of moving the drawing by (dx, dy) before transforming
+        the result with SkMatrix.
+
+        @param dx  distance to translate on x-axis
+        @param dy  distance to translate on y-axis
+    */
+    void translate(SkScalar dx, SkScalar dy);
+
+    /** Scales SkMatrix by sx on the x-axis and sy on the y-axis.
+
+        Mathematically, replaces SkMatrix with a scale matrix
+        premultiplied with SkMatrix.
+
+        This has the effect of scaling the drawing by (sx, sy) before transforming
+        the result with SkMatrix.
+
+        @param sx  amount to scale on x-axis
+        @param sy  amount to scale on y-axis
+    */
+    void scale(SkScalar sx, SkScalar sy);
+
+    /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise.
+
+        Mathematically, replaces SkMatrix with a rotation matrix
+        premultiplied with SkMatrix.
+
+        This has the effect of rotating the drawing by degrees before transforming
+        the result with SkMatrix.
+
+        @param degrees  amount to rotate, in degrees
+    */
+    void rotate(SkScalar degrees);
+
+    /** Rotates SkMatrix by degrees about a point at (px, py). Positive degrees rotates
+        clockwise.
+
+        Mathematically, constructs a rotation matrix; premultiplies the rotation matrix by
+        a translation matrix; then replaces SkMatrix with the resulting matrix
+        premultiplied with SkMatrix.
+
+        This has the effect of rotating the drawing about a given point before
+        transforming the result with SkMatrix.
+
+        @param degrees  amount to rotate, in degrees
+        @param px       x-axis value of the point to rotate about
+        @param py       y-axis value of the point to rotate about
+    */
+    void rotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+    /** Skews SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx
+        skews the drawing right as y-axis values increase; a positive value of sy skews
+        the drawing down as x-axis values increase.
+
+        Mathematically, replaces SkMatrix with a skew matrix premultiplied with SkMatrix.
+
+        This has the effect of skewing the drawing by (sx, sy) before transforming
+        the result with SkMatrix.
+
+        @param sx  amount to skew on x-axis
+        @param sy  amount to skew on y-axis
+    */
+    void skew(SkScalar sx, SkScalar sy);
+
+    /** Replaces SkMatrix with matrix premultiplied with existing SkMatrix.
+
+        This has the effect of transforming the drawn geometry by matrix, before
+        transforming the result with existing SkMatrix.
+
+        @param matrix  matrix to premultiply with existing SkMatrix
+    */
+    void concat(const SkMatrix& matrix);
+
+    /** Replaces SkMatrix with matrix.
+        Unlike concat(), any prior matrix state is overwritten.
+
+        @param matrix  matrix to copy, replacing existing SkMatrix
+    */
+    void setMatrix(const SkMatrix& matrix);
+
+    /** Sets SkMatrix to the identity matrix.
+        Any prior matrix state is overwritten.
+    */
+    void resetMatrix();
+
+    /** Replaces clip with the intersection or difference of clip and rect,
+        with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix
+        before it is combined with clip.
+
+        @param rect         SkRect to combine with clip
+        @param op           SkClipOp to apply to clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
+
+    /** Replaces clip with the intersection or difference of clip and rect.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        rect is transformed by SkMatrix before it is combined with clip.
+
+        @param rect  SkRect to combine with clip
+        @param op    SkClipOp to apply to clip
+    */
+    void clipRect(const SkRect& rect, SkClipOp op) {
+        this->clipRect(rect, op, false);
+    }
+
+    /** Replaces clip with the intersection of clip and rect.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        rect is transformed by SkMatrix
+        before it is combined with clip.
+
+        @param rect         SkRect to combine with clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipRect(const SkRect& rect, bool doAntiAlias = false) {
+        this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);
+    }
+
+    /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and
+        clipPath() and intersect the current clip with the specified rect.
+        The maximum clip affects only future clipping operations; it is not retroactive.
+        The clip restriction is not recorded in pictures.
+
+        Pass an empty rect to disable maximum clip.
+        This private API is for use by Android framework only.
+
+        @param rect  maximum allowed clip in device coordinates
+    */
+    void androidFramework_setDeviceClipRestriction(const SkIRect& rect);
+
+    /** Replaces clip with the intersection or difference of clip and rrect,
+        with an aliased or anti-aliased clip edge.
+        rrect is transformed by SkMatrix
+        before it is combined with clip.
+
+        @param rrect        SkRRect to combine with clip
+        @param op           SkClipOp to apply to clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
+
+    /** Replaces clip with the intersection or difference of clip and rrect.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        rrect is transformed by SkMatrix before it is combined with clip.
+
+        @param rrect  SkRRect to combine with clip
+        @param op     SkClipOp to apply to clip
+    */
+    void clipRRect(const SkRRect& rrect, SkClipOp op) {
+        this->clipRRect(rrect, op, false);
+    }
+
+    /** Replaces clip with the intersection of clip and rrect,
+        with an aliased or anti-aliased clip edge.
+        rrect is transformed by SkMatrix before it is combined with clip.
+
+        @param rrect        SkRRect to combine with clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
+        this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);
+    }
+
+    /** Replaces clip with the intersection or difference of clip and path,
+        with an aliased or anti-aliased clip edge. SkPath::FillType determines if path
+        describes the area inside or outside its contours; and if path contour overlaps
+        itself or another path contour, whether the overlaps form part of the area.
+        path is transformed by SkMatrix before it is combined with clip.
+
+        @param path         SkPath to combine with clip
+        @param op           SkClipOp to apply to clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
+
+    /** Replaces clip with the intersection or difference of clip and path.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        SkPath::FillType determines if path
+        describes the area inside or outside its contours; and if path contour overlaps
+        itself or another path contour, whether the overlaps form part of the area.
+        path is transformed by SkMatrix
+        before it is combined with clip.
+
+        @param path  SkPath to combine with clip
+        @param op    SkClipOp to apply to clip
+    */
+    void clipPath(const SkPath& path, SkClipOp op) {
+        this->clipPath(path, op, false);
+    }
+
+    /** Replaces clip with the intersection of clip and path.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        SkPath::FillType determines if path
+        describes the area inside or outside its contours; and if path contour overlaps
+        itself or another path contour, whether the overlaps form part of the area.
+        path is transformed by SkMatrix before it is combined with clip.
+
+        @param path         SkPath to combine with clip
+        @param doAntiAlias  true if clip is to be anti-aliased
+    */
+    void clipPath(const SkPath& path, bool doAntiAlias = false) {
+        this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);
+    }
+
+    /** Experimental. For testing only.
+        Set to simplify clip stack using PathOps.
+    */
+    void setAllowSimplifyClip(bool allow) {
+        fAllowSimplifyClip = allow;
+    }
+
+    /** Replaces clip with the intersection or difference of clip and SkRegion deviceRgn.
+        Resulting clip is aliased; pixels are fully contained by the clip.
+        deviceRgn is unaffected by SkMatrix.
+
+        @param deviceRgn  SkRegion to combine with clip
+        @param op         SkClipOp to apply to clip
+    */
+    void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
+
+    /** Returns true if SkRect rect, transformed by SkMatrix, can be quickly determined to be
+        outside of clip. May return false even though rect is outside of clip.
+
+        Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+        @param rect  SkRect to compare with clip
+        @return      true if rect, transformed by SkMatrix, does not intersect clip
+    */
+    bool quickReject(const SkRect& rect) const;
+
+    /** Returns true if path, transformed by SkMatrix, can be quickly determined to be
+        outside of clip. May return false even though path is outside of clip.
+
+        Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+        @param path  SkPath to compare with clip
+        @return      true if path, transformed by SkMatrix, does not intersect clip
+    */
+    bool quickReject(const SkPath& path) const;
+
+    /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+        return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+        SkRect returned is outset by one to account for partial pixel coverage if clip
+        is anti-aliased.
+
+        @return  bounds of clip in local coordinates
+    */
+    SkRect getLocalClipBounds() const;
+
+    /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+        return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+        bounds is outset by one to account for partial pixel coverage if clip
+        is anti-aliased.
+
+        @param bounds  SkRect of clip in local coordinates
+        @return        true if clip bounds is not empty
+    */
+    bool getLocalClipBounds(SkRect* bounds) const {
+        *bounds = this->getLocalClipBounds();
+        return !bounds->isEmpty();
+    }
+
+    /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+        return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+        Unlike getLocalClipBounds(), returned SkIRect is not outset.
+
+        @return  bounds of clip in SkBaseDevice coordinates
+    */
+    SkIRect getDeviceClipBounds() const;
+
+    /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+        return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+        Unlike getLocalClipBounds(), bounds is not outset.
+
+        @param bounds  SkRect of clip in device coordinates
+        @return        true if clip bounds is not empty
+    */
+    bool getDeviceClipBounds(SkIRect* bounds) const {
+        *bounds = this->getDeviceClipBounds();
+        return !bounds->isEmpty();
+    }
+
+    /** Fills clip with color color.
+        mode determines how ARGB is combined with destination.
+
+        @param color  unpremultiplied ARGB
+        @param mode   SkBlendMode used to combine source color and destination
+    */
+    void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
+
+    /** Fills clip with color color using SkBlendMode::kSrc.
+        This has the effect of replacing all pixels contained by clip with color.
+
+        @param color  unpremultiplied ARGB
+    */
+    void clear(SkColor color) {
+        this->drawColor(color, SkBlendMode::kSrc);
+    }
+
+    /** Makes SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels,
+        such as drawing with SkBlendMode, return undefined results. discard() does
+        not change clip or SkMatrix.
+
+        discard() may do nothing, depending on the implementation of SkSurface or SkBaseDevice
+        that created SkCanvas.
+
+        discard() allows optimized performance on subsequent draws by removing
+        cached data associated with SkSurface or SkBaseDevice.
+        It is not necessary to call discard() once done with SkCanvas;
+        any cached data is deleted when owning SkSurface or SkBaseDevice is deleted.
+    */
+    void discard() { this->onDiscard(); }
+
+    /** Fills clip with SkPaint paint. SkPaint components SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkBlendMode affect drawing;
+        SkPathEffect in paint is ignored.
+
+        @param paint  graphics state used to fill SkCanvas
+    */
+    void drawPaint(const SkPaint& paint);
+
+    /** \enum SkCanvas::PointMode
+        Selects if an array of points are drawn as discrete points, as lines, or as
+        an open polygon.
+    */
+    enum PointMode {
+        kPoints_PointMode,  //!< draw each point separately
+        kLines_PointMode,   //!< draw each pair of points as a line segment
+        kPolygon_PointMode, //!< draw the array of points as a open polygon
+    };
+
+    /** Draws pts using clip, SkMatrix and SkPaint paint.
+        count is the number of points; if count is less than one, has no effect.
+        mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
+
+        If mode is kPoints_PointMode, the shape of point drawn depends on paint
+        SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
+        circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap
+        or SkPaint::kButt_Cap, each point draws a square of width and height
+        SkPaint stroke width.
+
+        If mode is kLines_PointMode, each pair of points draws a line segment.
+        One line is drawn for every two points; each point is used once. If count is odd,
+        the final point is ignored.
+
+        If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
+        count minus one lines are drawn; the first and last point are used once.
+
+        Each line segment respects paint SkPaint::Cap and SkPaint stroke width.
+        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+        Always draws each element one at a time; is not affected by
+        SkPaint::Join, and unlike drawPath(), does not create a mask from all points
+        and lines before drawing.
+
+        @param mode   whether pts draws points or lines
+        @param count  number of points in the array
+        @param pts    array of points to draw
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
+
+    /** Draws point at (x, y) using clip, SkMatrix and SkPaint paint.
+
+        The shape of point drawn depends on paint SkPaint::Cap.
+        If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+        SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+        draw a square of width and height SkPaint stroke width.
+        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+        @param x      left edge of circle or square
+        @param y      top edge of circle or square
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+
+    /** Draws point p using clip, SkMatrix and SkPaint paint.
+
+        The shape of point drawn depends on paint SkPaint::Cap.
+        If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+        SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+        draw a square of width and height SkPaint stroke width.
+        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+        @param p      top-left edge of circle or square
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawPoint(SkPoint p, const SkPaint& paint) {
+        this->drawPoint(p.x(), p.y(), paint);
+    }
+
+    /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint stroke width describes the line thickness;
+        SkPaint::Cap draws the end rounded or square;
+        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+        @param x0     start of line segment on x-axis
+        @param y0     start of line segment on y-axis
+        @param x1     end of line segment on x-axis
+        @param y1     end of line segment on y-axis
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
+
+    /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint stroke width describes the line thickness;
+        SkPaint::Cap draws the end rounded or square;
+        SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+        @param p0     start of line segment
+        @param p1     end of line segment
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {
+        this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);
+    }
+
+    /** Draws SkRect rect using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint::Style determines if rectangle is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness, and
+        SkPaint::Join draws the corners rounded or square.
+
+        @param rect   rectangle to draw
+        @param paint  stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawRect(const SkRect& rect, const SkPaint& paint);
+
+    /** Draws SkIRect rect using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint::Style determines if rectangle is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness, and
+        SkPaint::Join draws the corners rounded or square.
+
+        @param rect   rectangle to draw
+        @param paint  stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawIRect(const SkIRect& rect, const SkPaint& paint) {
+        SkRect r;
+        r.set(rect);    // promotes the ints to scalars
+        this->drawRect(r, paint);
+    }
+
+    /** Draws SkRegion region using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint::Style determines if rectangle is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness, and
+        SkPaint::Join draws the corners rounded or square.
+
+        @param region  region to draw
+        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawRegion(const SkRegion& region, const SkPaint& paint);
+
+    /** Draws oval oval using clip, SkMatrix, and SkPaint.
+        In paint: SkPaint::Style determines if oval is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+
+        @param oval   SkRect bounds of oval
+        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawOval(const SkRect& oval, const SkPaint& paint);
+
+    /** Draws SkRRect rrect using clip, SkMatrix, and SkPaint paint.
+        In paint: SkPaint::Style determines if rrect is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+
+        rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
+        may have any combination of positive non-square radii for the four corners.
+
+        @param rrect  SkRRect with up to eight corner radii to draw
+        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawRRect(const SkRRect& rrect, const SkPaint& paint);
+
+    /** Draws SkRRect outer and inner
+        using clip, SkMatrix, and SkPaint paint.
+        outer must contain inner or the drawing is undefined.
+        In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+        If stroked and SkRRect corner has zero length radii, SkPaint::Join can
+        draw corners rounded or square.
+
+        GPU-backed platforms optimize drawing when both outer and inner are
+        concave and outer contains inner. These platforms may not be able to draw
+        SkPath built with identical data as fast.
+
+        @param outer  SkRRect outer bounds to draw
+        @param inner  SkRRect inner bounds to draw
+        @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+
+    /** Draws circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint.
+        If radius is zero or less, nothing is drawn.
+        In paint: SkPaint::Style determines if circle is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+
+        @param cx      circle center on the x-axis
+        @param cy      circle center on the y-axis
+        @param radius  half the diameter of circle
+        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
+
+    /** Draws circle at center with radius using clip, SkMatrix, and SkPaint paint.
+        If radius is zero or less, nothing is drawn.
+        In paint: SkPaint::Style determines if circle is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+
+        @param center  circle center
+        @param radius  half the diameter of circle
+        @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {
+        this->drawCircle(center.x(), center.y(), radius, paint);
+    }
+
+    /** Draws arc using clip, SkMatrix, and SkPaint paint.
+
+        Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus
+        sweepAngle. startAngle and sweepAngle are in degrees.
+
+        startAngle of zero places start point at the right middle edge of oval.
+        A positive sweepAngle places arc end point clockwise from start point;
+        a negative sweepAngle places arc end point counterclockwise from start point.
+        sweepAngle may exceed 360 degrees, a full circle.
+        If useCenter is true, draw a wedge that includes lines from oval
+        center to arc end points. If useCenter is false, draw arc between end points.
+
+        If SkRect oval is empty or sweepAngle is zero, nothing is drawn.
+
+        @param oval        SkRect bounds of oval containing arc to draw
+        @param startAngle  angle in degrees where arc begins
+        @param sweepAngle  sweep angle in degrees; positive is clockwise
+        @param useCenter   if true, include the center of the oval
+        @param paint       SkPaint stroke or fill, blend, color, and so on, used to draw
+    */
+    void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+                 bool useCenter, const SkPaint& paint);
+
+    /** Draws SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip,
+        SkMatrix, and SkPaint paint.
+
+        In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+        if stroked, SkPaint stroke width describes the line thickness.
+        If rx or ry are less than zero, they are treated as if they are zero.
+        If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
+        If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by
+        SkPaint::Join.
+
+        @param rect   SkRect bounds of SkRRect to draw
+        @param rx     axis length on x-axis of oval describing rounded corners
+        @param ry     axis length on y-axis of oval describing rounded corners
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
+
+    /** Draws SkPath path using clip, SkMatrix, and SkPaint paint.
+        SkPath contains an array of path contour, each of which may be open or closed.
+
+        In paint: SkPaint::Style determines if SkRRect is stroked or filled:
+        if filled, SkPath::FillType determines whether path contour describes inside or
+        outside of fill; if stroked, SkPaint stroke width describes the line thickness,
+        SkPaint::Cap describes line ends, and SkPaint::Join describes how
+        corners are drawn.
+
+        @param path   SkPath to draw
+        @param paint  stroke, blend, color, and so on, used to draw
+    */
+    void drawPath(const SkPath& path, const SkPaint& paint);
+
+    /** Draws SkImage image, with its top-left corner at (left, top),
+        using clip, SkMatrix, and optional SkPaint paint.
+
+        If paint is supplied, apply SkColorFilter, alpha, SkImageFilter, SkBlendMode,
+        and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds. If generated
+        mask extends beyond image bounds, replicate image edge colors, just as SkShader
+        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
+        image edge color when it samples outside of its bounds.
+
+        @param image  uncompressed rectangular map of pixels
+        @param left   left side of image
+        @param top    top side of image
+        @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                      and so on; or nullptr
+    */
+    void drawImage(const SkImage* image, SkScalar left, SkScalar top,
+                   const SkPaint* paint = nullptr);
+
+    /** Draws SkImage image, with its top-left corner at (left, top),
+        using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds. If generated
+        mask extends beyond image bounds, replicate image edge colors, just as SkShader
+        made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
+        image edge color when it samples outside of its bounds.
+
+        @param image  uncompressed rectangular map of pixels
+        @param left   left side of image
+        @param top    pop side of image
+        @param paint  SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                      and so on; or nullptr
+    */
+    void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
+                   const SkPaint* paint = nullptr) {
+        this->drawImage(image.get(), left, top, paint);
+    }
+
+    /** \enum SkCanvas::SrcRectConstraint
+        SrcRectConstraint controls the behavior at the edge of source SkRect,
+        provided to drawImageRect(), trading off speed for precision.
+
+        SkFilterQuality in SkPaint may sample multiple pixels in the image. Source SkRect
+        restricts the bounds of pixels that may be read. SkFilterQuality may slow down if
+        it cannot read outside the bounds, when sampling near the edge of source SkRect.
+        SrcRectConstraint specifies whether an SkImageFilter is allowed to read pixels
+        outside source SkRect.
+    */
+    enum SrcRectConstraint {
+        kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
+        kFast_SrcRectConstraint,   //!< sample outside bounds; faster
+    };
+
+    /** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within src; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param src         source SkRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within src or draw faster
+    */
+    void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
+                       const SkPaint* paint,
+                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /** Draws SkIRect isrc of SkImage image, scaled and translated to fill SkRect dst.
+        Note that isrc is on integer pixel boundaries; dst may include fractional
+        boundaries. Additionally transform draw using clip, SkMatrix, and optional SkPaint
+        paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param isrc        source SkIRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within isrc or draw faster
+    */
+    void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
+                       const SkPaint* paint,
+                       SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /** Draws SkImage image, scaled and translated to fill SkRect dst, using clip, SkMatrix,
+        and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+    */
+    void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint);
+
+    /** Draws SkRect src of SkImage image, scaled and translated to fill SkRect dst.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param src         source SkRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within src or draw faster
+    */
+    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
+                       const SkPaint* paint,
+                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
+        this->drawImageRect(image.get(), src, dst, paint, constraint);
+    }
+
+    /** Draws SkIRect isrc of SkImage image, scaled and translated to fill SkRect dst.
+        isrc is on integer pixel boundaries; dst may include fractional boundaries.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within image; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param isrc        source SkIRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within image or draw faster
+    */
+    void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
+                       const SkPaint* paint,
+                       SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
+        this->drawImageRect(image.get(), isrc, dst, paint, constraint);
+    }
+
+    /** Draws SkImage image, scaled and translated to fill SkRect dst,
+        using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within image; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param image       SkImage containing pixels, dimensions, and format
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+    */
+    void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint) {
+        this->drawImageRect(image.get(), dst, paint);
+    }
+
+    /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+        SkIRect center divides the image into nine sections: four sides, four corners, and
+        the center. Corners are unmodified or scaled down proportionately if their sides
+        are larger than dst; center and four sides are scaled to fit remaining space, if any.
+
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds. If paint
+        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
+        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
+        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        @param image   SkImage containing pixels, dimensions, and format
+        @param center  SkIRect edge of image corners and sides
+        @param dst     destination SkRect of image to draw to
+        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                       and so on; or nullptr
+    */
+    void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
+                       const SkPaint* paint = nullptr);
+
+    /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+        SkIRect center divides the image into nine sections: four sides, four corners, and
+        the center. Corners are not scaled, or scaled down proportionately if their sides
+        are larger than dst; center and four sides are scaled to fit remaining space, if any.
+
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds. If paint
+        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
+        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
+        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+        If generated mask extends beyond image bounds, replicate image edge colors, just
+        as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+        replicates the image edge color when it samples outside of its bounds.
+
+        @param image   SkImage containing pixels, dimensions, and format
+        @param center  SkIRect edge of image corners and sides
+        @param dst     destination SkRect of image to draw to
+        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                       and so on; or nullptr
+    */
+    void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
+                       const SkPaint* paint = nullptr) {
+        this->drawImageNine(image.get(), center, dst, paint);
+    }
+
+    /** Draws SkBitmap bitmap, with its top-left corner at (left, top),
+        using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is not nullptr, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        @param bitmap  SkBitmap containing pixels, dimensions, and format
+        @param left    left side of bitmap
+        @param top     top side of bitmap
+        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                       and so on; or nullptr
+    */
+    void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
+                    const SkPaint* paint = nullptr);
+
+    /** Draws SkRect src of SkBitmap bitmap, scaled and translated to fill SkRect dst.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within src; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param bitmap      SkBitmap containing pixels, dimensions, and format
+        @param src         source SkRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within src or draw faster
+    */
+    void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
+                        const SkPaint* paint,
+                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /** Draws SkIRect isrc of SkBitmap bitmap, scaled and translated to fill SkRect dst.
+        isrc is on integer pixel boundaries; dst may include fractional boundaries.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param bitmap      SkBitmap containing pixels, dimensions, and format
+        @param isrc        source SkIRect of image to draw from
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  sample strictly within isrc, or draw faster
+    */
+    void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
+                        const SkPaint* paint,
+                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /** Draws SkBitmap bitmap, scaled and translated to fill SkRect dst.
+        bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        constraint set to kStrict_SrcRectConstraint limits SkPaint SkFilterQuality to
+        sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to
+        improve performance.
+
+        @param bitmap      SkBitmap containing pixels, dimensions, and format
+        @param dst         destination SkRect of image to draw to
+        @param paint       SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                           and so on; or nullptr
+        @param constraint  filter strictly within bitmap or draw faster
+    */
+    void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
+                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /** Draws SkBitmap bitmap stretched proportionally to fit into SkRect dst.
+        SkIRect center divides the bitmap into nine sections: four sides, four corners,
+        and the center. Corners are not scaled, or scaled down proportionately if their
+        sides are larger than dst; center and four sides are scaled to fit remaining
+        space, if any.
+
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint
+        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
+        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
+        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        @param bitmap  SkBitmap containing pixels, dimensions, and format
+        @param center  SkIRect edge of image corners and sides
+        @param dst     destination SkRect of image to draw to
+        @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                       and so on; or nullptr
+    */
+    void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
+                        const SkPaint* paint = nullptr);
+
+    /** \struct SkCanvas::Lattice
+        SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid.
+        Grid entries on even columns and even rows are fixed; these entries are
+        always drawn at their original size if the destination is large enough.
+        If the destination side is too small to hold the fixed entries, all fixed
+        entries are proportionately scaled down to fit.
+        The grid entries not on even columns and rows are scaled to fit the
+        remaining space, if any.
+    */
+    struct Lattice {
+
+        /** \enum SkCanvas::Lattice::RectType
+            Optional setting per rectangular grid entry to make it transparent,
+            or to fill the grid entry with a color.
+        */
+        enum RectType : uint8_t {
+            kDefault     = 0, //!< draws SkBitmap into lattice rectangle
+            kTransparent,     //!< skips lattice rectangle by making it transparent
+            kFixedColor,      //!< draws one of fColors into lattice rectangle
+        };
+
+        const int*      fXDivs;     //!< x-axis values dividing bitmap
+        const int*      fYDivs;     //!< y-axis values dividing bitmap
+        const RectType* fRectTypes; //!< array of fill types
+        int             fXCount;    //!< number of x-coordinates
+        int             fYCount;    //!< number of y-coordinates
+        const SkIRect*  fBounds;    //!< source bounds to draw from
+        const SkColor*  fColors;    //!< array of colors
+    };
+
+    /** Draws SkBitmap bitmap stretched proportionally to fit into SkRect dst.
+
+        SkCanvas::Lattice lattice divides bitmap into a rectangular grid.
+        Each intersection of an even-numbered row and column is fixed; like the corners
+        of drawBitmapNine(), fixed lattice elements never scale larger than their initial
+        size and shrink proportionately when all fixed elements exceed the bitmap
+        dimension. All other grid elements scale to fill the available space, if any.
+
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If bitmap is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from bitmap bounds. If paint
+        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
+        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
+        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        @param bitmap   SkBitmap containing pixels, dimensions, and format
+        @param lattice  division of bitmap into fixed and variable rectangles
+        @param dst      destination SkRect of image to draw to
+        @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                        and so on; or nullptr
+    */
+    void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
+                           const SkPaint* paint = nullptr);
+
+    /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+
+        SkCanvas::Lattice lattice divides image into a rectangular grid.
+        Each intersection of an even-numbered row and column is fixed; like the corners
+        of drawBitmapNine(), fixed lattice elements never scale larger than their initial
+        size and shrink proportionately when all fixed elements exceed the bitmap
+        dimension. All other grid elements scale to fill the available space, if any.
+
+        Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+        If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter,
+        SkBlendMode, and SkDrawLooper. If image is kAlpha_8_SkColorType, apply SkShader.
+        If paint contains SkMaskFilter, generate mask from image bounds. If paint
+        SkFilterQuality set to kNone_SkFilterQuality, disable pixel filtering. For all
+        other values of paint SkFilterQuality, use kLow_SkFilterQuality to filter pixels.
+        Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+        If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+        just as SkShader made from SkShader::MakeBitmapShader with
+        SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+        outside of its bounds.
+
+        @param image    SkImage containing pixels, dimensions, and format
+        @param lattice  division of bitmap into fixed and variable rectangles
+        @param dst      destination SkRect of image to draw to
+        @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+                        and so on; or nullptr
+    */
+    void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
+                          const SkPaint* paint = nullptr);
+
+    /**
+     * Experimental. Controls anti-aliasing of each edge of images in an image-set.
+     */
+    enum QuadAAFlags : unsigned {
+        kLeft_QuadAAFlag    = 0b0001,
+        kTop_QuadAAFlag     = 0b0010,
+        kRight_QuadAAFlag   = 0b0100,
+        kBottom_QuadAAFlag  = 0b1000,
+
+        kNone_QuadAAFlags   = 0b0000,
+        kAll_QuadAAFlags    = 0b1111,
+    };
+
+    /** This is used by the experimental API below. */
+    struct ImageSetEntry {
+        sk_sp<const SkImage> fImage;
+        SkRect fSrcRect;
+        SkRect fDstRect;
+        float fAlpha;
+        unsigned fAAFlags;  // QuadAAFlags
+    };
+
+    /**
+     * This is an experimental API for the SkiaRenderer Chromium project. The signature will
+     * surely evolve if this is not removed. It currently offers no performance advantage over
+     * drawing images independently, though may in the future. The antialiasing flags are intended
+     * to allow control over each edge's AA status, to allow perfect seaming for tile sets. The
+     * current implementation only antialiases if all edges are flagged, however.
+     * Results are undefined if an image's src rect is not within the image's bounds.
+     */
+    void experimental_DrawImageSetV1(const ImageSetEntry imageSet[], int cnt,
+                                     SkFilterQuality quality, SkBlendMode mode);
+
+    /** Draws text, with origin at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
+        UTF-8.
+
+        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
+        text draws left to right, positioning the first glyph left side bearing at x
+        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        @param text        character code points or glyphs drawn
+        @param byteLength  byte length of text array
+        @param x           start of text on x-axis
+        @param y           start of text on y-axis
+        @param paint       text size, blend, color, and so on, used to draw
+    */
+    void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+                  const SkPaint& paint);
+
+    // Experimental
+    void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                        SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
+    /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
+        SkPaint paint.
+
+        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded
+        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired
+        results, since zero bytes may be embedded in the string.
+
+        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
+        string draws left to right, positioning the first glyph left side bearing at x
+        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        @param string  character code points or glyphs drawn,
+                       ending with a char value of zero
+        @param x       start of string on x-axis
+        @param y       start of string on y-axis
+        @param paint   text size, blend, color, and so on, used to draw
+    */
+    void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint) {
+        if (!string) {
+            return;
+        }
+        this->drawText(string, strlen(string), x, y, paint);
+    }
+
+    /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix, and
+        SkPaint paint.
+
+        string meaning depends on SkPaint::TextEncoding; by default, strings are encoded
+        as UTF-8. Other values of SkPaint::TextEncoding are unlikely to produce the desired
+        results, since zero bytes may be embedded in the string.
+
+        x and y meaning depends on SkPaint::Align and SkPaint vertical text; by default
+        string draws left to right, positioning the first glyph left side bearing at x
+        and its baseline at y. Text size is affected by SkMatrix and SkPaint text size.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        @param string  character code points or glyphs drawn,
+                       ending with a char value of zero
+        @param x       start of string on x-axis
+        @param y       start of string on y-axis
+        @param paint   text size, blend, color, and so on, used to draw
+    */
+    void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint);
+
+    /** Draws each glyph in text with the origin in pos array, using clip, SkMatrix, and
+        SkPaint paint. The number of entries in pos array must match the number of glyphs
+        described by byteLength of text.
+
+        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
+        UTF-8. pos elements meaning depends on SkPaint vertical text; by default
+        glyph left side bearing and baseline are relative to SkPoint in pos array.
+        Text size is affected by SkMatrix and SkPaint text size.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        Layout engines such as Harfbuzz typically position each glyph
+        rather than using the font advance widths.
+
+        @param text        character code points or glyphs drawn
+        @param byteLength  byte length of text array
+        @param pos         array of glyph origins
+        @param paint       text size, blend, color, and so on, used to draw
+    */
+    void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+                     const SkPaint& paint);
+
+    /** Draws each glyph in text with its origin composed from xpos array and
+        constY, using clip, SkMatrix, and SkPaint paint. The number of entries in xpos array
+        must match the number of glyphs described by byteLength of text.
+
+        text meaning depends on SkPaint::TextEncoding; by default, text is encoded as
+        UTF-8. xpos elements meaning depends on SkPaint vertical text;
+        by default each glyph left side bearing is positioned at an xpos element and
+        its baseline is positioned at constY. Text size is affected by SkMatrix and
+        SkPaint text size.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        Layout engines such as Harfbuzz typically position each glyph
+        rather than using the font advance widths if all glyphs share the same
+        baseline.
+
+        @param text        character code points or glyphs drawn
+        @param byteLength  byte length of text array
+        @param xpos        array of x-axis positions, used to position each glyph
+        @param constY      shared y-axis value for all of x-axis positions
+        @param paint       text size, blend, color, and so on, used to draw
+    */
+    void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
+                      const SkPaint& paint);
+
+    /** Draws text, transforming each glyph by the corresponding SkRSXform,
+        using clip, SkMatrix, and SkPaint paint.
+
+        SkRSXform xform array specifies a separate square scale, rotation, and translation
+        for each glyph. xform does not affect paint SkShader.
+
+        Optional SkRect cullRect is a conservative bounds of text, taking into account
+        SkRSXform and paint. If cullRect is outside of clip, canvas can skip drawing.
+
+        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+        SkColorFilter, SkImageFilter, and SkDrawLooper; apply to text. By default, draws
+        filled 12 point black glyphs.
+
+        @param text        character code points or glyphs drawn
+        @param byteLength  byte length of text array
+        @param xform       SkRSXform rotates, scales, and translates each glyph individually
+        @param cullRect    SkRect bounds of text for efficient clipping; or nullptr
+        @param paint       text size, blend, color, and so on, used to draw
+    */
+    void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+                         const SkRect* cullRect, const SkPaint& paint);
+
+    /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+        blob contains glyphs, their positions, and paint attributes specific to text:
+        SkTypeface, SkPaint text size, SkPaint text scale x,
+        SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+        SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+        and SkPaint subpixel text.
+
+        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
+
+        Elements of paint: anti-alias, SkBlendMode, color including alpha,
+        SkColorFilter, SkPaint dither, SkDrawLooper, SkMaskFilter, SkPathEffect, SkShader, and
+        SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
+        SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
+        apply to SkPath created from blob.
+
+        @param blob   glyphs, positions, and their paints' text size, typeface, and so on
+        @param x      horizontal offset applied to blob
+        @param y      vertical offset applied to blob
+        @param paint  blend, color, stroking, and so on, used to draw
+    */
+    void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+    /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+        blob contains glyphs, their positions, and paint attributes specific to text:
+        SkTypeface, SkPaint text size, SkPaint text scale x,
+        SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+        SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+        and SkPaint subpixel text.
+
+        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
+
+        Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
+        SkImageFilter, and SkDrawLooper; apply to blob.
+
+        @param blob   glyphs, positions, and their paints' text size, typeface, and so on
+        @param x      horizontal offset applied to blob
+        @param y      vertical offset applied to blob
+        @param paint  blend, color, stroking, and so on, used to draw
+    */
+    void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
+        this->drawTextBlob(blob.get(), x, y, paint);
+    }
+
+    /** Draws SkPicture picture, using clip and SkMatrix.
+        Clip and SkMatrix are unchanged by picture contents, as if
+        save() was called before and restore() was called after drawPicture().
+
+        SkPicture records a series of draw commands for later playback.
+
+        @param picture  recorded drawing commands to play
+    */
+    void drawPicture(const SkPicture* picture) {
+        this->drawPicture(picture, nullptr, nullptr);
+    }
+
+    /** Draws SkPicture picture, using clip and SkMatrix.
+        Clip and SkMatrix are unchanged by picture contents, as if
+        save() was called before and restore() was called after drawPicture().
+
+        SkPicture records a series of draw commands for later playback.
+
+        @param picture  recorded drawing commands to play
+    */
+    void drawPicture(const sk_sp<SkPicture>& picture) {
+        this->drawPicture(picture.get());
+    }
+
+    /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+        SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+        SkImageFilter, and SkBlendMode, if provided.
+
+        matrix transformation is equivalent to: save(), concat(), drawPicture(), restore().
+        paint use is equivalent to: saveLayer(), drawPicture(), restore().
+
+        @param picture  recorded drawing commands to play
+        @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr
+        @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr
+    */
+    void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
+
+    /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+        SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+        SkImageFilter, and SkBlendMode, if provided.
+
+        matrix transformation is equivalent to: save(), concat(), drawPicture(), restore().
+        paint use is equivalent to: saveLayer(), drawPicture(), restore().
+
+        @param picture  recorded drawing commands to play
+        @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr
+        @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr
+    */
+    void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix,
+                     const SkPaint* paint) {
+        this->drawPicture(picture.get(), matrix, paint);
+    }
+
+    /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+        If vertices texs and vertices colors are defined in vertices, and SkPaint paint
+        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+
+        @param vertices  triangle mesh to draw
+        @param mode      combines vertices colors with SkShader, if both are present
+        @param paint     specifies the SkShader, used as SkVertices texture; may be nullptr
+    */
+    void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
+
+    /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+        If vertices texs and vertices colors are defined in vertices, and SkPaint paint
+        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+
+        @param vertices  triangle mesh to draw
+        @param mode      combines vertices colors with SkShader, if both are present
+        @param paint     specifies the SkShader, used as SkVertices texture, may be nullptr
+    */
+    void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
+
+    /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix. Bone data is used to
+        deform vertices with bone weights.
+        If vertices texs and vertices colors are defined in vertices, and SkPaint paint
+        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+        The first element of bones should be an object to world space transformation matrix that
+        will be applied before performing mesh deformations. If no such transformation is needed,
+        it should be the identity matrix.
+        boneCount must be at most 80, and thus the size of bones should be at most 80.
+
+        @param vertices   triangle mesh to draw
+        @param bones      bone matrix data
+        @param boneCount  number of bone matrices
+        @param mode       combines vertices colors with SkShader, if both are present
+        @param paint      specifies the SkShader, used as SkVertices texture, may be nullptr
+    */
+    void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[], int boneCount,
+                      SkBlendMode mode, const SkPaint& paint);
+
+    /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix. Bone data is used to
+        deform vertices with bone weights.
+        If vertices texs and vertices colors are defined in vertices, and SkPaint paint
+        contains SkShader, SkBlendMode mode combines vertices colors with SkShader.
+        The first element of bones should be an object to world space transformation matrix that
+        will be applied before performing mesh deformations. If no such transformation is needed,
+        it should be the identity matrix.
+        boneCount must be at most 80, and thus the size of bones should be at most 80.
+
+        @param vertices   triangle mesh to draw
+        @param bones      bone matrix data
+        @param boneCount  number of bone matrices
+        @param mode       combines vertices colors with SkShader, if both are present
+        @param paint      specifies the SkShader, used as SkVertices texture, may be nullptr
+    */
+    void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
+                      int boneCount, SkBlendMode mode, const SkPaint& paint);
+
+    /** Draws a Coons patch: the interpolation of four cubics with shared corners,
+        associating a color, and optionally a texture SkPoint, with each corner.
+
+        Coons patch uses clip and SkMatrix, paint SkShader, SkColorFilter,
+        alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated
+        as Coons patch texture; SkBlendMode mode combines color colors and SkShader if
+        both are provided.
+
+        SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
+        in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
+        first point.
+
+        Color array color associates colors with corners in top-left, top-right,
+        bottom-right, bottom-left order.
+
+        If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
+        corners in top-left, top-right, bottom-right, bottom-left order.
+
+        @param cubics     SkPath cubic array, sharing common points
+        @param colors     color array, one for each corner
+        @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;
+                          may be nullptr
+        @param mode       SkBlendMode for colors, and for SkShader if paint has one
+        @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw
+    */
+    void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                   const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+
+    /** Draws SkPath cubic Coons patch: the interpolation of four cubics with shared corners,
+        associating a color, and optionally a texture SkPoint, with each corner.
+
+        Coons patch uses clip and SkMatrix, paint SkShader, SkColorFilter,
+        alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated
+        as Coons patch texture; SkBlendMode mode combines color colors and SkShader if
+        both are provided.
+
+        SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
+        in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
+        first point.
+
+        Color array color associates colors with corners in top-left, top-right,
+        bottom-right, bottom-left order.
+
+        If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
+        corners in top-left, top-right, bottom-right, bottom-left order.
+
+        @param cubics     SkPath cubic array, sharing common points
+        @param colors     color array, one for each corner
+        @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;
+                          may be nullptr
+        @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw
+    */
+    void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                   const SkPoint texCoords[4], const SkPaint& paint) {
+        this->drawPatch(cubics, colors, texCoords, SkBlendMode::kModulate, paint);
+    }
+
+    /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+        to draw, if present. For each entry in the array, SkRect tex locates sprite in
+        atlas, and SkRSXform xform transforms it into destination space.
+
+        xform, text, and colors if present, must contain count entries.
+        Optional colors are applied for each sprite using SkBlendMode mode, treating
+        sprite as source and colors as destination.
+        Optional cullRect is a conservative bounds of all transformed sprites.
+        If cullRect is outside of clip, canvas can skip drawing.
+
+        @param atlas     SkImage containing sprites
+        @param xform     SkRSXform mappings for sprites in atlas
+        @param tex       SkRect locations of sprites in atlas
+        @param colors    one per sprite, blended with sprite using SkBlendMode; may be nullptr
+        @param count     number of sprites to draw
+        @param mode      SkBlendMode combining colors and sprites
+        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr
+        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+    */
+    void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
+                   const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
+                   const SkPaint* paint);
+
+    /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+        to draw, if present. For each entry in the array, SkRect tex locates sprite in
+        atlas, and SkRSXform xform transforms it into destination space.
+
+        xform, text, and colors if present, must contain count entries.
+        Optional colors is applied for each sprite using SkBlendMode.
+        Optional cullRect is a conservative bounds of all transformed sprites.
+        If cullRect is outside of clip, canvas can skip drawing.
+
+        @param atlas     SkImage containing sprites
+        @param xform     SkRSXform mappings for sprites in atlas
+        @param tex       SkRect locations of sprites in atlas
+        @param colors    one per sprite, blended with sprite using SkBlendMode; may be nullptr
+        @param count     number of sprites to draw
+        @param mode      SkBlendMode combining colors and sprites
+        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr
+        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+    */
+    void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
+                   const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
+                   const SkPaint* paint) {
+        this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cullRect, paint);
+    }
+
+    /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+        to draw, if present. For each entry in the array, SkRect tex locates sprite in
+        atlas, and SkRSXform xform transforms it into destination space.
+
+        xform and text must contain count entries.
+        Optional cullRect is a conservative bounds of all transformed sprites.
+        If cullRect is outside of clip, canvas can skip drawing.
+
+        @param atlas     SkImage containing sprites
+        @param xform     SkRSXform mappings for sprites in atlas
+        @param tex       SkRect locations of sprites in atlas
+        @param count     number of sprites to draw
+        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr
+        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+    */
+    void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
+                   const SkRect* cullRect, const SkPaint* paint) {
+        this->drawAtlas(atlas, xform, tex, nullptr, count, SkBlendMode::kDst, cullRect, paint);
+    }
+
+    /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+        paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+        to draw, if present. For each entry in the array, SkRect tex locates sprite in
+        atlas, and SkRSXform xform transforms it into destination space.
+
+        xform and text must contain count entries.
+        Optional cullRect is a conservative bounds of all transformed sprites.
+        If cullRect is outside of clip, canvas can skip drawing.
+
+        @param atlas     SkImage containing sprites
+        @param xform     SkRSXform mappings for sprites in atlas
+        @param tex       SkRect locations of sprites in atlas
+        @param count     number of sprites to draw
+        @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr
+        @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+    */
+    void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
+                   int count, const SkRect* cullRect, const SkPaint* paint) {
+        this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkBlendMode::kDst,
+                        cullRect, paint);
+    }
+
+    /** Draws SkDrawable drawable using clip and SkMatrix, concatenated with
+        optional matrix.
+
+        If SkCanvas has an asynchronous implementation, as is the case
+        when it is recording into SkPicture, then drawable will be referenced,
+        so that SkDrawable::draw() can be called when the operation is finalized. To force
+        immediate drawing, call SkDrawable::draw() instead.
+
+        @param drawable  custom struct encapsulating drawing commands
+        @param matrix    transformation applied to drawing; may be nullptr
+    */
+    void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);
+
+    /** Draws SkDrawable drawable using clip and SkMatrix, offset by (x, y).
+
+        If SkCanvas has an asynchronous implementation, as is the case
+        when it is recording into SkPicture, then drawable will be referenced,
+        so that SkDrawable::draw() can be called when the operation is finalized. To force
+        immediate drawing, call SkDrawable::draw() instead.
+
+        @param drawable  custom struct encapsulating drawing commands
+        @param x         offset into SkCanvas writable pixels on x-axis
+        @param y         offset into SkCanvas writable pixels on y-axis
+    */
+    void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
+
+    /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is
+        a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+        Only some canvas implementations, such as recording to SkPicture, or drawing to
+        document PDF, use annotations.
+
+        @param rect   SkRect extent of canvas to annotate
+        @param key    string used for lookup
+        @param value  data holding value stored in annotation
+    */
+    void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
+
+    /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is
+        a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+        Only some canvas implementations, such as recording to SkPicture, or drawing to
+        document PDF, use annotations.
+
+        @param rect   SkRect extent of canvas to annotate
+        @param key    string used for lookup
+        @param value  data holding value stored in annotation
+    */
+    void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
+        this->drawAnnotation(rect, key, value.get());
+    }
+
+    /** Returns true if clip is empty; that is, nothing will draw.
+
+        May do work when called; it should not be called
+        more often than needed. However, once called, subsequent calls perform no
+        work until clip changes.
+
+        @return  true if clip is empty
+    */
+    virtual bool isClipEmpty() const;
+
+    /** Returns true if clip is SkRect and not empty.
+        Returns false if the clip is empty, or if it is not SkRect.
+
+        @return  true if clip is SkRect and not empty
+    */
+    virtual bool isClipRect() const;
+
+    /** Returns SkMatrix.
+        This does not account for translation by SkBaseDevice or SkSurface.
+
+        @return  SkMatrix in SkCanvas
+    */
+    const SkMatrix& getTotalMatrix() const;
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    // don't call
+    virtual GrRenderTargetContext* internal_private_accessTopLayerRenderTargetContext();
+    SkIRect internal_private_getTopLayerBounds() const { return getTopLayerBounds(); }
+
+    // TEMP helpers until we switch virtual over to const& for src-rect
+    void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+                              const SkPaint* paint,
+                              SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+    void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+                               const SkPaint* paint,
+                               SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+    /**
+     *  Returns the global clip as a region. If the clip contains AA, then only the bounds
+     *  of the clip may be returned.
+     */
+    void temporary_internal_getRgnClip(SkRegion* region);
+
+    void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
+
+
+protected:
+    // default impl defers to getDevice()->newSurface(info)
+    virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
+
+    // default impl defers to its device
+    virtual bool onPeekPixels(SkPixmap* pixmap);
+    virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);
+    virtual SkImageInfo onImageInfo() const;
+    virtual bool onGetProps(SkSurfaceProps* props) const;
+    virtual void onFlush();
+
+    // Subclass save/restore notifiers.
+    // Overriders should call the corresponding INHERITED method up the inheritance chain.
+    // getSaveLayerStrategy()'s return value may suppress full layer allocation.
+    enum SaveLayerStrategy {
+        kFullLayer_SaveLayerStrategy,
+        kNoLayer_SaveLayerStrategy,
+    };
+
+    virtual void willSave() {}
+    // Overriders should call the corresponding INHERITED method up the inheritance chain.
+    virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
+        return kFullLayer_SaveLayerStrategy;
+    }
+    virtual void willRestore() {}
+    virtual void didRestore() {}
+    virtual void didConcat(const SkMatrix& ) {}
+    virtual void didSetMatrix(const SkMatrix& ) {}
+    virtual void didTranslate(SkScalar dx, SkScalar dy) {
+        this->didConcat(SkMatrix::MakeTrans(dx, dy));
+    }
+
+    // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to
+    // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using
+    // that mechanism  will be required to implement the new function.
+    virtual void onDrawPaint(const SkPaint& paint);
+    virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
+    virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
+    virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+    virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
+    virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
+                           bool useCenter, const SkPaint& paint);
+    virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
+    virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
+
+    virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
+                            SkScalar y, const SkPaint& paint);
+    virtual void onDrawPosText(const void* text, size_t byteLength,
+                               const SkPoint pos[], const SkPaint& paint);
+    virtual void onDrawPosTextH(const void* text, size_t byteLength,
+                                const SkScalar xpos[], SkScalar constY,
+                                const SkPaint& paint);
+    virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+                                   const SkRect* cullRect, const SkPaint& paint);
+    virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+                                const SkPaint& paint);
+
+    virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                           const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+    virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
+                              const SkPaint& paint);
+
+    // TODO: Remove old signature
+    virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+                                      const SkPaint& paint) {
+        this->onDrawVerticesObject(vertices, nullptr, 0, mode, paint);
+    }
+    virtual void onDrawVerticesObject(const SkVertices* vertices, const SkVertices::Bone bones[],
+                                      int boneCount, SkBlendMode mode, const SkPaint& paint);
+
+    virtual void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint);
+    virtual void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+                                 const SkPaint* paint, SrcRectConstraint constraint);
+    virtual void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
+                                 const SkPaint* paint);
+    virtual void onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
+                                    const SkPaint* paint);
+
+    virtual void onDrawImageSet(const ImageSetEntry imageSet[], int count, SkFilterQuality,
+                                SkBlendMode);
+
+    virtual void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
+                              const SkPaint* paint);
+    virtual void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+                                  const SkPaint* paint, SrcRectConstraint constraint);
+    virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
+                                  const SkPaint* paint);
+    virtual void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
+                                     const SkRect& dst, const SkPaint* paint);
+
+    virtual void onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect rect[],
+                             const SkColor colors[], int count, SkBlendMode mode,
+                             const SkRect* cull, const SkPaint* paint);
+
+    virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);
+    virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
+
+    virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);
+    virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+                               const SkPaint* paint);
+
+    enum ClipEdgeStyle {
+        kHard_ClipEdgeStyle,
+        kSoft_ClipEdgeStyle
+    };
+
+    virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);
+    virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);
+    virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);
+    virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);
+
+    virtual void onDiscard();
+
+    // Clip rectangle bounds. Called internally by saveLayer.
+    // returns false if the entire rectangle is entirely clipped out
+    // If non-NULL, The imageFilter parameter will be used to expand the clip
+    // and offscreen bounds for any margin required by the filter DAG.
+    bool clipRectBounds(const SkRect* bounds, SaveLayerFlags flags, SkIRect* intersection,
+                        const SkImageFilter* imageFilter = nullptr);
+
+    SkBaseDevice* getTopDevice() const;
+
+private:
+    /** After calling saveLayer(), there can be any number of devices that make
+     up the top-most drawing area. LayerIter can be used to iterate through
+     those devices. Note that the iterator is only valid until the next API
+     call made on the canvas. Ownership of all pointers in the iterator stays
+     with the canvas, so none of them should be modified or deleted.
+     */
+    class LayerIter /*: SkNoncopyable*/ {
+    public:
+        /** Initialize iterator with canvas, and set values for 1st device */
+        LayerIter(SkCanvas*);
+        ~LayerIter();
+
+        /** Return true if the iterator is done */
+        bool done() const { return fDone; }
+        /** Cycle to the next device */
+        void next();
+
+        // These reflect the current device in the iterator
+
+        SkBaseDevice*   device() const;
+        const SkMatrix& matrix() const;
+        SkIRect clipBounds() const;
+        const SkPaint&  paint() const;
+        int             x() const;
+        int             y() const;
+
+    private:
+        // used to embed the SkDrawIter object directly in our instance, w/o
+        // having to expose that class def to the public. There is an assert
+        // in our constructor to ensure that fStorage is large enough
+        // (though needs to be a compile-time-assert!). We use intptr_t to work
+        // safely with 32 and 64 bit machines (to ensure the storage is enough)
+        intptr_t          fStorage[32];
+        class SkDrawIter* fImpl;    // this points at fStorage
+        SkPaint           fDefaultPaint;
+        bool              fDone;
+    };
+
+    static bool BoundsAffectsClip(SaveLayerFlags);
+
+    static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
+                                     SkBaseDevice* dst, const SkIPoint& dstOrigin,
+                                     const SkMatrix& ctm);
+
+    enum ShaderOverrideOpacity {
+        kNone_ShaderOverrideOpacity,        //!< there is no overriding shader (bitmap or image)
+        kOpaque_ShaderOverrideOpacity,      //!< the overriding shader is opaque
+        kNotOpaque_ShaderOverrideOpacity,   //!< the overriding shader may not be opaque
+    };
+
+    // notify our surface (if we have one) that we are about to draw, so it
+    // can perform copy-on-write or invalidate any cached images
+    void predrawNotify(bool willOverwritesEntireSurface = false);
+    void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
+    void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
+        this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
+                                                                : kNotOpaque_ShaderOverrideOpacity);
+    }
+
+    SkBaseDevice* getDevice() const;
+
+    class MCRec;
+
+    SkDeque     fMCStack;
+    // points to top of stack
+    MCRec*      fMCRec;
+
+    // the first N recs that can fit here mean we won't call malloc
+    static constexpr int kMCRecSize      = 128;  // most recent measurement
+    static constexpr int kMCRecCount     = 32;   // common depth for save/restores
+    static constexpr int kDeviceCMSize   = 224;  // most recent measurement
+
+    intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
+    intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
+
+    const SkSurfaceProps fProps;
+
+    int         fSaveCount;         // value returned by getSaveCount()
+
+    SkMetaData* fMetaData;
+    std::unique_ptr<SkRasterHandleAllocator> fAllocator;
+
+    SkSurface_Base*  fSurfaceBase;
+    SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
+    void setSurfaceBase(SkSurface_Base* sb) {
+        fSurfaceBase = sb;
+    }
+    friend class SkSurface_Base;
+    friend class SkSurface_Gpu;
+
+    SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
+
+    void doSave();
+    void checkForDeferredSave();
+    void internalSetMatrix(const SkMatrix&);
+
+    friend class SkAndroidFrameworkUtils;
+    friend class SkCanvasPriv;      // needs kDontClipToLayer_PrivateSaveLayerFlag
+    friend class SkDrawIter;        // needs setupDrawForLayerDevice()
+    friend class AutoDrawLooper;
+    friend class SkDebugCanvas;     // needs experimental fAllowSimplifyClip
+    friend class SkSurface_Raster;  // needs getDevice()
+    friend class SkNoDrawCanvas;    // needs resetForNextPicture()
+    friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)
+    friend class SkOverdrawCanvas;
+    friend class SkRasterHandleAllocator;
+
+protected:
+    // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
+    SkCanvas(const SkIRect& bounds);
+private:
+    SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
+             SkRasterHandleAllocator::Handle);
+
+    SkCanvas(SkCanvas&&) = delete;
+    SkCanvas(const SkCanvas&) = delete;
+    SkCanvas& operator=(SkCanvas&&) = delete;
+    SkCanvas& operator=(const SkCanvas&) = delete;
+
+    void resetForNextPicture(const SkIRect& bounds);
+
+    // needs gettotalclip()
+    friend class SkCanvasStateUtils;
+
+    // call this each time we attach ourselves to a device
+    //  - constructor
+    //  - internalSaveLayer
+    void setupDevice(SkBaseDevice*);
+
+    void init(sk_sp<SkBaseDevice>);
+
+    /**
+     * Gets the bounds of the top level layer in global canvas coordinates. We don't want this
+     * to be public because it exposes decisions about layer sizes that are internal to the canvas.
+     */
+    SkIRect getTopLayerBounds() const;
+
+    void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
+                                const SkRect& dst, const SkPaint* paint,
+                                SrcRectConstraint);
+    void internalDrawPaint(const SkPaint& paint);
+    void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
+    void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, SkImage* clipImage,
+                            const SkMatrix& clipMatrix);
+
+    // shared by save() and saveLayer()
+    void internalSave();
+    void internalRestore();
+
+    /*
+     *  Returns true if drawing the specified rect (or all if it is null) with the specified
+     *  paint (or default if null) would overwrite the entire root device of the canvas
+     *  (i.e. the canvas' surface if it had one).
+     */
+    bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
+
+    /**
+     *  Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
+     */
+    bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
+
+    /**
+     *  Returns true if the clip (for any active layer) contains antialiasing.
+     *  If the clip is empty, this will return false.
+     */
+    bool androidFramework_isClipAA() const;
+
+    /**
+     *  Keep track of the device clip bounds and if the matrix is scale-translate.  This allows
+     *  us to do a fast quick reject in the common case.
+     */
+    bool   fIsScaleTranslate;
+    SkRect fDeviceClipBounds;
+
+    bool fAllowSoftClip;
+    bool fAllowSimplifyClip;
+
+    class AutoValidateClip {
+    public:
+        explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
+            fCanvas->validateClip();
+        }
+        ~AutoValidateClip() { fCanvas->validateClip(); }
+
+    private:
+        const SkCanvas* fCanvas;
+
+        AutoValidateClip(AutoValidateClip&&) = delete;
+        AutoValidateClip(const AutoValidateClip&) = delete;
+        AutoValidateClip& operator=(AutoValidateClip&&) = delete;
+        AutoValidateClip& operator=(const AutoValidateClip&) = delete;
+    };
+
+#ifdef SK_DEBUG
+    void validateClip() const;
+#else
+    void validateClip() const {}
+#endif
+
+    std::unique_ptr<SkGlyphRunBuilder> fScratchGlyphRunBuilder;
+
+    typedef SkRefCnt INHERITED;
+};
+
+/** \class SkAutoCanvasRestore
+    Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore
+    goes out of scope. Use this to guarantee that the canvas is restored to a known
+    state.
+*/
+class SkAutoCanvasRestore {
+public:
+
+    /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix.
+
+        @param canvas  SkCanvas to guard
+        @param doSave  call SkCanvas::save()
+        @return        utility to restore SkCanvas state on destructor
+    */
+    SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
+        if (fCanvas) {
+            fSaveCount = canvas->getSaveCount();
+            if (doSave) {
+                canvas->save();
+            }
+        }
+    }
+
+    /** Restores SkCanvas to saved state. Destructor is called when container goes out of
+        scope.
+    */
+    ~SkAutoCanvasRestore() {
+        if (fCanvas) {
+            fCanvas->restoreToCount(fSaveCount);
+        }
+    }
+
+    /** Restores SkCanvas to saved state immediately. Subsequent calls and
+        ~SkAutoCanvasRestore have no effect.
+    */
+    void restore() {
+        if (fCanvas) {
+            fCanvas->restoreToCount(fSaveCount);
+            fCanvas = nullptr;
+        }
+    }
+
+private:
+    SkCanvas*   fCanvas;
+    int         fSaveCount;
+
+    SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete;
+    SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete;
+    SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete;
+    SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete;
+};
+#define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
+
+#endif

+ 93 - 0
skia/include/core/SkCanvasVirtualEnforcer.h

@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCanvasVirtualEnforcer_DEFINED
+#define SkCanvasVirtualEnforcer_DEFINED
+
+#include "SkCanvas.h"
+
+// If you would ordinarily want to inherit from Base (eg SkCanvas, SkNWayCanvas), instead
+// inherit from SkCanvasVirtualEnforcer<Base>, which will make the build fail if you forget
+// to override one of SkCanvas' key virtual hooks.
+template <typename Base>
+class SkCanvasVirtualEnforcer : public Base {
+public:
+    using Base::Base;
+
+protected:
+    void onDrawPaint(const SkPaint& paint) override = 0;
+    void onDrawRect(const SkRect& rect, const SkPaint& paint) override = 0;
+    void onDrawRRect(const SkRRect& rrect, const SkPaint& paint) override = 0;
+    void onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
+                      const SkPaint& paint) override = 0;
+    void onDrawOval(const SkRect& rect, const SkPaint& paint) override = 0;
+    void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
+                   const SkPaint& paint) override = 0;
+    void onDrawPath(const SkPath& path, const SkPaint& paint) override = 0;
+    void onDrawRegion(const SkRegion& region, const SkPaint& paint) override = 0;
+
+    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
+                    const SkPaint& paint) override = 0;
+    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
+                       const SkPaint& paint) override = 0;
+    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
+                        SkScalar constY, const SkPaint& paint) override = 0;
+    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
+                           const SkRect* cullRect, const SkPaint& paint) override = 0;
+    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+                        const SkPaint& paint) override = 0;
+
+    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+                     const SkPoint texCoords[4], SkBlendMode mode,
+                     const SkPaint& paint) override = 0;
+    void onDrawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint pts[],
+                      const SkPaint& paint) override = 0;
+    void onDrawVerticesObject(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
+                              SkBlendMode, const SkPaint&) override = 0;
+
+    void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy,
+                     const SkPaint* paint) override = 0;
+    void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
+                         const SkPaint* paint, SkCanvas::SrcRectConstraint constraint) override = 0;
+    void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
+                         const SkPaint* paint) override = 0;
+    void onDrawImageLattice(const SkImage* image, const SkCanvas::Lattice& lattice,
+                            const SkRect& dst, const SkPaint* paint) override = 0;
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    // This is under active development for Chrome and not used in Android. Hold off on adding
+    // implementations in Android's SkCanvas subclasses until this stabilizes.
+    void onDrawImageSet(const SkCanvas::ImageSetEntry[], int count, SkFilterQuality,
+                        SkBlendMode) override {};
+#else
+    void onDrawImageSet(const SkCanvas::ImageSetEntry[], int count, SkFilterQuality,
+                        SkBlendMode) override = 0;
+#endif
+
+    void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
+                      const SkPaint* paint) override = 0;
+    void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
+                          const SkPaint* paint,
+                          SkCanvas::SrcRectConstraint constraint) override = 0;
+    void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
+                          const SkPaint* paint) override = 0;
+    void onDrawBitmapLattice(const SkBitmap& bitmap, const SkCanvas::Lattice& lattice,
+                             const SkRect& dst, const SkPaint* paint) override = 0;
+
+    void onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect rect[],
+                     const SkColor colors[], int count, SkBlendMode mode, const SkRect* cull,
+                     const SkPaint* paint) override = 0;
+
+    void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) override = 0;
+    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override = 0;
+
+    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override = 0;
+    void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+                       const SkPaint* paint) override = 0;
+};
+
+#endif

+ 33 - 0
skia/include/core/SkClipOp.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkClipOp_DEFINED
+#define SkClipOp_DEFINED
+
+#include "SkTypes.h"
+
+enum class SkClipOp {
+    kDifference    = 0,
+    kIntersect     = 1,
+
+#ifdef SK_SUPPORT_DEPRECATED_CLIPOPS
+    kUnion_deprecated             = 2,
+    kXOR_deprecated               = 3,
+    kReverseDifference_deprecated = 4,
+    kReplace_deprecated           = 5,
+#else
+    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway2   = 2,
+    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway3   = 3,
+    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway4   = 4,
+    kExtraEnumNeedInternallyPleaseIgnoreWillGoAway5   = 5,
+#endif
+
+    // Used internally for validation, can only shrink to 1 when the deprecated flag is gone
+    kMax_EnumValue = 5,
+};
+
+#endif

+ 389 - 0
skia/include/core/SkColor.h

@@ -0,0 +1,389 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkColor.h and docs/SkColor_Reference.bmh
+   on 2018-06-14 13:13:34. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkColor_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkColor_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkColor.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkColor_DEFINED
+#define SkColor_DEFINED
+
+#include "SkImageInfo.h"
+#include "SkScalar.h"
+#include "SkTypes.h"
+
+/** \file SkColor.h
+
+    Types, consts, functions, and macros for colors.
+*/
+
+/** 8-bit type for an alpha value. 255 is 100% opaque, zero is 100% transparent.
+*/
+typedef uint8_t SkAlpha;
+
+/** 32-bit ARGB color value, unpremultiplied. Color components are always in
+    a known order. This is different from SkPMColor, which has its bytes in a configuration
+    dependent order, to match the format of kBGRA_8888_SkColorType bitmaps. SkColor
+    is the type used to specify colors in SkPaint and in gradients.
+
+    Color that is premultiplied has the same component values as color
+    that is unpremultiplied if alpha is 255, fully opaque, although may have the
+    component values in a different order.
+*/
+typedef uint32_t SkColor;
+
+/** Returns color value from 8-bit component values. Asserts if SK_DEBUG is defined
+    if a, r, g, or b exceed 255. Since color is unpremultiplied, a may be smaller
+    than the largest of r, g, and b.
+
+    @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
+    @param r  amount of red, from no red (0) to full red (255)
+    @param g  amount of green, from no green (0) to full green (255)
+    @param b  amount of blue, from no blue (0) to full blue (255)
+    @return   color and alpha, unpremultiplied
+*/
+static constexpr inline SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+    return SkASSERT(a <= 255 && r <= 255 && g <= 255 && b <= 255),
+           (a << 24) | (r << 16) | (g << 8) | (b << 0);
+}
+
+/** Returns color value from 8-bit component values, with alpha set
+    fully opaque to 255.
+*/
+#define SkColorSetRGB(r, g, b)  SkColorSetARGB(0xFF, r, g, b)
+
+/** Returns alpha byte from color value.
+*/
+#define SkColorGetA(color)      (((color) >> 24) & 0xFF)
+
+/** Returns red component of color, from zero to 255.
+*/
+#define SkColorGetR(color)      (((color) >> 16) & 0xFF)
+
+/** Returns green component of color, from zero to 255.
+*/
+#define SkColorGetG(color)      (((color) >>  8) & 0xFF)
+
+/** Returns blue component of color, from zero to 255.
+*/
+#define SkColorGetB(color)      (((color) >>  0) & 0xFF)
+
+/** Returns unpremultiplied color with red, blue, and green set from c; and alpha set
+    from a. Alpha component of c is ignored and is replaced by a in result.
+
+    @param c  packed RGB, eight bits per component
+    @param a  alpha: transparent at zero, fully opaque at 255
+    @return   color with transparency
+*/
+static constexpr inline SkColor SkColorSetA(SkColor c, U8CPU a) {
+    return (c & 0x00FFFFFF) | (a << 24);
+}
+
+/** Represents fully transparent SkAlpha value. SkAlpha ranges from zero,
+    fully transparent; to 255, fully opaque.
+*/
+constexpr SkAlpha SK_AlphaTRANSPARENT = 0x00;
+
+/** Represents fully opaque SkAlpha value. SkAlpha ranges from zero,
+    fully transparent; to 255, fully opaque.
+*/
+constexpr SkAlpha SK_AlphaOPAQUE      = 0xFF;
+
+/** Represents fully transparent SkColor. May be used to initialize a destination
+    containing a mask or a non-rectangular image.
+*/
+constexpr SkColor SK_ColorTRANSPARENT = SkColorSetARGB(0x00, 0x00, 0x00, 0x00);
+
+/** Represents fully opaque black.
+*/
+constexpr SkColor SK_ColorBLACK       = SkColorSetARGB(0xFF, 0x00, 0x00, 0x00);
+
+/** Represents fully opaque dark gray.
+    Note that SVG dark gray is equivalent to 0xFFA9A9A9.
+*/
+constexpr SkColor SK_ColorDKGRAY      = SkColorSetARGB(0xFF, 0x44, 0x44, 0x44);
+
+/** Represents fully opaque gray.
+    Note that HTML gray is equivalent to 0xFF808080.
+*/
+constexpr SkColor SK_ColorGRAY        = SkColorSetARGB(0xFF, 0x88, 0x88, 0x88);
+
+/** Represents fully opaque light gray. HTML silver is equivalent to 0xFFC0C0C0.
+    Note that SVG light gray is equivalent to 0xFFD3D3D3.
+*/
+constexpr SkColor SK_ColorLTGRAY      = SkColorSetARGB(0xFF, 0xCC, 0xCC, 0xCC);
+
+/** Represents fully opaque white.
+*/
+constexpr SkColor SK_ColorWHITE       = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0xFF);
+
+/** Represents fully opaque red.
+*/
+constexpr SkColor SK_ColorRED         = SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00);
+
+/** Represents fully opaque green. HTML lime is equivalent.
+    Note that HTML green is equivalent to 0xFF008000.
+*/
+constexpr SkColor SK_ColorGREEN       = SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00);
+
+/** Represents fully opaque blue.
+*/
+constexpr SkColor SK_ColorBLUE        = SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF);
+
+/** Represents fully opaque yellow.
+*/
+constexpr SkColor SK_ColorYELLOW      = SkColorSetARGB(0xFF, 0xFF, 0xFF, 0x00);
+
+/** Represents fully opaque cyan. HTML aqua is equivalent.
+*/
+constexpr SkColor SK_ColorCYAN        = SkColorSetARGB(0xFF, 0x00, 0xFF, 0xFF);
+
+/** Represents fully opaque magenta. HTML fuchsia is equivalent.
+*/
+constexpr SkColor SK_ColorMAGENTA     = SkColorSetARGB(0xFF, 0xFF, 0x00, 0xFF);
+
+/** Converts RGB to its HSV components.
+    hsv[0] contains hsv hue, a value from zero to less than 360.
+    hsv[1] contains hsv saturation, a value from zero to one.
+    hsv[2] contains hsv value, a value from zero to one.
+
+    @param red    red component value from zero to 255
+    @param green  green component value from zero to 255
+    @param blue   blue component value from zero to 255
+    @param hsv    three element array which holds the resulting HSV components
+*/
+SK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
+
+/** Converts ARGB to its HSV components. Alpha in ARGB is ignored.
+    hsv[0] contains hsv hue, and is assigned a value from zero to less than 360.
+    hsv[1] contains hsv saturation, a value from zero to one.
+    hsv[2] contains hsv value, a value from zero to one.
+
+    @param color  ARGB color to convert
+    @param hsv    three element array which holds the resulting HSV components
+*/
+static inline void SkColorToHSV(SkColor color, SkScalar hsv[3]) {
+    SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
+}
+
+/** Converts HSV components to an ARGB color. Alpha is passed through unchanged.
+    hsv[0] represents hsv hue, an angle from zero to less than 360.
+    hsv[1] represents hsv saturation, and varies from zero to one.
+    hsv[2] represents hsv value, and varies from zero to one.
+
+    Out of range hsv values are pinned.
+
+    @param alpha  alpha component of the returned ARGB color
+    @param hsv    three element array which holds the input HSV components
+    @return       ARGB equivalent to HSV
+*/
+SK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
+
+/** Converts HSV components to an ARGB color. Alpha is set to 255.
+    hsv[0] represents hsv hue, an angle from zero to less than 360.
+    hsv[1] represents hsv saturation, and varies from zero to one.
+    hsv[2] represents hsv value, and varies from zero to one.
+
+    Out of range hsv values are pinned.
+
+    @param hsv  three element array which holds the input HSV components
+    @return     RGB equivalent to HSV
+*/
+static inline SkColor SkHSVToColor(const SkScalar hsv[3]) {
+    return SkHSVToColor(0xFF, hsv);
+}
+
+/** 32-bit ARGB color value, premultiplied. The byte order for this value is
+    configuration dependent, matching the format of kBGRA_8888_SkColorType bitmaps.
+    This is different from SkColor, which is unpremultiplied, and is always in the
+    same byte order.
+*/
+typedef uint32_t SkPMColor;
+
+/** Returns a SkPMColor value from unpremultiplied 8-bit component values.
+
+    @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
+    @param r  amount of red, from no red (0) to full red (255)
+    @param g  amount of green, from no green (0) to full green (255)
+    @param b  amount of blue, from no blue (0) to full blue (255)
+    @return   premultiplied color
+*/
+SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+/** Returns pmcolor closest to color c. Multiplies c RGB components by the c alpha,
+    and arranges the bytes to match the format of kN32_SkColorType.
+
+    @param c  unpremultiplied ARGB color
+    @return   premultiplied color
+*/
+SK_API SkPMColor SkPreMultiplyColor(SkColor c);
+
+/** \struct SkRGBA4f
+    RGBA color value, holding four floating point components. Color components are always in
+    a known order. kAT determines if the SkRGBA4f's R, G, and B components are premultiplied
+    by alpha or not.
+
+    Skia's public API always uses unpremultiplied colors, which can be stored as
+    SkRGBA4f<kUnpremul_SkAlphaType>. For convenience, this type can also be referred to
+    as SkColor4f.
+*/
+template <SkAlphaType kAT>
+struct SkRGBA4f {
+    float fR;  //!< red component
+    float fG;  //!< green component
+    float fB;  //!< blue component
+    float fA;  //!< alpha component
+
+    /** Compares SkRGBA4f with other, and returns true if all components are equal.
+
+        @param other  SkRGBA4f to compare
+        @return       true if SkRGBA4f equals other
+    */
+    bool operator==(const SkRGBA4f& other) const {
+        return fA == other.fA && fR == other.fR && fG == other.fG && fB == other.fB;
+    }
+
+    /** Compares SkRGBA4f with other, and returns true if not all components are equal.
+
+        @param other  SkRGBA4f to compare
+        @return       true if SkRGBA4f is not equal to other
+    */
+    bool operator!=(const SkRGBA4f& other) const {
+        return !(*this == other);
+    }
+
+    /** Returns SkRGBA4f multiplied by scale.
+
+        @param scale  value to multiply by
+        @return       SkRGBA4f as (fR * scale, fG * scale, fB * scale, fA * scale)
+    */
+    SkRGBA4f operator*(float scale) const {
+        return { fR * scale, fG * scale, fB * scale, fA * scale };
+    }
+
+    /** Returns SkRGBA4f multiplied component-wise by scale.
+
+        @param scale  SkRGBA4f to multiply by
+        @return       SkRGBA4f as (fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA)
+    */
+    SkRGBA4f operator*(const SkRGBA4f& scale) const {
+        return { fR * scale.fR, fG * scale.fG, fB * scale.fB, fA * scale.fA };
+    }
+
+    /** Returns a pointer to components of SkRGBA4f, for array access.
+
+        @return       pointer to array [fR, fG, fB, fA]
+    */
+    const float* vec() const { return &fR; }
+
+    /** Returns a pointer to components of SkRGBA4f, for array access.
+
+        @return       pointer to array [fR, fG, fB, fA]
+    */
+    float* vec() { return &fR; }
+
+    /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+        @param index  one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+        @return       value corresponding to index
+    */
+    float operator[](int index) const {
+        SkASSERT(index >= 0 && index < 4);
+        return this->vec()[index];
+    }
+
+    /** Returns one component. Asserts if index is out of range and SK_DEBUG is defined.
+
+        @param index  one of: 0 (fR), 1 (fG), 2 (fB), 3 (fA)
+        @return       value corresponding to index
+    */
+    float& operator[](int index) {
+        SkASSERT(index >= 0 && index < 4);
+        return this->vec()[index];
+    }
+
+    /** Returns true if SkRGBA4f is an opaque color. Asserts if fA is out of range and
+        SK_DEBUG is defined.
+
+        @return       true if SkRGBA4f is opaque
+    */
+    bool isOpaque() const {
+        SkASSERT(fA <= 1.0f && fA >= 0.0f);
+        return fA == 1.0f;
+    }
+
+    /** Returns closest SkRGBA4f to SkColor. Only allowed if SkRGBA4f is unpremultiplied.
+
+        @return       SkColor as SkRGBA4f
+    */
+    static SkRGBA4f FromColor(SkColor);  // impl. depends on kAT
+
+    /** Returns closest SkColor to SkRGBA4f. Only allowed if SkRGBA4f is unpremultiplied.
+
+        @return       color as SkColor
+    */
+    SkColor toSkColor() const;  // impl. depends on kAT
+
+    /** Returns closest SkRGBA4f to SkPMColor. Only allowed if SkRGBA4f is premultiplied.
+
+        @return        SkPMColor as SkRGBA4f
+    */
+    static SkRGBA4f FromPMColor(SkPMColor);  // impl. depends on kAT
+
+    /** Returns SkRGBA4f premultiplied by alpha. Asserts at compile time if SkRGBA4f is
+        already premultiplied.
+
+        @return       premultiplied color
+    */
+    SkRGBA4f<kPremul_SkAlphaType> premul() const {
+        static_assert(kAT == kUnpremul_SkAlphaType, "");
+        return { fR * fA, fG * fA, fB * fA, fA };
+    }
+
+    /** Returns SkRGBA4f unpremultiplied by alpha. Asserts at compile time if SkRGBA4f is
+        already unpremultiplied.
+
+        @return       unpremultiplied color
+    */
+    SkRGBA4f<kUnpremul_SkAlphaType> unpremul() const {
+        static_assert(kAT == kPremul_SkAlphaType, "");
+
+        if (fA == 0.0f) {
+            return { 0, 0, 0, 0 };
+        } else {
+            float invAlpha = 1 / fA;
+            return { fR * invAlpha, fG * invAlpha, fB * invAlpha, fA };
+        }
+    }
+
+    // This produces bytes in RGBA order (eg GrColor). Impl. is the same, regardless of kAT
+    uint32_t toBytes_RGBA() const;
+    static SkRGBA4f FromBytes_RGBA(uint32_t color);
+
+    SkRGBA4f makeOpaque() const {
+        return { fR, fG, fB, 1.0f };
+    }
+};
+
+/** \struct SkColor4f
+    RGBA color value, holding four floating point components. Color components are always in
+    a known order, and are unpremultiplied.
+
+    This is a specialization of SkRGBA4f. For details, @see SkRGBA4f.
+*/
+using SkColor4f = SkRGBA4f<kUnpremul_SkAlphaType>;
+
+template <> SK_API SkColor4f SkColor4f::FromColor(SkColor);
+template <> SK_API SkColor   SkColor4f::toSkColor() const;
+
+#endif

+ 196 - 0
skia/include/core/SkColorFilter.h

@@ -0,0 +1,196 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorFilter_DEFINED
+#define SkColorFilter_DEFINED
+
+#include "SkBlendMode.h"
+#include "SkColor.h"
+#include "SkFlattenable.h"
+#include "SkRefCnt.h"
+
+class GrContext;
+class GrColorSpaceInfo;
+class GrFragmentProcessor;
+class SkArenaAlloc;
+class SkBitmap;
+class SkColorSpace;
+class SkColorSpaceXformer;
+class SkRasterPipeline;
+class SkString;
+
+/**
+ *  ColorFilters are optional objects in the drawing pipeline. When present in
+ *  a paint, they are called with the "src" colors, and return new colors, which
+ *  are then passed onto the next stage (either ImageFilter or Xfermode).
+ *
+ *  All subclasses are required to be reentrant-safe : it must be legal to share
+ *  the same instance between several threads.
+ */
+class SK_API SkColorFilter : public SkFlattenable {
+public:
+    /**
+     *  If the filter can be represented by a source color plus Mode, this
+     *  returns true, and sets (if not NULL) the color and mode appropriately.
+     *  If not, this returns false and ignores the parameters.
+     */
+    virtual bool asColorMode(SkColor* color, SkBlendMode* bmode) const;
+
+    /**
+     *  If the filter can be represented by a 5x4 matrix, this
+     *  returns true, and sets the matrix appropriately.
+     *  If not, this returns false and ignores the parameter.
+     */
+    virtual bool asColorMatrix(SkScalar matrix[20]) const;
+
+    /**
+     *  If the filter can be represented by per-component table, return true,
+     *  and if table is not null, copy the bitmap containing the table into it.
+     *
+     *  The table bitmap will be in SkBitmap::kA8_Config. Each row corresponding
+     *  to each component in ARGB order. e.g. row[0] == alpha, row[1] == red,
+     *  etc. To transform a color, you (logically) perform the following:
+     *
+     *      a' = *table.getAddr8(a, 0);
+     *      r' = *table.getAddr8(r, 1);
+     *      g' = *table.getAddr8(g, 2);
+     *      b' = *table.getAddr8(b, 3);
+     *
+     *  The original component value is the horizontal index for a given row,
+     *  and the stored value at that index is the new value for that component.
+     */
+    virtual bool asComponentTable(SkBitmap* table) const;
+
+    void appendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, bool shaderIsOpaque) const;
+
+    enum Flags {
+        /** If set the filter methods will not change the alpha channel of the colors.
+        */
+        kAlphaUnchanged_Flag = 1 << 0,
+    };
+
+    /** Returns the flags for this filter. Override in subclasses to return custom flags.
+    */
+    virtual uint32_t getFlags() const { return 0; }
+
+    SkColor filterColor(SkColor) const;
+    SkColor4f filterColor4f(const SkColor4f&, SkColorSpace*) const;
+
+    /** Create a colorfilter that uses the specified color and mode.
+        If the Mode is DST, this function will return NULL (since that
+        mode will have no effect on the result).
+        @param c    The source color used with the specified mode
+        @param mode The blend that is applied to each color in
+                        the colorfilter's filterSpan[16,32] methods
+        @return colorfilter object that applies the src color and mode,
+                    or NULL if the mode will have no effect.
+    */
+    static sk_sp<SkColorFilter> MakeModeFilter(SkColor c, SkBlendMode mode);
+
+    /** Construct a colorfilter whose effect is to first apply the inner filter and then apply
+     *  this filter, applied to the output of the inner filter.
+     *
+     *  result = this(inner(...))
+     *
+     *  Due to internal limits, it is possible that this will return NULL, so the caller must
+     *  always check.
+     */
+    sk_sp<SkColorFilter> makeComposed(sk_sp<SkColorFilter> inner) const;
+
+    // DEPRECATED, call makeComposed instead
+    static sk_sp<SkColorFilter> MakeComposeFilter(sk_sp<SkColorFilter> outer,
+                                                  sk_sp<SkColorFilter> inner) {
+        return outer ? outer->makeComposed(inner) : inner;
+    }
+
+    /** Construct a color filter that transforms a color by a 4x5 matrix. The matrix is in row-
+     *  major order and the translation column is specified in unnormalized, 0...255, space.
+     */
+    static sk_sp<SkColorFilter> MakeMatrixFilterRowMajor255(const SkScalar array[20]);
+
+    /** Construct a colorfilter that applies the srgb gamma curve to the RGB channels */
+    static sk_sp<SkColorFilter> MakeLinearToSRGBGamma();
+
+    /** Construct a colorfilter that applies the inverse of the srgb gamma curve to the
+     *  RGB channels
+     */
+    static sk_sp<SkColorFilter> MakeSRGBToLinearGamma();
+
+#if SK_SUPPORT_GPU
+    /**
+     *  A subclass may implement this factory function to work with the GPU backend. It returns
+     *  a GrFragmentProcessor that implemets the color filter in GPU shader code.
+     *
+     *  The fragment processor receives a premultiplied input color and produces a premultiplied
+     *  output color.
+     *
+     *  A null return indicates that the color filter isn't implemented for the GPU backend.
+     */
+    virtual std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(
+            GrContext*, const GrColorSpaceInfo& dstColorSpaceInfo) const;
+#endif
+
+    bool affectsTransparentBlack() const {
+        return this->filterColor(SK_ColorTRANSPARENT) != SK_ColorTRANSPARENT;
+    }
+
+    static void RegisterFlattenables();
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkColorFilter_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkColorFilter_Type;
+    }
+
+    static sk_sp<SkColorFilter> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkColorFilter>(static_cast<SkColorFilter*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkColorFilter_Type, data, size, procs).release()));
+    }
+
+protected:
+    SkColorFilter() {}
+
+    sk_sp<SkColorFilter> makeColorSpace(SkColorSpaceXformer* xformer) const {
+        return this->onMakeColorSpace(xformer);
+    }
+    virtual sk_sp<SkColorFilter> onMakeColorSpace(SkColorSpaceXformer*) const {
+        return sk_ref_sp(const_cast<SkColorFilter*>(this));
+    }
+
+    /**
+     *  If this subclass can optimally createa composition with the inner filter, return it as
+     *  a new filter (which the caller must unref() when it is done). If no such optimization
+     *  is known, return NULL.
+     *
+     *  e.g. result(color) == this_filter(inner(color))
+     */
+    virtual sk_sp<SkColorFilter> onMakeComposed(sk_sp<SkColorFilter>) const { return nullptr; }
+
+private:
+    /*
+     *  Returns 1 if this is a single filter (not a composition of other filters), otherwise it
+     *  reutrns the number of leaf-node filters in a composition. This should be the same value
+     *  as the number of GrFragmentProcessors returned by asFragmentProcessors's array parameter.
+     *
+     *  e.g. compose(filter, compose(compose(filter, filter), filter)) --> 4
+     */
+    virtual int privateComposedFilterCount() const { return 1; }
+
+    virtual void onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*,
+                                bool shaderIsOpaque) const = 0;
+
+    friend class SkColorSpaceXformer;
+    friend class SkComposeColorFilter;
+
+    typedef SkFlattenable INHERITED;
+};
+
+#endif

+ 163 - 0
skia/include/core/SkColorPriv.h

@@ -0,0 +1,163 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorPriv_DEFINED
+#define SkColorPriv_DEFINED
+
+#include "../private/SkTo.h"
+#include "SkColor.h"
+#include "SkMath.h"
+
+/** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
+    byte into a scale value, so that we can say scale * value >> 8 instead of
+    alpha * value / 255.
+
+    In debugging, asserts that alpha is 0..255
+*/
+static inline unsigned SkAlpha255To256(U8CPU alpha) {
+    SkASSERT(SkToU8(alpha) == alpha);
+    // this one assues that blending on top of an opaque dst keeps it that way
+    // even though it is less accurate than a+(a>>7) for non-opaque dsts
+    return alpha + 1;
+}
+
+/** Multiplify value by 0..256, and shift the result down 8
+    (i.e. return (value * alpha256) >> 8)
+ */
+#define SkAlphaMul(value, alpha256)     (((value) * (alpha256)) >> 8)
+
+static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
+    return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);
+}
+
+#define SK_A32_BITS     8
+#define SK_R32_BITS     8
+#define SK_G32_BITS     8
+#define SK_B32_BITS     8
+
+#define SK_A32_MASK     ((1 << SK_A32_BITS) - 1)
+#define SK_R32_MASK     ((1 << SK_R32_BITS) - 1)
+#define SK_G32_MASK     ((1 << SK_G32_BITS) - 1)
+#define SK_B32_MASK     ((1 << SK_B32_BITS) - 1)
+
+/*
+ *  Skia's 32bit backend only supports 1 swizzle order at a time (compile-time).
+ *  This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
+ *
+ *  For easier compatibility with Skia's GPU backend, we further restrict these
+ *  to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
+ *  not directly correspond to the same shift-order, since we have to take endianess
+ *  into account.
+ *
+ *  Here we enforce this constraint.
+ */
+
+#ifdef SK_CPU_BENDIAN
+    #define SK_RGBA_R32_SHIFT   24
+    #define SK_RGBA_G32_SHIFT   16
+    #define SK_RGBA_B32_SHIFT   8
+    #define SK_RGBA_A32_SHIFT   0
+
+    #define SK_BGRA_B32_SHIFT   24
+    #define SK_BGRA_G32_SHIFT   16
+    #define SK_BGRA_R32_SHIFT   8
+    #define SK_BGRA_A32_SHIFT   0
+#else
+    #define SK_RGBA_R32_SHIFT   0
+    #define SK_RGBA_G32_SHIFT   8
+    #define SK_RGBA_B32_SHIFT   16
+    #define SK_RGBA_A32_SHIFT   24
+
+    #define SK_BGRA_B32_SHIFT   0
+    #define SK_BGRA_G32_SHIFT   8
+    #define SK_BGRA_R32_SHIFT   16
+    #define SK_BGRA_A32_SHIFT   24
+#endif
+
+#if defined(SK_PMCOLOR_IS_RGBA) || defined(SK_PMCOLOR_IS_BGRA)
+    #error "Configure PMCOLOR by setting SK_R32_SHIFT, etc"
+#endif
+
+// Deduce which SK_PMCOLOR_IS_ to define from the _SHIFT defines
+
+#if (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
+     SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
+     SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
+     SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
+    #define SK_PMCOLOR_IS_RGBA
+#elif (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
+       SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
+       SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
+       SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
+    #define SK_PMCOLOR_IS_BGRA
+#else
+    #error "need 32bit packing to be either RGBA or BGRA"
+#endif
+
+#define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
+#define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
+#define SkGetPackedG32(packed)      ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
+#define SkGetPackedB32(packed)      ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
+
+#define SkA32Assert(a)  SkASSERT((unsigned)(a) <= SK_A32_MASK)
+#define SkR32Assert(r)  SkASSERT((unsigned)(r) <= SK_R32_MASK)
+#define SkG32Assert(g)  SkASSERT((unsigned)(g) <= SK_G32_MASK)
+#define SkB32Assert(b)  SkASSERT((unsigned)(b) <= SK_B32_MASK)
+
+/**
+ *  Pack the components into a SkPMColor, checking (in the debug version) that
+ *  the components are 0..255, and are already premultiplied (i.e. alpha >= color)
+ */
+static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+    SkA32Assert(a);
+    SkASSERT(r <= a);
+    SkASSERT(g <= a);
+    SkASSERT(b <= a);
+
+    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+/**
+ *  Same as SkPackARGB32, but this version guarantees to not check that the
+ *  values are premultiplied in the debug version.
+ */
+static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+    return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
+           (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
+}
+
+static inline
+SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
+    SkA32Assert(a);
+    SkR32Assert(r);
+    SkG32Assert(g);
+    SkB32Assert(b);
+
+    if (a != 255) {
+        r = SkMulDiv255Round(r, a);
+        g = SkMulDiv255Round(g, a);
+        b = SkMulDiv255Round(b, a);
+    }
+    return SkPackARGB32(a, r, g, b);
+}
+
+// When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
+// inlined; forcing inlining significantly improves performance.
+static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
+    uint32_t mask = 0xFF00FF;
+
+    uint32_t rb = ((c & mask) * scale) >> 8;
+    uint32_t ag = ((c >> 8) & mask) * scale;
+    return (rb & mask) | (ag & ~mask);
+}
+
+static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
+    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
+}
+
+#endif

+ 237 - 0
skia/include/core/SkColorSpace.h

@@ -0,0 +1,237 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpace_DEFINED
+#define SkColorSpace_DEFINED
+
+#include "../private/SkOnce.h"
+#include "SkMatrix44.h"
+#include "SkRefCnt.h"
+#include <memory>
+
+class SkData;
+struct skcms_ICCProfile;
+
+enum SkGammaNamed {
+    kLinear_SkGammaNamed,
+    kSRGB_SkGammaNamed,
+    k2Dot2Curve_SkGammaNamed,
+    kNonStandard_SkGammaNamed,
+};
+
+/**
+ *  Describes a color gamut with primaries and a white point.
+ */
+struct SK_API SkColorSpacePrimaries {
+    float fRX;
+    float fRY;
+    float fGX;
+    float fGY;
+    float fBX;
+    float fBY;
+    float fWX;
+    float fWY;
+
+    /**
+     *  Convert primaries and a white point to a toXYZD50 matrix, the preferred color gamut
+     *  representation of SkColorSpace.
+     */
+    bool toXYZD50(SkMatrix44* toXYZD50) const;
+};
+
+/**
+ *  Contains the coefficients for a common transfer function equation, specified as
+ *  a transformation from a curved space to linear.
+ *
+ *  LinearVal = sign(InputVal) * (  C*|InputVal| + F       ), for 0.0f <= |InputVal| <  D
+ *  LinearVal = sign(InputVal) * ( (A*|InputVal| + B)^G + E), for D    <= |InputVal|
+ *
+ *  Function must be positive and increasing.
+ */
+struct SK_API SkColorSpaceTransferFn {
+    float fG;
+    float fA;
+    float fB;
+    float fC;
+    float fD;
+    float fE;
+    float fF;
+};
+
+class SK_API SkColorSpace : public SkNVRefCnt<SkColorSpace> {
+public:
+    /**
+     *  Create the sRGB color space.
+     */
+    static sk_sp<SkColorSpace> MakeSRGB();
+
+    /**
+     *  Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
+     *  half-float surfaces, and high precision individual colors (gradient stops, etc...)
+     */
+    static sk_sp<SkColorSpace> MakeSRGBLinear();
+
+    enum RenderTargetGamma : uint8_t {
+        kLinear_RenderTargetGamma,
+
+        /**
+         *  Transfer function is the canonical sRGB curve, which has a short linear segment
+         *  followed by a 2.4f exponential.
+         */
+        kSRGB_RenderTargetGamma,
+    };
+
+    enum Gamut {
+        kSRGB_Gamut,
+        kAdobeRGB_Gamut,
+        kDCIP3_D65_Gamut,
+        kRec2020_Gamut,
+    };
+
+    /**
+     *  Create an SkColorSpace from a transfer function and a color gamut.
+     *
+     *  Transfer function can be specified as an enum or as the coefficients to an equation.
+     *  Gamut can be specified as an enum or as the matrix transformation to XYZ D50.
+     */
+    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, Gamut gamut);
+    static sk_sp<SkColorSpace> MakeRGB(RenderTargetGamma gamma, const SkMatrix44& toXYZD50);
+    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs, Gamut gamut);
+    static sk_sp<SkColorSpace> MakeRGB(const SkColorSpaceTransferFn& coeffs,
+                                       const SkMatrix44& toXYZD50);
+
+    static sk_sp<SkColorSpace> MakeRGB(SkGammaNamed gammaNamed, const SkMatrix44& toXYZD50);
+
+    /**
+     *  Create an SkColorSpace from a parsed (skcms) ICC profile.
+     */
+    static sk_sp<SkColorSpace> Make(const skcms_ICCProfile&);
+
+    /**
+     *  Convert this color space to an skcms ICC profile struct.
+     */
+    void toProfile(skcms_ICCProfile*) const;
+
+    SkGammaNamed gammaNamed() const { return fGammaNamed; }
+
+    /**
+     *  Returns true if the color space gamma is near enough to be approximated as sRGB.
+     */
+    bool gammaCloseToSRGB() const { return kSRGB_SkGammaNamed == fGammaNamed; }
+
+    /**
+     *  Returns true if the color space gamma is linear.
+     */
+    bool gammaIsLinear() const { return kLinear_SkGammaNamed == fGammaNamed; }
+
+    /**
+     *  If the transfer function can be represented as coefficients to the standard
+     *  equation, returns true and sets |fn| to the proper values.
+     *
+     *  If not, returns false.
+     */
+    bool isNumericalTransferFn(SkColorSpaceTransferFn* fn) const;
+
+    /**
+     *  Returns true and sets |toXYZD50| if the color gamut can be described as a matrix.
+     *  Returns false otherwise.
+     */
+    bool toXYZD50(SkMatrix44* toXYZD50) const;
+
+    /**
+     *  Returns a hash of the gamut transformation to XYZ D50. Allows for fast equality checking
+     *  of gamuts, at the (very small) risk of collision.
+     */
+    uint32_t toXYZD50Hash() const { return fToXYZD50Hash; }
+
+    /**
+     *  Returns a color space with the same gamut as this one, but with a linear gamma.
+     *  For color spaces whose gamut can not be described in terms of XYZ D50, returns
+     *  linear sRGB.
+     */
+    sk_sp<SkColorSpace> makeLinearGamma() const;
+
+    /**
+     *  Returns a color space with the same gamut as this one, with with the sRGB transfer
+     *  function. For color spaces whose gamut can not be described in terms of XYZ D50, returns
+     *  sRGB.
+     */
+    sk_sp<SkColorSpace> makeSRGBGamma() const;
+
+    /**
+     *  Returns a color space with the same transfer function as this one, but with the primary
+     *  colors rotated. For any XYZ space, this produces a new color space that maps RGB to GBR
+     *  (when applied to a source), and maps RGB to BRG (when applied to a destination). For other
+     *  types of color spaces, returns nullptr.
+     *
+     *  This is used for testing, to construct color spaces that have severe and testable behavior.
+     */
+    sk_sp<SkColorSpace> makeColorSpin() const;
+
+    /**
+     *  Returns true if the color space is sRGB.
+     *  Returns false otherwise.
+     *
+     *  This allows a little bit of tolerance, given that we might see small numerical error
+     *  in some cases: converting ICC fixed point to float, converting white point to D50,
+     *  rounding decisions on transfer function and matrix.
+     *
+     *  This does not consider a 2.2f exponential transfer function to be sRGB.  While these
+     *  functions are similar (and it is sometimes useful to consider them together), this
+     *  function checks for logical equality.
+     */
+    bool isSRGB() const;
+
+    /**
+     *  Returns nullptr on failure.  Fails when we fallback to serializing ICC data and
+     *  the data is too large to serialize.
+     */
+    sk_sp<SkData> serialize() const;
+
+    /**
+     *  If |memory| is nullptr, returns the size required to serialize.
+     *  Otherwise, serializes into |memory| and returns the size.
+     */
+    size_t writeToMemory(void* memory) const;
+
+    static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
+
+    /**
+     *  If both are null, we return true.  If one is null and the other is not, we return false.
+     *  If both are non-null, we do a deeper compare.
+     */
+    static bool Equals(const SkColorSpace*, const SkColorSpace*);
+
+    void       transferFn(float gabcdef[7]) const;
+    void    invTransferFn(float gabcdef[7]) const;
+    void gamutTransformTo(const SkColorSpace* dst, float src_to_dst_row_major[9]) const;
+
+    uint32_t transferFnHash() const { return fTransferFnHash; }
+    uint64_t           hash() const { return (uint64_t)fTransferFnHash << 32 | fToXYZD50Hash; }
+
+private:
+    friend class SkColorSpaceSingletonFactory;
+
+    SkColorSpace(SkGammaNamed gammaNamed,
+                 const float transferFn[7],
+                 const SkMatrix44& toXYZ);
+
+    void computeLazyDstFields() const;
+
+    SkGammaNamed                        fGammaNamed;         // TODO: 2-bit, pack tightly?  drop?
+    uint32_t                            fTransferFnHash;
+    uint32_t                            fToXYZD50Hash;
+
+    float                               fTransferFn[7];
+    float                               fToXYZD50_3x3[9];    // row-major
+
+    mutable float                       fInvTransferFn[7];
+    mutable float                       fFromXYZD50_3x3[9];  // row-major
+    mutable SkOnce                      fLazyDstFieldsOnce;
+};
+
+#endif

+ 20 - 0
skia/include/core/SkColorSpaceXformCanvas.h

@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkColorSpaceXformCanvas_DEFINED
+#define SkColorSpaceXformCanvas_DEFINED
+
+#include <SkCanvas.h>
+#include <SkColorSpace.h>
+#include <memory>
+
+// Proxy SkCanvas calls to unowned target, transforming colors into targetCS as it goes.
+// May return nullptr if |targetCS| is unsupported.
+std::unique_ptr<SkCanvas> SK_API SkCreateColorSpaceXformCanvas(SkCanvas* target,
+                                                               sk_sp<SkColorSpace> targetCS);
+
+#endif  //SkColorSpaceXformCanvas_DEFINED

+ 30 - 0
skia/include/core/SkCoverageMode.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCoverageMode_DEFINED
+#define SkCoverageMode_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ *  Describes geometric operations (ala SkRegion::Op) that can be applied to coverage bytes.
+ *  These can be thought of as variants of porter-duff (SkBlendMode) modes, but only applied
+ *  to the alpha channel.
+ *
+ *  See SkMaskFilter for ways to use these when combining two different masks.
+ */
+enum class SkCoverageMode {
+    kUnion,             // A ∪ B    A+B-A*B
+    kIntersect,         // A ∩ B    A*B
+    kDifference,        // A - B    A*(1-B)
+    kReverseDifference, // B - A    B*(1-A)
+    kXor,               // A ⊕ B    A+B-2*A*B
+
+    kLast = kXor,
+};
+
+#endif

+ 182 - 0
skia/include/core/SkData.h

@@ -0,0 +1,182 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkData_DEFINED
+#define SkData_DEFINED
+
+#include <stdio.h>
+
+#include "SkRefCnt.h"
+
+class SkStream;
+
+/**
+ *  SkData holds an immutable data buffer. Not only is the data immutable,
+ *  but the actual ptr that is returned (by data() or bytes()) is guaranteed
+ *  to always be the same for the life of this instance.
+ */
+class SK_API SkData final : public SkNVRefCnt<SkData> {
+public:
+    /**
+     *  Returns the number of bytes stored.
+     */
+    size_t size() const { return fSize; }
+
+    bool isEmpty() const { return 0 == fSize; }
+
+    /**
+     *  Returns the ptr to the data.
+     */
+    const void* data() const { return fPtr; }
+
+    /**
+     *  Like data(), returns a read-only ptr into the data, but in this case
+     *  it is cast to uint8_t*, to make it easy to add an offset to it.
+     */
+    const uint8_t* bytes() const {
+        return reinterpret_cast<const uint8_t*>(fPtr);
+    }
+
+    /**
+     *  USE WITH CAUTION.
+     *  This call will assert that the refcnt is 1, as a precaution against modifying the
+     *  contents when another client/thread has access to the data.
+     */
+    void* writable_data() {
+        if (fSize) {
+            // only assert we're unique if we're not empty
+            SkASSERT(this->unique());
+        }
+        return fPtr;
+    }
+
+    /**
+     *  Helper to copy a range of the data into a caller-provided buffer.
+     *  Returns the actual number of bytes copied, after clamping offset and
+     *  length to the size of the data. If buffer is NULL, it is ignored, and
+     *  only the computed number of bytes is returned.
+     */
+    size_t copyRange(size_t offset, size_t length, void* buffer) const;
+
+    /**
+     *  Returns true if these two objects have the same length and contents,
+     *  effectively returning 0 == memcmp(...)
+     */
+    bool equals(const SkData* other) const;
+
+    /**
+     *  Function that, if provided, will be called when the SkData goes out
+     *  of scope, allowing for custom allocation/freeing of the data's contents.
+     */
+    typedef void (*ReleaseProc)(const void* ptr, void* context);
+
+    /**
+     *  Create a new dataref by copying the specified data
+     */
+    static sk_sp<SkData> MakeWithCopy(const void* data, size_t length);
+
+
+    /**
+     *  Create a new data with uninitialized contents. The caller should call writable_data()
+     *  to write into the buffer, but this must be done before another ref() is made.
+     */
+    static sk_sp<SkData> MakeUninitialized(size_t length);
+
+    /**
+     *  Create a new dataref by copying the specified c-string
+     *  (a null-terminated array of bytes). The returned SkData will have size()
+     *  equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
+     *  as "".
+     */
+    static sk_sp<SkData> MakeWithCString(const char cstr[]);
+
+    /**
+     *  Create a new dataref, taking the ptr as is, and using the
+     *  releaseproc to free it. The proc may be NULL.
+     */
+    static sk_sp<SkData> MakeWithProc(const void* ptr, size_t length, ReleaseProc proc, void* ctx);
+
+    /**
+     *  Call this when the data parameter is already const and will outlive the lifetime of the
+     *  SkData. Suitable for with const globals.
+     */
+    static sk_sp<SkData> MakeWithoutCopy(const void* data, size_t length) {
+        return MakeWithProc(data, length, DummyReleaseProc, nullptr);
+    }
+
+    /**
+     *  Create a new dataref from a pointer allocated by malloc. The Data object
+     *  takes ownership of that allocation, and will handling calling sk_free.
+     */
+    static sk_sp<SkData> MakeFromMalloc(const void* data, size_t length);
+
+    /**
+     *  Create a new dataref the file with the specified path.
+     *  If the file cannot be opened, this returns NULL.
+     */
+    static sk_sp<SkData> MakeFromFileName(const char path[]);
+
+    /**
+     *  Create a new dataref from a stdio FILE.
+     *  This does not take ownership of the FILE, nor close it.
+     *  The caller is free to close the FILE at its convenience.
+     *  The FILE must be open for reading only.
+     *  Returns NULL on failure.
+     */
+    static sk_sp<SkData> MakeFromFILE(FILE* f);
+
+    /**
+     *  Create a new dataref from a file descriptor.
+     *  This does not take ownership of the file descriptor, nor close it.
+     *  The caller is free to close the file descriptor at its convenience.
+     *  The file descriptor must be open for reading only.
+     *  Returns NULL on failure.
+     */
+    static sk_sp<SkData> MakeFromFD(int fd);
+
+    /**
+     *  Attempt to read size bytes into a SkData. If the read succeeds, return the data,
+     *  else return NULL. Either way the stream's cursor may have been changed as a result
+     *  of calling read().
+     */
+    static sk_sp<SkData> MakeFromStream(SkStream*, size_t size);
+
+    /**
+     *  Create a new dataref using a subset of the data in the specified
+     *  src dataref.
+     */
+    static sk_sp<SkData> MakeSubset(const SkData* src, size_t offset, size_t length);
+
+    /**
+     *  Returns a new empty dataref (or a reference to a shared empty dataref).
+     *  New or shared, the caller must see that unref() is eventually called.
+     */
+    static sk_sp<SkData> MakeEmpty();
+
+private:
+    friend class SkNVRefCnt<SkData>;
+    ReleaseProc fReleaseProc;
+    void*       fReleaseProcContext;
+    void*       fPtr;
+    size_t      fSize;
+
+    SkData(const void* ptr, size_t size, ReleaseProc, void* context);
+    explicit SkData(size_t size);   // inplace new/delete
+    ~SkData();
+
+    // Ensure the unsized delete is called.
+    void operator delete(void* p);
+
+    // shared internal factory
+    static sk_sp<SkData> PrivateNewWithCopy(const void* srcOrNull, size_t length);
+
+    static void DummyReleaseProc(const void*, void*); // {}
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 119 - 0
skia/include/core/SkDataTable.h

@@ -0,0 +1,119 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDataTable_DEFINED
+#define SkDataTable_DEFINED
+
+#include "../private/SkTDArray.h"
+#include "SkData.h"
+#include "SkString.h"
+
+/**
+ *  Like SkData, SkDataTable holds an immutable data buffer. The data buffer is
+ *  organized into a table of entries, each with a length, so the entries are
+ *  not required to all be the same size.
+ */
+class SK_API SkDataTable : public SkRefCnt {
+public:
+    /**
+     *  Returns true if the table is empty (i.e. has no entries).
+     */
+    bool isEmpty() const { return 0 == fCount; }
+
+    /**
+     *  Return the number of entries in the table. 0 for an empty table
+     */
+    int count() const { return fCount; }
+
+    /**
+     *  Return the size of the index'th entry in the table. The caller must
+     *  ensure that index is valid for this table.
+     */
+    size_t atSize(int index) const;
+
+    /**
+     *  Return a pointer to the data of the index'th entry in the table.
+     *  The caller must ensure that index is valid for this table.
+     *
+     *  @param size If non-null, this returns the byte size of this entry. This
+     *              will be the same value that atSize(index) would return.
+     */
+    const void* at(int index, size_t* size = nullptr) const;
+
+    template <typename T>
+    const T* atT(int index, size_t* size = nullptr) const {
+        return reinterpret_cast<const T*>(this->at(index, size));
+    }
+
+    /**
+     *  Returns the index'th entry as a c-string, and assumes that the trailing
+     *  null byte had been copied into the table as well.
+     */
+    const char* atStr(int index) const {
+        size_t size;
+        const char* str = this->atT<const char>(index, &size);
+        SkASSERT(strlen(str) + 1 == size);
+        return str;
+    }
+
+    typedef void (*FreeProc)(void* context);
+
+    static sk_sp<SkDataTable> MakeEmpty();
+
+    /**
+     *  Return a new DataTable that contains a copy of the data stored in each
+     *  "array".
+     *
+     *  @param ptrs array of points to each element to be copied into the table.
+     *  @param sizes array of byte-lengths for each entry in the corresponding
+     *               ptrs[] array.
+     *  @param count the number of array elements in ptrs[] and sizes[] to copy.
+     */
+    static sk_sp<SkDataTable> MakeCopyArrays(const void * const * ptrs,
+                                             const size_t sizes[], int count);
+
+    /**
+     *  Return a new table that contains a copy of the data in array.
+     *
+     *  @param array contiguous array of data for all elements to be copied.
+     *  @param elemSize byte-length for a given element.
+     *  @param count the number of entries to be copied out of array. The number
+     *               of bytes that will be copied is count * elemSize.
+     */
+    static sk_sp<SkDataTable> MakeCopyArray(const void* array, size_t elemSize, int count);
+
+    static sk_sp<SkDataTable> MakeArrayProc(const void* array, size_t elemSize, int count,
+                                            FreeProc proc, void* context);
+
+private:
+    struct Dir {
+        const void* fPtr;
+        uintptr_t   fSize;
+    };
+
+    int         fCount;
+    size_t      fElemSize;
+    union {
+        const Dir*  fDir;
+        const char* fElems;
+    } fU;
+
+    FreeProc    fFreeProc;
+    void*       fFreeProcContext;
+
+    SkDataTable();
+    SkDataTable(const void* array, size_t elemSize, int count,
+                FreeProc, void* context);
+    SkDataTable(const Dir*, int count, FreeProc, void* context);
+    virtual ~SkDataTable();
+
+    friend class SkDataTableBuilder;    // access to Dir
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 165 - 0
skia/include/core/SkDeferredDisplayListRecorder.h

@@ -0,0 +1,165 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeferredDisplayListMaker_DEFINED
+#define SkDeferredDisplayListMaker_DEFINED
+
+#include "SkImageInfo.h"
+#include "SkRefCnt.h"
+#include "SkSurfaceCharacterization.h"
+#include "SkTypes.h"
+
+#include "../private/SkDeferredDisplayList.h"
+
+class GrBackendFormat;
+class GrBackendTexture;
+class GrContext;
+
+class SkCanvas;
+class SkImage;
+class SkSurface;
+struct SkYUVAIndex;
+struct SkYUVASizeInfo;
+
+/*
+ * This class is intended to be used as:
+ *   Get an SkSurfaceCharacterization representing the intended gpu-backed destination SkSurface
+ *   Create one of these (an SkDDLMaker) on the stack
+ *   Get the canvas and render into it
+ *   Snap off and hold on to an SkDeferredDisplayList
+ *   Once your app actually needs the pixels, call SkSurface::draw(SkDeferredDisplayList*)
+ *
+ * This class never accesses the GPU but performs all the cpu work it can. It
+ * is thread-safe (i.e., one can break a scene into tiles and perform their cpu-side
+ * work in parallel ahead of time).
+ */
+class SK_API SkDeferredDisplayListRecorder {
+public:
+    SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&);
+    ~SkDeferredDisplayListRecorder();
+
+    const SkSurfaceCharacterization& characterization() const {
+        return fCharacterization;
+    }
+
+    // The backing canvas will become invalid (and this entry point will return
+    // null) once 'detach' is called.
+    // Note: ownership of the SkCanvas is not transfered via this call.
+    SkCanvas* getCanvas();
+
+    std::unique_ptr<SkDeferredDisplayList> detach();
+
+    // Matches the defines in SkImage_GpuBase.h
+    typedef void* TextureContext;
+    typedef void (*TextureReleaseProc)(TextureContext textureContext);
+    typedef void (*TextureFulfillProc)(TextureContext textureContext, GrBackendTexture* outTexture);
+    typedef void (*PromiseDoneProc)(TextureContext textureContext);
+
+    /**
+        Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main
+        difference is that the client doesn't have the backend texture on the gpu yet but they know
+        all the properties of the texture. So instead of passing in a GrBackendTexture the client
+        supplies a GrBackendFormat, width, height, and GrMipMapped state.
+
+        When we actually send the draw calls to the GPU, we will call the textureFulfillProc and
+        the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must
+        match those set during the SkImage creation, and it must have a valid backend gpu texture.
+        The gpu texture supplied by the client must stay valid until we call the textureReleaseProc.
+
+        When we are done with the texture returned by the textureFulfillProc we will call the
+        textureReleaseProc passing in the textureContext. This is a signal to the client that they
+        are free to delete the underlying gpu texture. If future draws also use the same promise
+        image we will call the textureFulfillProc again if we've already called the
+        textureReleaseProc. We will always call textureFulfillProc and textureReleaseProc in pairs.
+        In other words we will never call textureFulfillProc or textureReleaseProc multiple times
+        for the same textureContext before calling the other.
+
+        We call the promiseDoneProc when we will no longer call the textureFulfillProc again. We
+        pass in the textureContext as a parameter to the promiseDoneProc. We also guarantee that
+        there will be no outstanding textureReleaseProcs that still need to be called when we call
+        the textureDoneProc. Thus when the textureDoneProc gets called the client is able to cleanup
+        all GPU objects and meta data needed for the textureFulfill call.
+
+        This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context.
+
+        @param backendFormat       format of promised gpu texture
+        @param width               width of promised gpu texture
+        @param height              height of promised gpu texture
+        @param mipMapped           mip mapped state of promised gpu texture
+        @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param colorType           one of: kUnknown_SkColorType, kAlpha_8_SkColorType,
+                                   kRGB_565_SkColorType, kARGB_4444_SkColorType,
+                                   kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,
+                                   kGray_8_SkColorType, kRGBA_F16_SkColorType
+        @param alphaType           one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType,
+                                   kPremul_SkAlphaType, kUnpremul_SkAlphaType
+        @param colorSpace          range of colors; may be nullptr
+        @param textureFulfillProc  function called to get actual gpu texture
+        @param textureReleaseProc  function called when texture can be released
+        @param promiseDoneProc     function called when we will no longer call textureFulfillProc
+        @param textureContext      state passed to textureFulfillProc and textureReleaseProc
+        @return                    created SkImage, or nullptr
+     */
+    sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
+                                      int width,
+                                      int height,
+                                      GrMipMapped mipMapped,
+                                      GrSurfaceOrigin origin,
+                                      SkColorType colorType,
+                                      SkAlphaType alphaType,
+                                      sk_sp<SkColorSpace> colorSpace,
+                                      TextureFulfillProc textureFulfillProc,
+                                      TextureReleaseProc textureReleaseProc,
+                                      PromiseDoneProc promiseDoneProc,
+                                      TextureContext textureContext);
+
+    /**
+        This entry point operates the same as 'makePromiseTexture' except that its
+        textureFulfillProc can be called up to four times to fetch the required YUVA
+        planes (passing a different textureContext to each call). So, if the 'yuvaIndices'
+        indicate that only the first two backend textures are used, 'textureFulfillProc' will
+        be called with the first two 'textureContexts'.
+     */
+    sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
+                                          const GrBackendFormat yuvaFormats[],
+                                          const SkISize yuvaSizes[],
+                                          const SkYUVAIndex yuvaIndices[4],
+                                          int imageWidth,
+                                          int imageHeight,
+                                          GrSurfaceOrigin imageOrigin,
+                                          sk_sp<SkColorSpace> imageColorSpace,
+                                          TextureFulfillProc textureFulfillProc,
+                                          TextureReleaseProc textureReleaseProc,
+                                          PromiseDoneProc promiseDoneProc,
+                                          TextureContext textureContexts[]);
+
+    // deprecated version that doesn't take yuvaSizeInfo
+    sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
+                                          const GrBackendFormat yuvaFormats[],
+                                          const SkYUVAIndex yuvaIndices[4],
+                                          int imageWidth,
+                                          int imageHeight,
+                                          GrSurfaceOrigin imageOrigin,
+                                          sk_sp<SkColorSpace> imageColorSpace,
+                                          TextureFulfillProc textureFulfillProc,
+                                          TextureReleaseProc textureReleaseProc,
+                                          PromiseDoneProc promiseDoneProc,
+                                          TextureContext textureContexts[]);
+
+private:
+    bool init();
+
+    const SkSurfaceCharacterization             fCharacterization;
+
+#if SK_SUPPORT_GPU
+    sk_sp<GrContext>                            fContext;
+    sk_sp<SkDeferredDisplayList::LazyProxyData> fLazyProxyData;
+    sk_sp<SkSurface>                            fSurface;
+#endif
+};
+
+#endif

+ 139 - 0
skia/include/core/SkDeque.h

@@ -0,0 +1,139 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDeque_DEFINED
+#define SkDeque_DEFINED
+
+#include "../private/SkNoncopyable.h"
+#include "SkTypes.h"
+
+/*
+ * The deque class works by blindly creating memory space of a specified element
+ * size. It manages the memory as a doubly linked list of blocks each of which
+ * can contain multiple elements. Pushes and pops add/remove blocks from the
+ * beginning/end of the list as necessary while each block tracks the used
+ * portion of its memory.
+ * One behavior to be aware of is that the pops do not immediately remove an
+ * empty block from the beginning/end of the list (Presumably so push/pop pairs
+ * on the block boundaries don't cause thrashing). This can result in the first/
+ * last element not residing in the first/last block.
+ */
+class SK_API SkDeque : SkNoncopyable {
+public:
+    /**
+     * elemSize specifies the size of each individual element in the deque
+     * allocCount specifies how many elements are to be allocated as a block
+     */
+    explicit SkDeque(size_t elemSize, int allocCount = 1);
+    SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCount = 1);
+    ~SkDeque();
+
+    bool    empty() const { return 0 == fCount; }
+    int     count() const { return fCount; }
+    size_t  elemSize() const { return fElemSize; }
+
+    const void* front() const { return fFront; }
+    const void* back() const  { return fBack; }
+
+    void* front() {
+        return (void*)((const SkDeque*)this)->front();
+    }
+
+    void* back() {
+        return (void*)((const SkDeque*)this)->back();
+    }
+
+    /**
+     * push_front and push_back return a pointer to the memory space
+     * for the new element
+     */
+    void* push_front();
+    void* push_back();
+
+    void pop_front();
+    void pop_back();
+
+private:
+    struct Block;
+
+public:
+    class Iter {
+    public:
+        enum IterStart {
+            kFront_IterStart,
+            kBack_IterStart,
+        };
+
+        /**
+         * Creates an uninitialized iterator. Must be reset()
+         */
+        Iter();
+
+        Iter(const SkDeque& d, IterStart startLoc);
+        void* next();
+        void* prev();
+
+        void reset(const SkDeque& d, IterStart startLoc);
+
+    private:
+        SkDeque::Block* fCurBlock;
+        char*           fPos;
+        size_t          fElemSize;
+    };
+
+    // Inherit privately from Iter to prevent access to reverse iteration
+    class F2BIter : private Iter {
+    public:
+        F2BIter() {}
+
+        /**
+         * Wrap Iter's 2 parameter ctor to force initialization to the
+         * beginning of the deque
+         */
+        F2BIter(const SkDeque& d) : INHERITED(d, kFront_IterStart) {}
+
+        using Iter::next;
+
+        /**
+         * Wrap Iter::reset to force initialization to the beginning of the
+         * deque
+         */
+        void reset(const SkDeque& d) {
+            this->INHERITED::reset(d, kFront_IterStart);
+        }
+
+    private:
+        typedef Iter INHERITED;
+    };
+
+private:
+    // allow unit test to call numBlocksAllocated
+    friend class DequeUnitTestHelper;
+
+    void*   fFront;
+    void*   fBack;
+
+    Block*  fFrontBlock;
+    Block*  fBackBlock;
+    size_t  fElemSize;
+    void*   fInitialStorage;
+    int     fCount;             // number of elements in the deque
+    int     fAllocCount;        // number of elements to allocate per block
+
+    Block*  allocateBlock(int allocCount);
+    void    freeBlock(Block* block);
+
+    /**
+     * This returns the number of chunk blocks allocated by the deque. It
+     * can be used to gauge the effectiveness of the selected allocCount.
+     */
+    int  numBlocksAllocated() const;
+};
+
+#endif

+ 91 - 0
skia/include/core/SkDocument.h

@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDocument_DEFINED
+#define SkDocument_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+
+class SkCanvas;
+class SkWStream;
+struct SkRect;
+
+/** SK_ScalarDefaultDPI is 72 dots per inch. */
+static constexpr SkScalar SK_ScalarDefaultRasterDPI = 72.0f;
+
+/**
+ *  High-level API for creating a document-based canvas. To use..
+ *
+ *  1. Create a document, specifying a stream to store the output.
+ *  2. For each "page" of content:
+ *      a. canvas = doc->beginPage(...)
+ *      b. draw_my_content(canvas);
+ *      c. doc->endPage();
+ *  3. Close the document with doc->close().
+ */
+class SK_API SkDocument : public SkRefCnt {
+public:
+
+    /**
+     *  Begin a new page for the document, returning the canvas that will draw
+     *  into the page. The document owns this canvas, and it will go out of
+     *  scope when endPage() or close() is called, or the document is deleted.
+     */
+    SkCanvas* beginPage(SkScalar width, SkScalar height, const SkRect* content = nullptr);
+
+    /**
+     *  Call endPage() when the content for the current page has been drawn
+     *  (into the canvas returned by beginPage()). After this call the canvas
+     *  returned by beginPage() will be out-of-scope.
+     */
+    void endPage();
+
+    /**
+     *  Call close() when all pages have been drawn. This will close the file
+     *  or stream holding the document's contents. After close() the document
+     *  can no longer add new pages. Deleting the document will automatically
+     *  call close() if need be.
+     */
+    void close();
+
+    /**
+     *  Call abort() to stop producing the document immediately.
+     *  The stream output must be ignored, and should not be trusted.
+     */
+    void abort();
+
+protected:
+    SkDocument(SkWStream*);
+
+    // note: subclasses must call close() in their destructor, as the base class
+    // cannot do this for them.
+    virtual ~SkDocument();
+
+    virtual SkCanvas* onBeginPage(SkScalar width, SkScalar height) = 0;
+    virtual void onEndPage() = 0;
+    virtual void onClose(SkWStream*) = 0;
+    virtual void onAbort() = 0;
+
+    // Allows subclasses to write to the stream as pages are written.
+    SkWStream* getStream() { return fStream; }
+
+    enum State {
+        kBetweenPages_State,
+        kInPage_State,
+        kClosed_State
+    };
+    State getState() const { return fState; }
+
+private:
+    SkWStream* fStream;
+    State      fState;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 129 - 0
skia/include/core/SkDrawLooper.h

@@ -0,0 +1,129 @@
+
+/*
+ * Copyright 2011 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkDrawLooper_DEFINED
+#define SkDrawLooper_DEFINED
+
+#include "../private/SkNoncopyable.h"
+#include "SkBlurTypes.h"
+#include "SkFlattenable.h"
+#include "SkPoint.h"
+#include "SkColor.h"
+
+class  SkArenaAlloc;
+class  SkCanvas;
+class  SkColorSpaceXformer;
+class  SkPaint;
+struct SkRect;
+class  SkString;
+
+/** \class SkDrawLooper
+    Subclasses of SkDrawLooper can be attached to a SkPaint. Where they are,
+    and something is drawn to a canvas with that paint, the looper subclass will
+    be called, allowing it to modify the canvas and/or paint for that draw call.
+    More than that, via the next() method, the looper can modify the draw to be
+    invoked multiple times (hence the name loop-er), allow it to perform effects
+    like shadows or frame/fills, that require more than one pass.
+*/
+class SK_API SkDrawLooper : public SkFlattenable {
+public:
+    /**
+     *  Holds state during a draw. Users call next() until it returns false.
+     *
+     *  Subclasses of SkDrawLooper should create a subclass of this object to
+     *  hold state specific to their subclass.
+     */
+    class SK_API Context : ::SkNoncopyable {
+    public:
+        Context() {}
+        virtual ~Context() {}
+
+        /**
+         *  Called in a loop on objects returned by SkDrawLooper::createContext().
+         *  Each time true is returned, the object is drawn (possibly with a modified
+         *  canvas and/or paint). When false is finally returned, drawing for the object
+         *  stops.
+         *
+         *  On each call, the paint will be in its original state, but the
+         *  canvas will be as it was following the previous call to next() or
+         *  createContext().
+         *
+         *  The implementation must ensure that, when next() finally returns
+         *  false, the canvas has been restored to the state it was
+         *  initially, before createContext() was first called.
+         */
+        virtual bool next(SkCanvas* canvas, SkPaint* paint) = 0;
+    };
+
+    /**
+     *  Called right before something is being drawn. Returns a Context
+     *  whose next() method should be called until it returns false.
+     */
+    virtual Context* makeContext(SkCanvas*, SkArenaAlloc*) const = 0;
+
+    /**
+     * The fast bounds functions are used to enable the paint to be culled early
+     * in the drawing pipeline. If a subclass can support this feature it must
+     * return true for the canComputeFastBounds() function.  If that function
+     * returns false then computeFastBounds behavior is undefined otherwise it
+     * is expected to have the following behavior. Given the parent paint and
+     * the parent's bounding rect the subclass must fill in and return the
+     * storage rect, where the storage rect is with the union of the src rect
+     * and the looper's bounding rect.
+     */
+    bool canComputeFastBounds(const SkPaint& paint) const;
+    void computeFastBounds(const SkPaint& paint, const SkRect& src, SkRect* dst) const;
+
+    struct BlurShadowRec {
+        SkScalar        fSigma;
+        SkVector        fOffset;
+        SkColor         fColor;
+        SkBlurStyle     fStyle;
+    };
+    /**
+     *  If this looper can be interpreted as having two layers, such that
+     *      1. The first layer (bottom most) just has a blur and translate
+     *      2. The second layer has no modifications to either paint or canvas
+     *      3. No other layers.
+     *  then return true, and if not null, fill out the BlurShadowRec).
+     *
+     *  If any of the above are not met, return false and ignore the BlurShadowRec parameter.
+     */
+    virtual bool asABlurShadow(BlurShadowRec*) const;
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkDrawLooper_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkDrawLooper_Type;
+    }
+
+    static sk_sp<SkDrawLooper> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkDrawLooper>(static_cast<SkDrawLooper*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkDrawLooper_Type, data, size, procs).release()));
+    }
+
+protected:
+    sk_sp<SkDrawLooper> makeColorSpace(SkColorSpaceXformer* xformer) const {
+        return this->onMakeColorSpace(xformer);
+    }
+    virtual sk_sp<SkDrawLooper> onMakeColorSpace(SkColorSpaceXformer*) const = 0;
+
+    SkDrawLooper() {}
+
+private:
+    friend class SkColorSpaceXformer;
+
+    typedef SkFlattenable INHERITED;
+};
+
+#endif

+ 150 - 0
skia/include/core/SkDrawable.h

@@ -0,0 +1,150 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDrawable_DEFINED
+#define SkDrawable_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkScalar.h"
+
+class GrBackendDrawableInfo;
+class SkCanvas;
+class SkMatrix;
+class SkPicture;
+enum class GrBackendApi : unsigned;
+struct SkRect;
+
+/**
+ *  Base-class for objects that draw into SkCanvas.
+ *
+ *  The object has a generation ID, which is guaranteed to be unique across all drawables. To
+ *  allow for clients of the drawable that may want to cache the results, the drawable must
+ *  change its generation ID whenever its internal state changes such that it will draw differently.
+ */
+class SK_API SkDrawable : public SkFlattenable {
+public:
+    /**
+     *  Draws into the specified content. The drawing sequence will be balanced upon return
+     *  (i.e. the saveLevel() on the canvas will match what it was when draw() was called,
+     *  and the current matrix and clip settings will not be changed.
+     */
+    void draw(SkCanvas*, const SkMatrix* = nullptr);
+    void draw(SkCanvas*, SkScalar x, SkScalar y);
+
+    /**
+     *  When using the GPU backend it is possible for a drawable to execute using the underlying 3D
+     *  API rather than the SkCanvas API. It does so by creating a GpuDrawHandler. The GPU backend
+     *  is deferred so the handler will be given access to the 3D API at the correct point in the
+     *  drawing stream as the GPU backend flushes. Since the drawable may mutate, each time it is
+     *  drawn to a GPU-backed canvas a new handler is snapped, representing the drawable's state at
+     *  the time of the snap.
+     *
+     *  When the GPU backend flushes to the 3D API it will call the draw method on the
+     *  GpuDrawHandler. At this time the drawable may add commands to the stream of GPU commands for
+     *  the unerlying 3D API. The draw function takes a GrBackendDrawableInfo which contains
+     *  information about the current state of 3D API which the caller must respect. See
+     *  GrBackendDrawableInfo for more specific details on what information is sent and the
+     *  requirements for different 3D APIs.
+     *
+     *  Additionaly there may be a slight delay from when the drawable adds its commands to when
+     *  those commands are actually submitted to the GPU. Thus the drawable or GpuDrawHandler is
+     *  required to keep any resources that are used by its added commands alive and valid until
+     *  those commands are submitted to the GPU. The GpuDrawHandler will be kept alive and then
+     *  deleted once the commands are submitted to the GPU. The dtor of the GpuDrawHandler is the
+     *  signal to the drawable that the commands have all been submitted. Different 3D APIs may have
+     *  additional requirements for certain resources which require waiting for the GPU to finish
+     *  all work on those resources before reusing or deleting them. In this case, the drawable can
+     *  use the dtor call of the GpuDrawHandler to add a fence to the GPU to track when the GPU work
+     *  has completed.
+     *
+     *  Currently this is only supported for the GPU Vulkan backend.
+     */
+
+    class GpuDrawHandler {
+    public:
+        virtual ~GpuDrawHandler() {}
+
+        virtual void draw(const GrBackendDrawableInfo&) {}
+    };
+
+    /**
+     * Snaps off a GpuDrawHandler to represent the state of the SkDrawable at the time the snap is
+     * called. This is used for executing GPU backend specific draws intermixed with normal Skia GPU
+     * draws. The GPU API, which will be used for the draw, as well as the full matrix are passed in
+     * as inputs.
+     */
+    std::unique_ptr<GpuDrawHandler> snapGpuDrawHandler(GrBackendApi backendApi,
+                                                       const SkMatrix& matrix) {
+        return this->onSnapGpuDrawHandler(backendApi, matrix);
+    }
+
+    SkPicture* newPictureSnapshot();
+
+    /**
+     *  Return a unique value for this instance. If two calls to this return the same value,
+     *  it is presumed that calling the draw() method will render the same thing as well.
+     *
+     *  Subclasses that change their state should call notifyDrawingChanged() to ensure that
+     *  a new value will be returned the next time it is called.
+     */
+    uint32_t getGenerationID();
+
+    /**
+     *  Return the (conservative) bounds of what the drawable will draw. If the drawable can
+     *  change what it draws (e.g. animation or in response to some external change), then this
+     *  must return a bounds that is always valid for all possible states.
+     */
+    SkRect getBounds();
+
+    /**
+     *  Calling this invalidates the previous generation ID, and causes a new one to be computed
+     *  the next time getGenerationID() is called. Typically this is called by the object itself,
+     *  in response to its internal state changing.
+     */
+    void notifyDrawingChanged();
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkDrawable_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkDrawable_Type;
+    }
+
+    static sk_sp<SkDrawable> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkDrawable>(static_cast<SkDrawable*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkDrawable_Type, data, size, procs).release()));
+    }
+
+    Factory getFactory() const override { return nullptr; }
+    const char* getTypeName() const override { return nullptr; }
+
+protected:
+    SkDrawable();
+
+    virtual SkRect onGetBounds() = 0;
+    virtual void onDraw(SkCanvas*) = 0;
+
+    virtual std::unique_ptr<GpuDrawHandler> onSnapGpuDrawHandler(GrBackendApi, const SkMatrix&) {
+        return nullptr;
+    }
+
+    /**
+     *  Default implementation calls onDraw() with a canvas that records into a picture. Subclasses
+     *  may override if they have a more efficient way to return a picture for the current state
+     *  of their drawable. Note: this picture must draw the same as what would be drawn from
+     *  onDraw().
+     */
+    virtual SkPicture* onNewPictureSnapshot();
+
+private:
+    int32_t fGenerationID;
+};
+
+#endif

+ 34 - 0
skia/include/core/SkEncodedImageFormat.h

@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkEncodedImageFormat_DEFINED
+#define SkEncodedImageFormat_DEFINED
+
+#include <stdint.h>
+
+/**
+ *  Enum describing format of encoded data.
+ */
+enum class SkEncodedImageFormat {
+#ifdef SK_BUILD_FOR_GOOGLE3
+    kUnknown,
+#endif
+    kBMP,
+    kGIF,
+    kICO,
+    kJPEG,
+    kPNG,
+    kWBMP,
+    kWEBP,
+    kPKM,
+    kKTX,
+    kASTC,
+    kDNG,
+    kHEIF,
+};
+
+#endif  // SkEncodedImageFormat_DEFINED

+ 33 - 0
skia/include/core/SkExecutor.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkExecutor_DEFINED
+#define SkExecutor_DEFINED
+
+#include <functional>
+#include <memory>
+
+class SkExecutor {
+public:
+    virtual ~SkExecutor();
+
+    // Create a thread pool SkExecutor with a fixed thread count, by default the number of cores.
+    static std::unique_ptr<SkExecutor> MakeFIFOThreadPool(int threads = 0);
+    static std::unique_ptr<SkExecutor> MakeLIFOThreadPool(int threads = 0);
+
+    // There is always a default SkExecutor available by calling SkExecutor::GetDefault().
+    static SkExecutor& GetDefault();
+    static void SetDefault(SkExecutor*);  // Does not take ownership.  Not thread safe.
+
+    // Add work to execute.
+    virtual void add(std::function<void(void)>) = 0;
+
+    // If it makes sense for this executor, use this thread to execute work for a little while.
+    virtual void borrow() {}
+};
+
+#endif//SkExecutor_DEFINED

+ 26 - 0
skia/include/core/SkFilterQuality.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFilterQuality_DEFINED
+#define SkFilterQuality_DEFINED
+
+#include "SkTypes.h"
+
+/**
+ *  Controls how much filtering to be done when scaling/transforming complex colors
+ *  e.g. images
+ */
+enum SkFilterQuality {
+    kNone_SkFilterQuality,      //!< fastest but lowest quality, typically nearest-neighbor
+    kLow_SkFilterQuality,       //!< typically bilerp
+    kMedium_SkFilterQuality,    //!< typically bilerp + mipmaps for down-scaling
+    kHigh_SkFilterQuality,      //!< slowest but highest quality, typically bicubic or better
+
+    kLast_SkFilterQuality = kHigh_SkFilterQuality,
+};
+
+#endif

+ 107 - 0
skia/include/core/SkFlattenable.h

@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFlattenable_DEFINED
+#define SkFlattenable_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkData;
+class SkReadBuffer;
+class SkWriteBuffer;
+
+struct SkSerialProcs;
+struct SkDeserialProcs;
+
+/** \class SkFlattenable
+
+ SkFlattenable is the base class for objects that need to be flattened
+ into a data stream for either transport or as part of the key to the
+ font cache.
+ */
+class SK_API SkFlattenable : public SkRefCnt {
+public:
+    enum Type {
+        kSkColorFilter_Type,
+        kSkDrawable_Type,
+        kSkDrawLooper_Type,
+        kSkImageFilter_Type,
+        kSkMaskFilter_Type,
+        kSkPathEffect_Type,
+        kSkPixelRef_Type,
+        kSkUnused_Type4,    // used to be SkRasterizer
+        kSkShaderBase_Type,
+        kSkUnused_Type,     // used to be SkUnitMapper
+        kSkUnused_Type2,
+        kSkNormalSource_Type,
+    };
+
+    typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);
+
+    SkFlattenable() {}
+
+    /** Implement this to return a factory function pointer that can be called
+     to recreate your class given a buffer (previously written to by your
+     override of flatten().
+     */
+    virtual Factory getFactory() const = 0;
+
+    /**
+     *  Returns the name of the object's class.
+     */
+    virtual const char* getTypeName() const = 0;
+
+    static Factory NameToFactory(const char name[]);
+    static const char* FactoryToName(Factory);
+
+    static void Register(const char name[], Factory);
+
+    /**
+     *  Override this if your subclass needs to record data that it will need to recreate itself
+     *  from its CreateProc (returned by getFactory()).
+     *
+     *  DEPRECATED public : will move to protected ... use serialize() instead
+     */
+    virtual void flatten(SkWriteBuffer&) const {}
+
+    virtual Type getFlattenableType() const = 0;
+
+    //
+    // public ways to serialize / deserialize
+    //
+    sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;
+    size_t serialize(void* memory, size_t memory_size,
+                     const SkSerialProcs* = nullptr) const;
+    static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
+                                            const SkDeserialProcs* procs = nullptr);
+
+protected:
+    class PrivateInitializer {
+    public:
+        static void InitEffects();
+        static void InitImageFilters();
+    };
+
+private:
+    static void RegisterFlattenablesIfNeeded();
+    static void Finalize();
+
+    friend class SkGraphics;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#define SK_REGISTER_FLATTENABLE(type) \
+    SkFlattenable::Register(#type, type::CreateProc);
+
+#define SK_FLATTENABLE_HOOKS(type)                                   \
+    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);           \
+    friend class SkFlattenable::PrivateInitializer;                  \
+    Factory getFactory() const override { return type::CreateProc; } \
+    const char* getTypeName() const override { return #type; }
+
+#endif

+ 488 - 0
skia/include/core/SkFont.h

@@ -0,0 +1,488 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFont_DEFINED
+#define SkFont_DEFINED
+
+#include "SkFontTypes.h"
+#include "SkScalar.h"
+#include "SkTypeface.h"
+
+class SkMatrix;
+class SkPaint;
+class SkPath;
+struct SkFontMetrics;
+
+/** \class SkFont
+    SkFont controls options applied when drawing and measuring text.
+*/
+class SK_API SkFont {
+public:
+    /** Whether edge pixels draw opaque or with partial transparency.
+    */
+    enum class Edging {
+        kAlias,              //!< no transparent pixels on glyph edges
+        kAntiAlias,          //!< may have transparent pixels on glyph edges
+        kSubpixelAntiAlias,  //!< glyph positioned in pixel using transparency
+    };
+
+#ifdef SK_SUPPORT_LEGACY_NESTED_HINTINGENUM
+    /** Amount of font hinting applied to glyph outlines.
+    */
+    enum Hinting : uint8_t {
+        kNo_Hinting     = 0, //!< glyph outlines unchanged
+        kSlight_Hinting = 1, //!< minimal modification to improve constrast
+        kNormal_Hinting = 2, //!< glyph outlines modified to improve constrast
+        kFull_Hinting   = 3, //!< modifies glyph outlines for maximum constrast
+    };
+#endif
+
+    /** Constructs SkFont with default values.
+
+        @return  default initialized SkFont
+    */
+    SkFont();
+
+    /** Constructs SkFont with default values with SkTypeface and size in points.
+
+        @param typeface  font and style used to draw and measure text
+        @param size      typographic height of text
+        @return          initialized SkFont
+    */
+    SkFont(sk_sp<SkTypeface> typeface, SkScalar size);
+
+
+    /** Constructs SkFont with default values with SkTypeface and size in points,
+        horizontal scale, and horizontal skew. Horizontal scale emulates condensed
+        and expanded fonts. Horizontal skew emulates oblique fonts.
+
+        @param typeface  font and style used to draw and measure text
+        @param size      typographic height of text
+        @param scaleX    text horizontal scale
+        @param skewX     additional shear on x-axis relative to y-axis
+        @return          initialized SkFont
+    */
+    SkFont(sk_sp<SkTypeface> typeface, SkScalar size, SkScalar scaleX, SkScalar skewX);
+
+
+    /** Compares SkFont and font, and returns true if they are equivalent.
+        May return false if SkTypeface has identical contents but different pointers.
+
+        @param font  SkPaint to compare
+        @return      true if SkFont pair are equivalent
+    */
+    bool operator==(const SkFont& font) const;
+
+    /** If true, instructs the font manager to always hint glyphs.
+        Returned value is only meaningful if platform uses FreeType as the font manager.
+
+        @return  true if all glyphs are hinted
+    */
+    bool isForceAutoHinting() const { return SkToBool(fFlags & kForceAutoHinting_PrivFlag); }
+
+    /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
+
+        @return  true if glyphs may be font bitmaps
+    */
+    bool isEmbeddedBitmaps() const { return SkToBool(fFlags & kEmbeddedBitmaps_PrivFlag); }
+
+    /** Returns true if glyphs at different sub-pixel positions may differ on pixel edge coverage.
+
+        @return  true if glyph positioned in pixel using transparency
+    */
+    bool isSubpixel() const { return SkToBool(fFlags & kSubpixel_PrivFlag); }
+
+    /** Returns true if text is converted to SkPath before drawing and measuring.
+
+        @return  true glyph hints are never applied
+    */
+    bool isLinearMetrics() const { return SkToBool(fFlags & kLinearMetrics_PrivFlag); }
+
+    /** Returns true if bold is approximated by increasing the stroke width when creating glyph
+        bitmaps from outlines.
+
+        @return  bold is approximated through stroke width
+    */
+    bool isEmbolden() const { return SkToBool(fFlags & kEmbolden_PrivFlag); }
+
+    /** Sets whether to always hint glyphs.
+        If forceAutoHinting is set, instructs the font manager to always hint glyphs.
+
+        Only affects platforms that use FreeType as the font manager.
+
+        @param forceAutoHinting  setting to always hint glyphs
+    */
+    void setForceAutoHinting(bool forceAutoHinting);
+
+    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
+
+        @param embeddedBitmaps  setting to use bitmaps in fonts
+    */
+    void setEmbeddedBitmaps(bool embeddedBitmaps);
+
+    /** Requests, but does not require, that glyphs respect sub-pixel positioning.
+
+        @param subpixel  setting for sub-pixel positioning
+    */
+    void setSubpixel(bool subpixel);
+
+    /** Requests, but does not require, that glyphs are converted to SkPath
+        before drawing and measuring.
+
+        @param linearMetrics  setting for converting glyphs to paths
+    */
+    void setLinearMetrics(bool linearMetrics);
+
+    /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
+
+        @param embolden  setting for bold approximation
+    */
+    void setEmbolden(bool embolden);
+
+    /** Whether edge pixels draw opaque or with partial transparency.
+
+        @return  one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
+    */
+    Edging getEdging() const { return (Edging)fEdging; }
+
+    /** Requests, but does not require, that edge pixels draw opaque or with
+        partial transparency.
+
+        @param edging  one of: Edging::kAlias, Edging::kAntiAlias, Edging::kSubpixelAntiAlias
+    */
+    void setEdging(Edging edging);
+
+    /** Sets level of glyph outline adjustment.
+        Does not check for valid values of hintingLevel.
+
+        @param hintingLevel  one of: SkFontHinting::kNone, SkFontHinting::kSlight,
+                                     SkFontHinting::kNormal, SkFontHinting::kFull
+    */
+    void setHinting(SkFontHinting hintingLevel);
+
+    /** Returns level of glyph outline adjustment.
+
+        @return  one of: SkFontHinting::kNone, SkFontHinting::kSlight, SkFontHinting::kNormal,
+                         SkFontHinting::kFull
+     */
+    SkFontHinting getHinting() const { return (SkFontHinting)fHinting; }
+
+    /** Returns a font with the same attributes of this font, but with the specified size.
+        Returns nullptr if size is less than zero, infinite, or NaN.
+
+        @param size  typographic height of text
+        @return      initialized SkFont
+     */
+    SkFont makeWithSize(SkScalar size) const;
+
+    /** Returns SkTypeface if set, or nullptr.
+        Does not alter SkTypeface SkRefCnt.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    SkTypeface* getTypeface() const { return fTypeface.get(); }
+
+    /** Returns text size in points.
+
+        @return  typographic height of text
+    */
+    SkScalar    getSize() const { return fSize; }
+
+    /** Returns text scale on x-axis.
+        Default value is 1.
+
+        @return  text horizontal scale
+    */
+    SkScalar    getScaleX() const { return fScaleX; }
+
+    /** Returns text skew on x-axis.
+        Default value is zero.
+
+        @return  additional shear on x-axis relative to y-axis
+    */
+    SkScalar    getSkewX() const { return fSkewX; }
+
+    /** Increases SkTypeface SkRefCnt by one.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
+
+    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
+        Pass nullptr to clear SkTypeface and use the default typeface. Increments
+        tf SkRefCnt by one.
+
+        @param tf  font and style used to draw text
+    */
+    void setTypeface(sk_sp<SkTypeface> tf) { fTypeface = tf; }
+
+    /** Sets text size in points.
+        Has no effect if textSize is not greater than or equal to zero.
+
+        @param textSize  typographic height of text
+    */
+    void setSize(SkScalar textSize);
+
+    /** Sets text scale on x-axis.
+        Default value is 1.
+
+        @param scaleX  text horizontal scale
+    */
+    void setScaleX(SkScalar scaleX);
+
+    /** Sets text skew on x-axis.
+        Default value is zero.
+
+        @param skewX  additional shear on x-axis relative to y-axis
+    */
+    void setSkewX(SkScalar skewX);
+
+    /** Converts text into glyph indices.
+        Returns the number of glyph indices represented by text.
+        SkTextEncoding specifies how text represents characters or glyphs.
+        glyphs may be nullptr, to compute the glyph count.
+
+        Does not check text for valid character codes or valid glyph indices.
+
+        If byteLength equals zero, returns zero.
+        If byteLength includes a partial character, the partial character is ignored.
+
+        If encoding is kUTF8_SkTextEncoding and text contains an invalid UTF-8 sequence,
+        zero is returned.
+
+        If maxGlyphCount is not sufficient to store all the glyphs, no glyphs are copied.
+        The total glyph count is returned for subsequent buffer reallocation.
+
+        @param text          character storage encoded with SkPaint::TextEncoding
+        @param byteLength    length of character storage in bytes
+        @param encoding      one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                             kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @param glyphs        storage for glyph indices; may be nullptr
+        @param maxGlyphCount storage capacity
+        @return              number of glyphs represented by text of length byteLength
+    */
+    int textToGlyphs(const void* text, size_t byteLength, SkTextEncoding encoding,
+                     SkGlyphID glyphs[], int maxGlyphCount) const;
+
+    /** Returns glyph index for Unicode character.
+
+        @param uni  Unicode character
+        @return     glyph index
+    */
+    uint16_t unicharToGlyph(SkUnichar uni) const {
+        return fTypeface->unicharToGlyph(uni);
+    }
+
+    /** Returns number of glyphs represented by text.
+
+        @param text          character storage encoded with SkPaint::TextEncoding
+        @param byteLength    length of character storage in bytes
+        @param encoding      one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                             kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @return              number of glyphs represented by text of length byteLength
+    */
+    int countText(const void* text, size_t byteLength, SkTextEncoding encoding) const {
+        return this->textToGlyphs(text, byteLength, encoding, nullptr, 0);
+    }
+
+    /** Returns true if all text corresponds to a non-zero glyph index.
+        Returns false if any characters in text are not supported in
+        SkTypeface.
+
+        If SkTextEncoding is kGlyphID_SkTextEncoding,
+        returns true if all glyph indices in text are non-zero;
+        does not check to see if text contains valid glyph indices for SkTypeface.
+
+        Returns true if byteLength is zero.
+
+        @param text        array of characters or glyphs
+        @param byteLength  number of bytes in text array
+        @param encoding    text encoding
+        @return            true if all text corresponds to a non-zero glyph index
+     */
+    bool containsText(const void* text, size_t byteLength, SkTextEncoding encoding) const;
+
+    /** Returns the advance width of text.
+        The advance is the normal distance to move before drawing additional text.
+        Returns the bounding box of text if bounds is not nullptr.
+
+        @param text        character storage encoded with SkPaint::TextEncoding
+        @param byteLength  length of character storage in bytes
+        @param encoding    one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
+                           kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
+        @param bounds      returns bounding box relative to (0, 0) if not nullptr
+        @return            number of glyphs represented by text of length byteLength
+    */
+    SkScalar measureText(const void* text, size_t byteLength, SkTextEncoding encoding,
+                         SkRect* bounds = nullptr) const;
+
+    /** DEPRECATED
+        Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph; may be nullptr
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+    */
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[], SkRect bounds[]) const {
+        this->getWidthsBounds(glyphs, count, widths, bounds, nullptr);
+    }
+
+    // DEPRECATED
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[], std::nullptr_t) const {
+        this->getWidths(glyphs, count, widths);
+    }
+
+    /** Experimental
+        Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph
+     */
+    void getWidths(const uint16_t glyphs[], int count, SkScalar widths[]) const {
+        this->getWidthsBounds(glyphs, count, widths, nullptr, nullptr);
+    }
+
+    /** Experimental.
+        Retrieves the advance and bounds for each glyph in glyphs.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of count entries.
+        if bounds is not nullptr, bounds must be an array of count entries.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param widths      returns text advances for each glyph; may be nullptr
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+        @param paint       optional, specifies stroking, patheffect and maskfilter
+     */
+    void getWidthsBounds(const uint16_t glyphs[], int count, SkScalar widths[], SkRect bounds[],
+                         const SkPaint* paint) const;
+
+
+    /** Experimental.
+        Retrieves the bounds for each glyph in glyphs.
+        bounds must be an array of count entries.
+        If paint is not nullptr, its stroking, patheffect and maskfilter fields will be respected.
+
+        @param glyphs      array of glyph indices to be measured
+        @param count       number of glyphs
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+        @param paint       optional, specifies stroking, patheffect and maskfilter
+     */
+    void getBounds(const uint16_t glyphs[], int count, SkRect bounds[], const SkPaint* paint) const {
+        this->getWidthsBounds(glyphs, count, nullptr, bounds, paint);
+    }
+
+    /** Experimental
+        Retrieves the positions for each glyph, beginning at the specified origin. The caller
+        must allocated at least count number of elements in the pos[] array.
+
+        @param glyphs   array of glyph indices to be positioned
+        @param count    number of glyphs
+        @param pos      returns glyphs positions
+        @param origin   location of the first glyph. Defaults to {0, 0}.
+     */
+    void getPos(const uint16_t glyphs[], int count, SkPoint pos[], SkPoint origin = {0, 0}) const;
+
+    /** Experimental
+        Retrieves the x-positions for each glyph, beginning at the specified origin. The caller
+        must allocated at least count number of elements in the xpos[] array.
+
+        @param glyphs   array of glyph indices to be positioned
+        @param count    number of glyphs
+        @param xpos     returns glyphs x-positions
+        @param origin   x-position of the first glyph. Defaults to 0.
+     */
+    void getXPos(const uint16_t glyphs[], int count, SkScalar xpos[], SkScalar origin = 0) const;
+
+    /** Returns path corresponding to glyph outline.
+        If glyph has an outline, copies outline to path and returns true.
+        path returned may be empty.
+        If glyph is described by a bitmap, returns false and ignores path parameter.
+
+        @param glyphID  index of glyph
+        @param path     pointer to existing SkPath
+        @return         true if glyphID is described by path
+     */
+    bool getPath(uint16_t glyphID, SkPath* path) const;
+
+    /** Returns path corresponding to glyph array.
+
+        @param glyphIDs      array of glyph indices
+        @param count         number of glyphs
+        @param glyphPathProc function returning one glyph description as path
+        @param ctx           function context
+   */
+    void getPaths(const uint16_t glyphIDs[], int count,
+                  void (*glyphPathProc)(const SkPath* pathOrNull, const SkMatrix& mx, void* ctx),
+                  void* ctx) const;
+
+    /** Returns SkFontMetrics associated with SkTypeface.
+        The return value is the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        If metrics is not nullptr, SkFontMetrics is copied to metrics.
+        Results are scaled by text size but does not take into account
+        dimensions required by text scale, text skew, fake bold,
+        style stroke, and SkPathEffect.
+
+        @param metrics  storage for SkFontMetrics; may be nullptr
+        @return         recommended spacing between lines
+    */
+    SkScalar getMetrics(SkFontMetrics* metrics) const;
+
+    /** Returns the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        Result is scaled by text size but does not take into account
+        dimensions required by stroking and SkPathEffect.
+        Returns the same result as getMetrics().
+
+        @return  recommended spacing between lines
+    */
+    SkScalar getSpacing() const { return this->getMetrics(nullptr); }
+
+    /** Deprecated.
+    */
+    void LEGACY_applyToPaint(SkPaint* paint) const;
+    /** Deprecated.
+     */
+    void LEGACY_applyPaintFlags(uint32_t paintFlags);
+    /** Deprecated.
+    */
+    static SkFont LEGACY_ExtractFromPaint(const SkPaint& paint);
+
+private:
+    enum PrivFlags {
+        kForceAutoHinting_PrivFlag      = 1 << 0,
+        kEmbeddedBitmaps_PrivFlag       = 1 << 1,
+        kSubpixel_PrivFlag              = 1 << 2,
+        kLinearMetrics_PrivFlag         = 1 << 3,
+        kEmbolden_PrivFlag              = 1 << 4,
+    };
+
+    static constexpr unsigned kAllFlags = 0x07F;
+
+    sk_sp<SkTypeface> fTypeface;
+    SkScalar    fSize;
+    SkScalar    fScaleX;
+    SkScalar    fSkewX;
+    uint8_t     fFlags;
+    uint8_t     fEdging;
+    uint8_t     fHinting;
+
+    SkScalar setupForAsPaths(SkPaint*);
+
+    friend class SkCanonicalizeFont;
+};
+
+#endif

+ 79 - 0
skia/include/core/SkFontArguments.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontArguments_DEFINED
+#define SkFontArguments_DEFINED
+
+#include "SkScalar.h"
+#include "SkTypes.h"
+
+/** Represents a set of actual arguments for a font. */
+struct SkFontArguments {
+    struct VariationPosition {
+        struct Coordinate {
+            SkFourByteTag axis;
+            float value;
+        };
+        const Coordinate* coordinates;
+        int coordinateCount;
+    };
+    // deprecated, use VariationPosition::Coordinate instead
+    struct Axis {
+       SkFourByteTag fTag;
+       float fStyleValue;
+    };
+
+    SkFontArguments() : fCollectionIndex(0), fVariationDesignPosition{nullptr, 0} {}
+
+    /** Specify the index of the desired font.
+     *
+     *  Font formats like ttc, dfont, cff, cid, pfr, t42, t1, and fon may actually be indexed
+     *  collections of fonts.
+     */
+    SkFontArguments& setCollectionIndex(int collectionIndex) {
+        fCollectionIndex = collectionIndex;
+        return *this;
+    }
+
+    // deprecated, use setVariationDesignPosition instead.
+    SkFontArguments& setAxes(const Axis* axes, int axisCount) {
+        fVariationDesignPosition.coordinates =
+                reinterpret_cast<const VariationPosition::Coordinate*>(axes);
+        fVariationDesignPosition.coordinateCount = axisCount;
+        return *this;
+    }
+
+    /** Specify a position in the variation design space.
+     *
+     *  Any axis not specified will use the default value.
+     *  Any specified axis not actually present in the font will be ignored.
+     *
+     *  @param position not copied. The value must remain valid for life of SkFontArguments.
+     */
+    SkFontArguments& setVariationDesignPosition(VariationPosition position) {
+        fVariationDesignPosition.coordinates = position.coordinates;
+        fVariationDesignPosition.coordinateCount = position.coordinateCount;
+        return *this;
+    }
+
+    int getCollectionIndex() const {
+        return fCollectionIndex;
+    }
+    // deprecated, use getVariationDesignPosition instead.
+    const Axis* getAxes(int* axisCount) const {
+        *axisCount = fVariationDesignPosition.coordinateCount;
+        return reinterpret_cast<const Axis*>(fVariationDesignPosition.coordinates);
+    }
+    VariationPosition getVariationDesignPosition() const {
+        return fVariationDesignPosition;
+    }
+private:
+    int fCollectionIndex;
+    VariationPosition fVariationDesignPosition;
+};
+
+#endif

+ 58 - 0
skia/include/core/SkFontLCDConfig.h

@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontLCDConfig_DEFINED
+#define SkFontLCDConfig_DEFINED
+
+#include "SkTypes.h"
+
+class SK_API SkFontLCDConfig {
+public:
+    /** LCDs either have their color elements arranged horizontally or
+        vertically. When rendering subpixel glyphs we need to know which way
+        round they are.
+
+        Note, if you change this after startup, you'll need to flush the glyph
+        cache because it'll have the wrong type of masks cached.
+
+        @deprecated use SkPixelGeometry instead.
+    */
+    enum LCDOrientation {
+        kHorizontal_LCDOrientation = 0,    //!< this is the default
+        kVertical_LCDOrientation   = 1,
+    };
+
+    /** @deprecated set on Device creation. */
+    static void SetSubpixelOrientation(LCDOrientation orientation);
+    /** @deprecated get from Device. */
+    static LCDOrientation GetSubpixelOrientation();
+
+    /** LCD color elements can vary in order. For subpixel text we need to know
+        the order which the LCDs uses so that the color fringes are in the
+        correct place.
+
+        Note, if you change this after startup, you'll need to flush the glyph
+        cache because it'll have the wrong type of masks cached.
+
+        kNONE_LCDOrder means that the subpixel elements are not spatially
+        separated in any usable fashion.
+
+        @deprecated use SkPixelGeometry instead.
+     */
+    enum LCDOrder {
+        kRGB_LCDOrder = 0,    //!< this is the default
+        kBGR_LCDOrder = 1,
+        kNONE_LCDOrder = 2,
+    };
+
+    /** @deprecated set on Device creation. */
+    static void SetSubpixelOrder(LCDOrder order);
+    /** @deprecated get from Device. */
+    static LCDOrder GetSubpixelOrder();
+};
+
+#endif

+ 106 - 0
skia/include/core/SkFontMetrics.h

@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMetrics_DEFINED
+#define SkFontMetrics_DEFINED
+
+#include "SkScalar.h"
+
+struct SK_API SkFontMetrics {
+
+    /** \enum FontMetricsFlags
+     FontMetricsFlags are set in fFlags when underline and strikeout metrics are valid;
+     the underline or strikeout metric may be valid and zero.
+     Fonts with embedded bitmaps may not have valid underline or strikeout metrics.
+     */
+    enum FontMetricsFlags {
+        kUnderlineThicknessIsValid_Flag = 1 << 0, //!< set if fUnderlineThickness is valid
+        kUnderlinePositionIsValid_Flag  = 1 << 1, //!< set if fUnderlinePosition is valid
+        kStrikeoutThicknessIsValid_Flag = 1 << 2, //!< set if fStrikeoutThickness is valid
+        kStrikeoutPositionIsValid_Flag  = 1 << 3, //!< set if fStrikeoutPosition is valid
+    };
+
+    uint32_t fFlags;              //!< is set to FontMetricsFlags when metrics are valid
+    SkScalar fTop;                //!< extent above baseline
+    SkScalar fAscent;             //!< distance to reserve above baseline
+    SkScalar fDescent;            //!< distance to reserve below baseline
+    SkScalar fBottom;             //!< extent below baseline
+    SkScalar fLeading;            //!< distance to add between lines
+    SkScalar fAvgCharWidth;       //!< average character width
+    SkScalar fMaxCharWidth;       //!< maximum character width
+    SkScalar fXMin;               //!< minimum x
+    SkScalar fXMax;               //!< maximum x
+    SkScalar fXHeight;            //!< height of lower-case 'x'
+    SkScalar fCapHeight;          //!< height of an upper-case letter
+    SkScalar fUnderlineThickness; //!< underline thickness
+    SkScalar fUnderlinePosition;  //!< underline position relative to baseline
+    SkScalar fStrikeoutThickness; //!< strikeout thickness
+    SkScalar fStrikeoutPosition;  //!< strikeout position relative to baseline
+
+    /** Returns true if SkFontMetrics has a valid underline thickness, and sets
+     thickness to that value. If the underline thickness is not valid,
+     return false, and ignore thickness.
+
+     @param thickness  storage for underline width
+     @return           true if font specifies underline width
+     */
+    bool hasUnderlineThickness(SkScalar* thickness) const {
+        if (SkToBool(fFlags & kUnderlineThicknessIsValid_Flag)) {
+            *thickness = fUnderlineThickness;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid underline position, and sets
+     position to that value. If the underline position is not valid,
+     return false, and ignore position.
+
+     @param position  storage for underline position
+     @return          true if font specifies underline position
+     */
+    bool hasUnderlinePosition(SkScalar* position) const {
+        if (SkToBool(fFlags & kUnderlinePositionIsValid_Flag)) {
+            *position = fUnderlinePosition;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid strikeout thickness, and sets
+     thickness to that value. If the underline thickness is not valid,
+     return false, and ignore thickness.
+
+     @param thickness  storage for strikeout width
+     @return           true if font specifies strikeout width
+     */
+    bool hasStrikeoutThickness(SkScalar* thickness) const {
+        if (SkToBool(fFlags & kStrikeoutThicknessIsValid_Flag)) {
+            *thickness = fStrikeoutThickness;
+            return true;
+        }
+        return false;
+    }
+
+    /** Returns true if SkFontMetrics has a valid strikeout position, and sets
+     position to that value. If the underline position is not valid,
+     return false, and ignore position.
+
+     @param position  storage for strikeout position
+     @return          true if font specifies strikeout position
+     */
+    bool hasStrikeoutPosition(SkScalar* position) const {
+        if (SkToBool(fFlags & kStrikeoutPositionIsValid_Flag)) {
+            *position = fStrikeoutPosition;
+            return true;
+        }
+        return false;
+    }
+
+};
+
+#endif

+ 163 - 0
skia/include/core/SkFontMgr.h

@@ -0,0 +1,163 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontMgr_DEFINED
+#define SkFontMgr_DEFINED
+
+#include "SkFontArguments.h"
+#include "SkFontStyle.h"
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+
+class SkData;
+class SkFontData;
+class SkStreamAsset;
+class SkString;
+class SkTypeface;
+
+class SK_API SkFontStyleSet : public SkRefCnt {
+public:
+    virtual int count() = 0;
+    virtual void getStyle(int index, SkFontStyle*, SkString* style) = 0;
+    virtual SkTypeface* createTypeface(int index) = 0;
+    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) = 0;
+
+    static SkFontStyleSet* CreateEmpty();
+
+protected:
+    SkTypeface* matchStyleCSS3(const SkFontStyle& pattern);
+
+private:
+    typedef SkRefCnt INHERITED;
+};
+
+class SK_API SkFontMgr : public SkRefCnt {
+public:
+    int countFamilies() const;
+    void getFamilyName(int index, SkString* familyName) const;
+    SkFontStyleSet* createStyleSet(int index) const;
+
+    /**
+     *  The caller must call unref() on the returned object.
+     *  Never returns NULL; will return an empty set if the name is not found.
+     *
+     *  Passing nullptr as the parameter will return the default system family.
+     *  Note that most systems don't have a default system family, so passing nullptr will often
+     *  result in the empty set.
+     *
+     *  It is possible that this will return a style set not accessible from
+     *  createStyleSet(int) due to hidden or auto-activated fonts.
+     */
+    SkFontStyleSet* matchFamily(const char familyName[]) const;
+
+    /**
+     *  Find the closest matching typeface to the specified familyName and style
+     *  and return a ref to it. The caller must call unref() on the returned
+     *  object. Will return nullptr if no 'good' match is found.
+     *
+     *  Passing |nullptr| as the parameter for |familyName| will return the
+     *  default system font.
+     *
+     *  It is possible that this will return a style set not accessible from
+     *  createStyleSet(int) or matchFamily(const char[]) due to hidden or
+     *  auto-activated fonts.
+     */
+    SkTypeface* matchFamilyStyle(const char familyName[], const SkFontStyle&) const;
+
+    /**
+     *  Use the system fallback to find a typeface for the given character.
+     *  Note that bcp47 is a combination of ISO 639, 15924, and 3166-1 codes,
+     *  so it is fine to just pass a ISO 639 here.
+     *
+     *  Will return NULL if no family can be found for the character
+     *  in the system fallback.
+     *
+     *  Passing |nullptr| as the parameter for |familyName| will return the
+     *  default system font.
+     *
+     *  bcp47[0] is the least significant fallback, bcp47[bcp47Count-1] is the
+     *  most significant. If no specified bcp47 codes match, any font with the
+     *  requested character will be matched.
+     */
+    SkTypeface* matchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+                                          const char* bcp47[], int bcp47Count,
+                                          SkUnichar character) const;
+
+    SkTypeface* matchFaceStyle(const SkTypeface*, const SkFontStyle&) const;
+
+    /**
+     *  Create a typeface for the specified data and TTC index (pass 0 for none)
+     *  or NULL if the data is not recognized. The caller must call unref() on
+     *  the returned object if it is not null.
+     */
+    sk_sp<SkTypeface> makeFromData(sk_sp<SkData>, int ttcIndex = 0) const;
+
+    /**
+     *  Create a typeface for the specified stream and TTC index
+     *  (pass 0 for none) or NULL if the stream is not recognized. The caller
+     *  must call unref() on the returned object if it is not null.
+     */
+    sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, int ttcIndex = 0) const;
+
+    /* Experimental, API subject to change. */
+    sk_sp<SkTypeface> makeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&) const;
+
+    /**
+     *  Create a typeface from the specified font data.
+     *  Will return NULL if the typeface could not be created.
+     *  The caller must call unref() on the returned object if it is not null.
+     */
+    sk_sp<SkTypeface> makeFromFontData(std::unique_ptr<SkFontData>) const;
+
+    /**
+     *  Create a typeface for the specified fileName and TTC index
+     *  (pass 0 for none) or NULL if the file is not found, or its contents are
+     *  not recognized. The caller must call unref() on the returned object
+     *  if it is not null.
+     */
+    sk_sp<SkTypeface> makeFromFile(const char path[], int ttcIndex = 0) const;
+
+    sk_sp<SkTypeface> legacyMakeTypeface(const char familyName[], SkFontStyle style) const;
+
+    /** Return the default fontmgr. */
+    static sk_sp<SkFontMgr> RefDefault();
+
+protected:
+    virtual int onCountFamilies() const = 0;
+    virtual void onGetFamilyName(int index, SkString* familyName) const = 0;
+    virtual SkFontStyleSet* onCreateStyleSet(int index)const  = 0;
+
+    /** May return NULL if the name is not found. */
+    virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const = 0;
+
+    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
+                                           const SkFontStyle&) const = 0;
+    virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&,
+                                                    const char* bcp47[], int bcp47Count,
+                                                    SkUnichar character) const = 0;
+    virtual SkTypeface* onMatchFaceStyle(const SkTypeface*,
+                                         const SkFontStyle&) const = 0;
+
+    virtual sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const = 0;
+    virtual sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
+                                                    int ttcIndex) const = 0;
+    virtual sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
+                                                   const SkFontArguments&) const;
+    virtual sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const;
+    virtual sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const = 0;
+
+    virtual sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[], SkFontStyle) const = 0;
+
+private:
+
+    /** Implemented by porting layer to return the default factory. */
+    static sk_sp<SkFontMgr> Factory();
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 38 - 0
skia/include/core/SkFontParameters.h

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontParameters_DEFINED
+#define SkFontParameters_DEFINED
+
+#include "SkScalar.h"
+#include "SkTypes.h"
+
+struct SkFontParameters {
+    struct Variation {
+        // Parameters in a variation font axis.
+        struct Axis {
+            // Four character identifier of the font axis (weight, width, slant, italic...).
+            SkFourByteTag tag;
+            // Minimum value supported by this axis.
+            float min;
+            // Default value set by this axis.
+            float def;
+            // Maximum value supported by this axis. The maximum can equal the minimum.
+            float max;
+            // Return whether this axis is recommended to be remain hidden in user interfaces.
+            bool isHidden() const { return flags & HIDDEN; }
+            // Set this axis to be remain hidden in user interfaces.
+            void setHidden(bool hidden) { flags = hidden ? (flags | HIDDEN) : (flags & ~HIDDEN); }
+        private:
+            static constexpr uint16_t HIDDEN = 0x0001;
+            // Attributes for a font axis.
+            uint16_t flags;
+        };
+    };
+};
+
+#endif

+ 80 - 0
skia/include/core/SkFontStyle.h

@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontStyle_DEFINED
+#define SkFontStyle_DEFINED
+
+#include "SkTypes.h"
+
+class SK_API SkFontStyle {
+public:
+    enum Weight {
+        kInvisible_Weight   =    0,
+        kThin_Weight        =  100,
+        kExtraLight_Weight  =  200,
+        kLight_Weight       =  300,
+        kNormal_Weight      =  400,
+        kMedium_Weight      =  500,
+        kSemiBold_Weight    =  600,
+        kBold_Weight        =  700,
+        kExtraBold_Weight   =  800,
+        kBlack_Weight       =  900,
+        kExtraBlack_Weight  = 1000,
+    };
+
+    enum Width {
+        kUltraCondensed_Width   = 1,
+        kExtraCondensed_Width   = 2,
+        kCondensed_Width        = 3,
+        kSemiCondensed_Width    = 4,
+        kNormal_Width           = 5,
+        kSemiExpanded_Width     = 6,
+        kExpanded_Width         = 7,
+        kExtraExpanded_Width    = 8,
+        kUltraExpanded_Width    = 9,
+    };
+
+    enum Slant {
+        kUpright_Slant,
+        kItalic_Slant,
+        kOblique_Slant,
+    };
+
+    constexpr SkFontStyle(int weight, int width, Slant slant) : fValue(
+        (SkTPin<int>(weight, kInvisible_Weight, kExtraBlack_Weight)) +
+        (SkTPin<int>(width, kUltraCondensed_Width, kUltraExpanded_Width) << 16) +
+        (SkTPin<int>(slant, kUpright_Slant, kOblique_Slant) << 24)
+     ) { }
+
+    constexpr SkFontStyle() : SkFontStyle{kNormal_Weight, kNormal_Width, kUpright_Slant} { }
+
+    bool operator==(const SkFontStyle& rhs) const {
+        return fValue == rhs.fValue;
+    }
+
+    int weight() const { return fValue & 0xFFFF; }
+    int width() const { return (fValue >> 16) & 0xFF; }
+    Slant slant() const { return (Slant)((fValue >> 24) & 0xFF); }
+
+    static constexpr SkFontStyle Normal() {
+        return SkFontStyle(kNormal_Weight, kNormal_Width, kUpright_Slant);
+    }
+    static constexpr SkFontStyle Bold() {
+        return SkFontStyle(kBold_Weight,   kNormal_Width, kUpright_Slant);
+    }
+    static constexpr SkFontStyle Italic() {
+        return SkFontStyle(kNormal_Weight, kNormal_Width, kItalic_Slant );
+    }
+    static constexpr SkFontStyle BoldItalic() {
+        return SkFontStyle(kBold_Weight,   kNormal_Width, kItalic_Slant );
+    }
+
+private:
+    uint32_t fValue;
+};
+
+#endif

+ 49 - 0
skia/include/core/SkFontTypes.h

@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkFontTypes_DEFINED
+#define SkFontTypes_DEFINED
+
+#include "SkScalar.h"
+#include "SkTypeface.h"
+
+// TODO: add to clients, and then remove from here.
+#define SK_SUPPORT_LEGACY_TEXTENCODINGENUM
+
+#ifdef SK_SUPPORT_LEGACY_TEXTENCODINGENUM
+enum SkTextEncoding : uint8_t {
+    kUTF8_SkTextEncoding,
+    kUTF16_SkTextEncoding,
+    kUTF32_SkTextEncoding,
+    kGlyphID_SkTextEncoding,
+};
+#else
+enum class SkTextEncoding {
+    kUTF8,
+    kUTF16,
+    kUTF32,
+    kGlyphID,
+};
+#define kUTF8_SkTextEncoding    SkTextEncoding::kUTF8
+#define kUTF16_SkTextEncoding   SkTextEncoding::kUTF16
+#define kUTF32_SkTextEncoding   SkTextEncoding::kUTF32
+#define kGlyphID_SkTextEncoding SkTextEncoding::kGlyphID
+#endif
+
+enum class SkFontHinting {
+    kNone,      //!< glyph outlines unchanged
+    kSlight,    //!< minimal modification to improve constrast
+    kNormal,    //!< glyph outlines modified to improve constrast
+    kFull,      //!< modifies glyph outlines for maximum constrast
+};
+
+#define kNo_SkFontHinting       SkFontHinting::kNone
+#define kSlight_SkFontHinting   SkFontHinting::kSlight
+#define kNormal_SkFontHinting   SkFontHinting::kNormal
+#define kFull_SkFontHinting     SkFontHinting::kFull
+
+#endif

+ 185 - 0
skia/include/core/SkGraphics.h

@@ -0,0 +1,185 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGraphics_DEFINED
+#define SkGraphics_DEFINED
+
+#include "SkRefCnt.h"
+
+class SkData;
+class SkImageGenerator;
+class SkTraceMemoryDump;
+
+class SK_API SkGraphics {
+public:
+    /**
+     *  Call this at process initialization time if your environment does not
+     *  permit static global initializers that execute code.
+     *  Init() is thread-safe and idempotent.
+     */
+    static void Init();
+
+    // We're in the middle of cleaning this up.
+    static void Term() {}
+
+    /**
+     *  Return the version numbers for the library. If the parameter is not
+     *  null, it is set to the version number.
+     */
+    static void GetVersion(int32_t* major, int32_t* minor, int32_t* patch);
+
+    /**
+     *  Return the max number of bytes that should be used by the font cache.
+     *  If the cache needs to allocate more, it will purge previous entries.
+     *  This max can be changed by calling SetFontCacheLimit().
+     */
+    static size_t GetFontCacheLimit();
+
+    /**
+     *  Specify the max number of bytes that should be used by the font cache.
+     *  If the cache needs to allocate more, it will purge previous entries.
+     *
+     *  This function returns the previous setting, as if GetFontCacheLimit()
+     *  had be called before the new limit was set.
+     */
+    static size_t SetFontCacheLimit(size_t bytes);
+
+    /**
+     *  Return the number of bytes currently used by the font cache.
+     */
+    static size_t GetFontCacheUsed();
+
+    /**
+     *  Return the number of entries in the font cache.
+     *  A cache "entry" is associated with each typeface + pointSize + matrix.
+     */
+    static int GetFontCacheCountUsed();
+
+    /**
+     *  Return the current limit to the number of entries in the font cache.
+     *  A cache "entry" is associated with each typeface + pointSize + matrix.
+     */
+    static int GetFontCacheCountLimit();
+
+    /**
+     *  Set the limit to the number of entries in the font cache, and return
+     *  the previous value. If this new value is lower than the previous,
+     *  it will automatically try to purge entries to meet the new limit.
+     */
+    static int SetFontCacheCountLimit(int count);
+
+    /*
+     *  Returns the maximum point size for text that may be cached.
+     *
+     *  Sizes above this will be drawn directly from the font's outline.
+     *  Setting this to a large value may speed up drawing larger text (repeatedly),
+     *  but could cause the cache to purge other sizes more often.
+     *
+     *  This value is a hint to the font engine, and the actual limit may be different due to
+     *  implementation specific details.
+     */
+    static int GetFontCachePointSizeLimit();
+
+    /*
+     *  Set the maximum point size for text that may be cached, returning the previous value.
+     *
+     *  Sizes above this will be drawn directly from the font's outline.
+     *  Setting this to a large value may speed up drawing larger text (repeatedly),
+     *  but could cause the cache to purge other sizes more often.
+     *
+     *  This value is a hint to the font engine, and the actual limit may be different due to
+     *  implementation specific details.
+     */
+    static int SetFontCachePointSizeLimit(int maxPointSize);
+
+    /**
+     *  For debugging purposes, this will attempt to purge the font cache. It
+     *  does not change the limit, but will cause subsequent font measures and
+     *  draws to be recreated, since they will no longer be in the cache.
+     */
+    static void PurgeFontCache();
+
+    /**
+     *  Scaling bitmaps with the kHigh_SkFilterQuality setting is
+     *  expensive, so the result is saved in the global Scaled Image
+     *  Cache.
+     *
+     *  This function returns the memory usage of the Scaled Image Cache.
+     */
+    static size_t GetResourceCacheTotalBytesUsed();
+
+    /**
+     *  These functions get/set the memory usage limit for the resource cache, used for temporary
+     *  bitmaps and other resources. Entries are purged from the cache when the memory useage
+     *  exceeds this limit.
+     */
+    static size_t GetResourceCacheTotalByteLimit();
+    static size_t SetResourceCacheTotalByteLimit(size_t newLimit);
+
+    /**
+     *  For debugging purposes, this will attempt to purge the resource cache. It
+     *  does not change the limit.
+     */
+    static void PurgeResourceCache();
+
+    /**
+     *  When the cachable entry is very lage (e.g. a large scaled bitmap), adding it to the cache
+     *  can cause most/all of the existing entries to be purged. To avoid the, the client can set
+     *  a limit for a single allocation. If a cacheable entry would have been cached, but its size
+     *  exceeds this limit, then we do not attempt to cache it at all.
+     *
+     *  Zero is the default value, meaning we always attempt to cache entries.
+     */
+    static size_t GetResourceCacheSingleAllocationByteLimit();
+    static size_t SetResourceCacheSingleAllocationByteLimit(size_t newLimit);
+
+    /**
+     *  Dumps memory usage of caches using the SkTraceMemoryDump interface. See SkTraceMemoryDump
+     *  for usage of this method.
+     */
+    static void DumpMemoryStatistics(SkTraceMemoryDump* dump);
+
+    /**
+     *  Free as much globally cached memory as possible. This will purge all private caches in Skia,
+     *  including font and image caches.
+     *
+     *  If there are caches associated with GPU context, those will not be affected by this call.
+     */
+    static void PurgeAllCaches();
+
+    /**
+     *  Applications with command line options may pass optional state, such
+     *  as cache sizes, here, for instance:
+     *  font-cache-limit=12345678
+     *
+     *  The flags format is name=value[;name=value...] with no spaces.
+     *  This format is subject to change.
+     */
+    static void SetFlags(const char* flags);
+
+    typedef std::unique_ptr<SkImageGenerator>
+                                            (*ImageGeneratorFromEncodedDataFactory)(sk_sp<SkData>);
+
+    /**
+     *  To instantiate images from encoded data, first looks at this runtime function-ptr. If it
+     *  exists, it is called to create an SkImageGenerator from SkData. If there is no function-ptr
+     *  or there is, but it returns NULL, then skia will call its internal default implementation.
+     *
+     *  Returns the previous factory (which could be NULL).
+     */
+    static ImageGeneratorFromEncodedDataFactory
+                    SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory);
+};
+
+class SkAutoGraphics {
+public:
+    SkAutoGraphics() {
+        SkGraphics::Init();
+    }
+};
+
+#endif

+ 23 - 0
skia/include/core/SkICC.h

@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkICC_DEFINED
+#define SkICC_DEFINED
+
+#include "SkData.h"
+#include "SkMatrix44.h"
+#include "SkRefCnt.h"
+
+struct SkColorSpaceTransferFn;
+
+SK_API sk_sp<SkData> SkWriteICCProfile(const SkColorSpaceTransferFn&, const float toXYZD50[9]);
+
+namespace SkICC {
+    SK_API sk_sp<SkData> WriteToICC(const SkColorSpaceTransferFn&, const SkMatrix44&);
+}
+
+#endif//SkICC_DEFINED

+ 1026 - 0
skia/include/core/SkImage.h

@@ -0,0 +1,1026 @@
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkImage.h and docs/SkImage_Reference.bmh
+   on 2018-09-18 07:26:44. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkImage_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkImage_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkImage.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkImage_DEFINED
+#define SkImage_DEFINED
+
+#include "GrTypes.h"
+#include "SkFilterQuality.h"
+#include "SkImageInfo.h"
+#include "SkImageEncoder.h"
+#include "SkRefCnt.h"
+#include "SkScalar.h"
+#include "SkShader.h"
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+#include <android/hardware_buffer.h>
+#endif
+
+class SkData;
+class SkCanvas;
+class SkImageFilter;
+class SkImageGenerator;
+class SkPaint;
+class SkPicture;
+class SkString;
+class SkSurface;
+class GrBackendTexture;
+class GrContext;
+class GrContextThreadSafeProxy;
+class GrTexture;
+
+struct SkYUVAIndex;
+
+/** \class SkImage
+    SkImage describes a two dimensional array of pixels to draw. The pixels may be
+    decoded in a raster bitmap, encoded in a SkPicture or compressed data stream,
+    or located in GPU memory as a GPU texture.
+
+    SkImage cannot be modified after it is created. SkImage may allocate additional
+    storage as needed; for instance, an encoded SkImage may decode when drawn.
+
+    SkImage width and height are greater than zero. Creating an SkImage with zero width
+    or height returns SkImage equal to nullptr.
+
+    SkImage may be created from SkBitmap, SkPixmap, SkSurface, SkPicture, encoded streams,
+    GPU texture, YUV_ColorSpace data, or hardware buffer. Encoded streams supported
+    include BMP, GIF, HEIF, ICO, JPEG, PNG, WBMP, WebP. Supported encoding details
+    vary with platform.
+*/
+class SK_API SkImage : public SkRefCnt {
+public:
+
+    /** Caller data passed to RasterReleaseProc; may be nullptr.
+    */
+    typedef void* ReleaseContext;
+
+    /** Creates SkImage from SkPixmap and copy of pixels. Since pixels are copied, SkPixmap
+        pixels may be modified or deleted without affecting SkImage.
+
+        SkImage is returned if SkPixmap is valid. Valid SkPixmap parameters include:
+        dimensions are greater than zero;
+        each dimension fits in 29 bits;
+        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+        row bytes are large enough to hold one row of pixels;
+        pixel address is not nullptr.
+
+        @param pixmap  SkImageInfo, pixel address, and row bytes
+        @return        copy of SkPixmap pixels, or nullptr
+    */
+    static sk_sp<SkImage> MakeRasterCopy(const SkPixmap& pixmap);
+
+    /** Creates SkImage from SkImageInfo, sharing pixels.
+
+        SkImage is returned if SkImageInfo is valid. Valid SkImageInfo parameters include:
+        dimensions are greater than zero;
+        each dimension fits in 29 bits;
+        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+        rowBytes are large enough to hold one row of pixels;
+        pixels is not nullptr, and contains enough data for SkImage.
+
+        @param info      contains width, height, SkAlphaType, SkColorType, SkColorSpace
+        @param pixels    address or pixel storage
+        @param rowBytes  size of pixel row or larger
+        @return          SkImage sharing pixels, or nullptr
+    */
+    static sk_sp<SkImage> MakeRasterData(const SkImageInfo& info, sk_sp<SkData> pixels,
+                                         size_t rowBytes);
+
+    /** Function called when SkImage no longer shares pixels. ReleaseContext is
+        provided by caller when SkImage is created, and may be nullptr.
+    */
+    typedef void (*RasterReleaseProc)(const void* pixels, ReleaseContext);
+
+    /** Creates SkImage from pixmap, sharing SkPixmap pixels. Pixels must remain valid and
+        unchanged until rasterReleaseProc is called. rasterReleaseProc is passed
+        releaseContext when SkImage is deleted or no longer refers to pixmap pixels.
+
+        Pass nullptr for rasterReleaseProc to share SkPixmap without requiring a callback
+        when SkImage is released. Pass nullptr for releaseContext if rasterReleaseProc
+        does not require state.
+
+        SkImage is returned if pixmap is valid. Valid SkPixmap parameters include:
+        dimensions are greater than zero;
+        each dimension fits in 29 bits;
+        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+        row bytes are large enough to hold one row of pixels;
+        pixel address is not nullptr.
+
+        @param pixmap             SkImageInfo, pixel address, and row bytes
+        @param rasterReleaseProc  function called when pixels can be released; or nullptr
+        @param releaseContext     state passed to rasterReleaseProc; or nullptr
+        @return                   SkImage sharing pixmap
+    */
+    static sk_sp<SkImage> MakeFromRaster(const SkPixmap& pixmap,
+                                         RasterReleaseProc rasterReleaseProc,
+                                         ReleaseContext releaseContext);
+
+    /** Creates SkImage from bitmap, sharing or copying bitmap pixels. If the bitmap
+        is marked immutable, and its pixel memory is shareable, it may be shared
+        instead of copied.
+
+        SkImage is returned if bitmap is valid. Valid SkBitmap parameters include:
+        dimensions are greater than zero;
+        each dimension fits in 29 bits;
+        SkColorType and SkAlphaType are valid, and SkColorType is not kUnknown_SkColorType;
+        row bytes are large enough to hold one row of pixels;
+        pixel address is not nullptr.
+
+        @param bitmap  SkImageInfo, row bytes, and pixels
+        @return        created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromBitmap(const SkBitmap& bitmap);
+
+    /** Creates SkImage from data returned by imageGenerator. Generated data is owned by SkImage and
+        may not be shared or accessed.
+
+        subset allows selecting a portion of the full image. Pass nullptr to select the entire
+        image; otherwise, subset must be contained by image bounds.
+
+        SkImage is returned if generator data is valid. Valid data parameters vary by type of data
+        and platform.
+
+        imageGenerator may wrap SkPicture data, codec data, or custom data.
+
+        @param imageGenerator  stock or custom routines to retrieve SkImage
+        @param subset          bounds of returned SkImage; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromGenerator(std::unique_ptr<SkImageGenerator> imageGenerator,
+                                            const SkIRect* subset = nullptr);
+
+    /** Creates SkImage from encoded data.
+        subset allows selecting a portion of the full image. Pass nullptr to select the entire
+        image; otherwise, subset must be contained by image bounds.
+
+        SkImage is returned if format of the encoded data is recognized and supported.
+        Recognized formats vary by platform.
+
+        @param encoded  data of SkImage to decode
+        @param subset   bounds of returned SkImage; may be nullptr
+        @return         created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset = nullptr);
+
+    /** User function called when supplied texture may be deleted.
+    */
+    typedef void (*TextureReleaseProc)(ReleaseContext releaseContext);
+
+    /** Creates SkImage from GPU texture associated with context. Caller is responsible for
+        managing the lifetime of GPU texture.
+
+        SkImage is returned if format of backendTexture is recognized and supported.
+        Recognized formats vary by GPU back-end.
+
+        @param context         GPU context
+        @param backendTexture  texture residing on GPU
+        @param origin          one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param colorType       one of:
+                               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+                               kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
+                               kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
+                               kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+                               kGray_8_SkColorType, kRGBA_F16_SkColorType
+        @param alphaType       one of:
+                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                               kUnpremul_SkAlphaType
+        @param colorSpace      range of colors; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromTexture(GrContext* context,
+                                          const GrBackendTexture& backendTexture,
+                                          GrSurfaceOrigin origin,
+                                          SkColorType colorType,
+                                          SkAlphaType alphaType,
+                                          sk_sp<SkColorSpace> colorSpace) {
+        return MakeFromTexture(context, backendTexture, origin, colorType, alphaType, colorSpace,
+                               nullptr, nullptr);
+    }
+
+    /** Creates SkImage from GPU texture associated with context. GPU texture must stay
+        valid and unchanged until textureReleaseProc is called. textureReleaseProc is
+        passed releaseContext when SkImage is deleted or no longer refers to texture.
+
+        SkImage is returned if format of backendTexture is recognized and supported.
+        Recognized formats vary by GPU back-end.
+
+        @param context             GPU context
+        @param backendTexture      texture residing on GPU
+        @param origin              one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param colorType           one of:
+                                   kUnknown_SkColorType, kAlpha_8_SkColorType,
+                                   kRGB_565_SkColorType, kARGB_4444_SkColorType,
+                                   kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                                   kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                                   kRGB_101010x_SkColorType, kGray_8_SkColorType,
+                                   kRGBA_F16_SkColorType
+        @param alphaType           one of:
+                                   kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                                   kUnpremul_SkAlphaType
+        @param colorSpace          range of colors; may be nullptr
+        @param textureReleaseProc  function called when texture can be released
+        @param releaseContext      state passed to textureReleaseProc
+        @return                    created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromTexture(GrContext* context,
+                                          const GrBackendTexture& backendTexture,
+                                          GrSurfaceOrigin origin,
+                                          SkColorType colorType,
+                                          SkAlphaType alphaType,
+                                          sk_sp<SkColorSpace> colorSpace,
+                                          TextureReleaseProc textureReleaseProc,
+                                          ReleaseContext releaseContext);
+
+    /** Creates SkImage from encoded data. SkImage is uploaded to GPU back-end using context.
+
+        Created SkImage is available to other GPU contexts, and is available across thread
+        boundaries. All contexts must be in the same GPU share group, or otherwise
+        share resources.
+
+        When SkImage is no longer referenced, context releases texture memory
+        asynchronously.
+
+        GrBackendTexture decoded from data is uploaded to match SkSurface created with
+        dstColorSpace. SkColorSpace of SkImage is determined by encoded data.
+
+        SkImage is returned if format of data is recognized and supported, and if context
+        supports moving resources. Recognized formats vary by platform and GPU back-end.
+
+        SkImage is returned using MakeFromEncoded() if context is nullptr or does not support
+        moving resources between contexts.
+
+        @param context                GPU context
+        @param data                   SkImage to decode
+        @param buildMips              create SkImage as mip map if true
+        @param dstColorSpace          range of colors of matching SkSurface on GPU
+        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary
+        @return                       created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeCrossContextFromEncoded(GrContext* context, sk_sp<SkData> data,
+                                                      bool buildMips, SkColorSpace* dstColorSpace,
+                                                      bool limitToMaxTextureSize = false);
+
+    /** Creates SkImage from pixmap. SkImage is uploaded to GPU back-end using context.
+
+        Created SkImage is available to other GPU contexts, and is available across thread
+        boundaries. All contexts must be in the same GPU share group, or otherwise
+        share resources.
+
+        When SkImage is no longer referenced, context releases texture memory
+        asynchronously.
+
+        GrBackendTexture created from pixmap is uploaded to match SkSurface created with
+        dstColorSpace. SkColorSpace of SkImage is determined by pixmap.colorSpace().
+
+        SkImage is returned referring to GPU back-end if context is not nullptr,
+        format of data is recognized and supported, and if context supports moving
+        resources between contexts. Otherwise, pixmap pixel data is copied and SkImage
+        as returned in raster format if possible; nullptr may be returned.
+        Recognized GPU formats vary by platform and GPU back-end.
+
+        @param context                GPU context
+        @param pixmap                 SkImageInfo, pixel address, and row bytes
+        @param buildMips              create SkImage as mip map if true
+        @param dstColorSpace          range of colors of matching SkSurface on GPU
+        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary
+        @return                       created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeCrossContextFromPixmap(GrContext* context, const SkPixmap& pixmap,
+                                                     bool buildMips, SkColorSpace* dstColorSpace,
+                                                     bool limitToMaxTextureSize = false);
+
+    /** Creates SkImage from backendTexture associated with context. backendTexture and
+        returned SkImage are managed internally, and are released when no longer needed.
+
+        SkImage is returned if format of backendTexture is recognized and supported.
+        Recognized formats vary by GPU back-end.
+
+        @param context         GPU context
+        @param backendTexture  texture residing on GPU
+        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param colorType       one of:
+                               kUnknown_SkColorType, kAlpha_8_SkColorType,
+                               kRGB_565_SkColorType, kARGB_4444_SkColorType,
+                               kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                               kRGB_101010x_SkColorType, kGray_8_SkColorType,
+                               kRGBA_F16_SkColorType
+        @param alphaType       one of:
+                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                               kUnpremul_SkAlphaType
+        @param colorSpace      range of colors; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromAdoptedTexture(GrContext* context,
+                                                 const GrBackendTexture& backendTexture,
+                                                 GrSurfaceOrigin surfaceOrigin,
+                                                 SkColorType colorType,
+                                                 SkAlphaType alphaType = kPremul_SkAlphaType,
+                                                 sk_sp<SkColorSpace> colorSpace = nullptr);
+
+    /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
+        image.
+
+        @param context         GPU context
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVATexturesCopy(GrContext* context,
+                                                   SkYUVColorSpace yuvColorSpace,
+                                                   const GrBackendTexture yuvaTextures[],
+                                                   const SkYUVAIndex yuvaIndices[4],
+                                                   SkISize imageSize,
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates an SkImage by flattening the specified YUVA planes into a single, interleaved RGBA
+        image. 'backendTexture' is used to store the result of the flattening.
+
+        @param context         GPU context
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param backendTexture  the resource that stores the final pixels
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVATexturesCopyWithExternalBackend(
+            GrContext* context,
+            SkYUVColorSpace yuvColorSpace,
+            const GrBackendTexture yuvaTextures[],
+            const SkYUVAIndex yuvaIndices[4],
+            SkISize imageSize,
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates an SkImage by storing the specified YUVA planes into an image, to be rendered
+        via multitexturing.
+
+        @param context         GPU context
+        @param yuvColorSpace   How the YUV values are converted to RGB. One of:
+                                           kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                           kRec709_SkYUVColorSpace
+        @param yuvaTextures    array of (up to four) YUVA textures on GPU which contain the,
+                               possibly interleaved, YUVA planes
+        @param yuvaIndices     array indicating which texture in yuvaTextures, and channel
+                               in that texture, maps to each component of YUVA.
+        @param imageSize       size of the resulting image
+        @param imageOrigin     origin of the resulting image. One of: kBottomLeft_GrSurfaceOrigin,
+                               kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors of the resulting image; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVATextures(GrContext* context,
+                                               SkYUVColorSpace yuvColorSpace,
+                                               const GrBackendTexture yuvaTextures[],
+                                               const SkYUVAIndex yuvaIndices[4],
+                                               SkISize imageSize,
+                                               GrSurfaceOrigin imageOrigin,
+                                               sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates SkImage from pixmap array representing YUVA data.
+        SkImage is uploaded to GPU back-end using context.
+
+        Each GrBackendTexture created from yuvaPixmaps array is uploaded to match SkSurface
+        using SkColorSpace of SkPixmap. SkColorSpace of SkImage is determined by imageColorSpace.
+
+        SkImage is returned referring to GPU back-end if context is not nullptr and
+        format of data is recognized and supported. Otherwise, nullptr is returned.
+        Recognized GPU formats vary by platform and GPU back-end.
+
+        @param context                GPU context
+        @param yuvColorSpace          How the YUV values are converted to RGB. One of:
+                                            kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                                            kRec709_SkYUVColorSpace
+        @param yuvaPixmaps            array of (up to four) SkPixmap which contain the,
+                                      possibly interleaved, YUVA planes
+        @param yuvaIndices            array indicating which pixmap in yuvaPixmaps, and channel
+                                      in that pixmap, maps to each component of YUVA.
+        @param imageSize              size of the resulting image
+        @param imageOrigin            origin of the resulting image. One of:
+                                            kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param buildMips              create internal YUVA textures as mip map if true
+        @param limitToMaxTextureSize  downscale image to GPU maximum texture size, if necessary
+        @param imageColorSpace        range of colors of the resulting image; may be nullptr
+        @return                       created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromYUVAPixmaps(
+            GrContext* context, SkYUVColorSpace yuvColorSpace, const SkPixmap yuvaPixmaps[],
+            const SkYUVAIndex yuvaIndices[4], SkISize imageSize, GrSurfaceOrigin imageOrigin,
+            bool buildMips, bool limitToMaxTextureSize = false,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** To be deprecated.
+    */
+    static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
+                                                  const GrBackendTexture yuvTextures[3],
+                                                  GrSurfaceOrigin imageOrigin,
+                                                  sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** To be deprecated.
+    */
+    static sk_sp<SkImage> MakeFromYUVTexturesCopyWithExternalBackend(
+            GrContext* context, SkYUVColorSpace yuvColorSpace,
+            const GrBackendTexture yuvTextures[3], GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture, sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
+        nv12Textures[0] contains pixels for YUV component y plane.
+        nv12Textures[1] contains pixels for YUV component u plane,
+        followed by pixels for YUV component v plane.
+        Returned SkImage has the dimensions nv12Textures[2].
+        yuvColorSpace describes how YUV colors convert to RGB colors.
+
+        @param context         GPU context
+        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
+        @param nv12Textures    array of YUV textures on GPU
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param imageColorSpace range of colors; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext* context,
+                                                   SkYUVColorSpace yuvColorSpace,
+                                                   const GrBackendTexture nv12Textures[2],
+                                                   GrSurfaceOrigin imageOrigin,
+                                                   sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    /** Creates SkImage from copy of nv12Textures, an array of textures on GPU.
+        nv12Textures[0] contains pixels for YUV component y plane.
+        nv12Textures[1] contains pixels for YUV component u plane,
+        followed by pixels for YUV component v plane.
+        Returned SkImage has the dimensions nv12Textures[2] and stores pixels in backendTexture.
+        yuvColorSpace describes how YUV colors convert to RGB colors.
+
+        @param context         GPU context
+        @param yuvColorSpace   one of: kJPEG_SkYUVColorSpace, kRec601_SkYUVColorSpace,
+                               kRec709_SkYUVColorSpace
+        @param nv12Textures    array of YUV textures on GPU
+        @param imageOrigin     one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @param backendTexture  the resource that stores the final pixels
+        @param imageColorSpace range of colors; may be nullptr
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromNV12TexturesCopyWithExternalBackend(
+            GrContext* context,
+            SkYUVColorSpace yuvColorSpace,
+            const GrBackendTexture nv12Textures[2],
+            GrSurfaceOrigin imageOrigin,
+            const GrBackendTexture& backendTexture,
+            sk_sp<SkColorSpace> imageColorSpace = nullptr);
+
+    enum class BitDepth {
+        kU8,  //!< uses 8-bit unsigned int per color component
+        kF16, //!< uses 16-bit float per color component
+    };
+
+    /** Creates SkImage from picture. Returned SkImage width and height are set by dimensions.
+        SkImage draws picture with matrix and paint, set to bitDepth and colorSpace.
+
+        If matrix is nullptr, draws with identity SkMatrix. If paint is nullptr, draws
+        with default SkPaint. colorSpace may be nullptr.
+
+        @param picture     stream of drawing commands
+        @param dimensions  width and height
+        @param matrix      SkMatrix to rotate, scale, translate, and so on; may be nullptr
+        @param paint       SkPaint to apply transparency, filtering, and so on; may be nullptr
+        @param bitDepth    8-bit integer or 16-bit float: per component
+        @param colorSpace  range of colors; may be nullptr
+        @return            created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
+                                          const SkMatrix* matrix, const SkPaint* paint,
+                                          BitDepth bitDepth,
+                                          sk_sp<SkColorSpace> colorSpace);
+
+#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
+    /** (See Skia bug 7447)
+        Creates SkImage from Android hardware buffer.
+        Returned SkImage takes a reference on the buffer.
+
+        Only available on Android, when __ANDROID_API__ is defined to be 26 or greater.
+
+        @param hardwareBuffer  AHardwareBuffer Android hardware buffer
+        @param alphaType       one of:
+                               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                               kUnpremul_SkAlphaType
+        @param colorSpace      range of colors; may be nullptr
+        @param surfaceOrigin   one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
+        @return                created SkImage, or nullptr
+    */
+    static sk_sp<SkImage> MakeFromAHardwareBuffer(
+            AHardwareBuffer* hardwareBuffer,
+            SkAlphaType alphaType = kPremul_SkAlphaType,
+            sk_sp<SkColorSpace> colorSpace = nullptr,
+            GrSurfaceOrigin surfaceOrigin = kTopLeft_GrSurfaceOrigin);
+#endif
+
+    /** Returns pixel count in each row.
+
+        @return  pixel width in SkImage
+    */
+    int width() const { return fWidth; }
+
+    /** Returns pixel row count.
+
+        @return  pixel height in SkImage
+    */
+    int height() const { return fHeight; }
+
+    /** Returns SkISize { width(), height() }.
+
+        @return  integral size of width() and height()
+    */
+    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
+
+    /** Returns SkIRect { 0, 0, width(), height() }.
+
+        @return  integral rectangle from origin to width() and height()
+    */
+    SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
+
+    /** Returns value unique to image. SkImage contents cannot change after SkImage is
+        created. Any operation to create a new SkImage will receive generate a new
+        unique number.
+
+        @return  unique identifier
+    */
+    uint32_t uniqueID() const { return fUniqueID; }
+
+    /** Returns SkAlphaType, one of:
+        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+        kUnpremul_SkAlphaType.
+
+        SkAlphaType returned was a parameter to an SkImage constructor,
+        or was parsed from encoded data.
+
+        @return  SkAlphaType in SkImage
+    */
+    SkAlphaType alphaType() const;
+
+    /** Returns SkColorType if known; otherwise, returns kUnknown_SkColorType.
+
+        @return  SkColorType of SkImage
+    */
+    SkColorType colorType() const;
+
+    /** Returns SkColorSpace, the range of colors, associated with SkImage.  The
+        reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+        immutable.
+
+        SkColorSpace returned was passed to an SkImage constructor,
+        or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
+        is drawn, depending on the capabilities of the SkSurface receiving the drawing.
+
+        @return  SkColorSpace in SkImage, or nullptr
+    */
+    SkColorSpace* colorSpace() const;
+
+    /** Returns a smart pointer to SkColorSpace, the range of colors, associated with
+        SkImage.  The smart pointer tracks the number of objects sharing this
+        SkColorSpace reference so the memory is released when the owners destruct.
+
+        The returned SkColorSpace is immutable.
+
+        SkColorSpace returned was passed to an SkImage constructor,
+        or was parsed from encoded data. SkColorSpace returned may be ignored when SkImage
+        is drawn, depending on the capabilities of the SkSurface receiving the drawing.
+
+        @return  SkColorSpace in SkImage, or nullptr, wrapped in a smart pointer
+    */
+    sk_sp<SkColorSpace> refColorSpace() const;
+
+    /** Returns true if SkImage pixels represent transparency only. If true, each pixel
+        is packed in 8 bits as defined by kAlpha_8_SkColorType.
+
+        @return  true if pixels represent a transparency mask
+    */
+    bool isAlphaOnly() const;
+
+    /** Returns true if pixels ignore their alpha value and are treated as fully opaque.
+
+        @return  true if SkAlphaType is kOpaque_SkAlphaType
+    */
+    bool isOpaque() const { return SkAlphaTypeIsOpaque(this->alphaType()); }
+
+    /** Creates SkShader from SkImage. SkShader dimensions are taken from SkImage. SkShader uses
+        SkShader::TileMode rules to fill drawn area outside SkImage. localMatrix permits
+        transforming SkImage before SkCanvas matrix is applied.
+
+        @param tileMode1    tiling on x-axis, one of: SkShader::kClamp_TileMode,
+                            SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode
+        @param tileMode2    tiling on y-axis, one of: SkShader::kClamp_TileMode,
+                            SkShader::kRepeat_TileMode, SkShader::kMirror_TileMode
+        @param localMatrix  SkImage transformation, or nullptr
+        @return             SkShader containing SkImage
+    */
+    sk_sp<SkShader> makeShader(SkShader::TileMode tileMode1, SkShader::TileMode tileMode2,
+                               const SkMatrix* localMatrix = nullptr) const;
+
+    /** Creates SkShader from SkImage. SkShader dimensions are taken from SkImage. SkShader uses
+        SkShader::kClamp_TileMode to fill drawn area outside SkImage. localMatrix permits
+        transforming SkImage before SkCanvas matrix is applied.
+
+        @param localMatrix  SkImage transformation, or nullptr
+        @return             SkShader containing SkImage
+    */
+    sk_sp<SkShader> makeShader(const SkMatrix* localMatrix = nullptr) const {
+        return this->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, localMatrix);
+    }
+
+    /** Copies SkImage pixel address, row bytes, and SkImageInfo to pixmap, if address
+        is available, and returns true. If pixel address is not available, return
+        false and leave pixmap unchanged.
+
+        @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
+        @return        true if SkImage has direct access to pixels
+    */
+    bool peekPixels(SkPixmap* pixmap) const;
+
+    /** Deprecated.
+    */
+    GrTexture* getTexture() const;
+
+    /** Returns true the contents of SkImage was created on or uploaded to GPU memory,
+        and is available as a GPU texture.
+
+        @return  true if SkImage is a GPU texture
+    */
+    bool isTextureBacked() const;
+
+    /** Returns true if SkImage can be drawn on either raster surface or GPU surface.
+        If context is nullptr, tests if SkImage draws on raster surface;
+        otherwise, tests if SkImage draws on GPU surface associated with context.
+
+        SkImage backed by GPU texture may become invalid if associated GrContext is
+        invalid. lazy image may be invalid and may not draw to raster surface or
+        GPU surface or both.
+
+        @param context  GPU context
+        @return         true if SkImage can be drawn
+    */
+    bool isValid(GrContext* context) const;
+
+    /** Retrieves the back-end texture. If SkImage has no back-end texture, an invalid
+        object is returned. Call GrBackendTexture::isValid to determine if the result
+        is valid.
+
+        If flushPendingGrContextIO is true, completes deferred I/O operations.
+
+        If origin in not nullptr, copies location of content drawn into SkImage.
+
+        @param flushPendingGrContextIO  flag to flush outstanding requests
+        @param origin                   storage for one of: kTopLeft_GrSurfaceOrigin,
+                                        kBottomLeft_GrSurfaceOrigin; or nullptr
+        @return                         back-end API texture handle; invalid on failure
+    */
+    GrBackendTexture getBackendTexture(bool flushPendingGrContextIO,
+                                       GrSurfaceOrigin* origin = nullptr) const;
+
+    /** \enum SkImage::CachingHint
+        CachingHint selects whether Skia may internally cache SkBitmap generated by
+        decoding SkImage, or by copying SkImage from GPU to CPU. The default behavior
+        allows caching SkBitmap.
+
+        Choose kDisallow_CachingHint if SkImage pixels are to be used only once, or
+        if SkImage pixels reside in a cache outside of Skia, or to reduce memory pressure.
+
+        Choosing kAllow_CachingHint does not ensure that pixels will be cached.
+        SkImage pixels may not be cached if memory requirements are too large or
+        pixels are not accessible.
+    */
+    enum CachingHint {
+        kAllow_CachingHint,    //!< allows internally caching decoded and copied pixels
+        kDisallow_CachingHint, //!< disallows internally caching decoded and copied pixels
+    };
+
+    /** Copies SkRect of pixels from SkImage to dstPixels. Copy starts at offset (srcX, srcY),
+        and does not exceed SkImage (width(), height()).
+
+        dstInfo specifies width, height, SkColorType, SkAlphaType, and SkColorSpace of
+        destination. dstRowBytes specifics the gap from one destination row to the next.
+        Returns true if pixels are copied. Returns false if:
+        - dstInfo.addr() equals nullptr
+        - dstRowBytes is less than dstInfo.minRowBytes()
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+        If SkImage SkColorType is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+        If SkImage SkAlphaType is kOpaque_SkAlphaType, dstInfo.alphaType() must
+        match. If SkImage SkColorSpace is nullptr, dstInfo.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false if width() or height() is zero or negative.
+        Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
+
+        If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
+        @param dstPixels    destination pixel storage
+        @param dstRowBytes  destination row length
+        @param srcX         column index whose absolute value is less than width()
+        @param srcY         row index whose absolute value is less than height()
+        @param cachingHint  one of: kAllow_CachingHint, kDisallow_CachingHint
+        @return             true if pixels are copied to dstPixels
+    */
+    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+                    int srcX, int srcY, CachingHint cachingHint = kAllow_CachingHint) const;
+
+    /** Copies a SkRect of pixels from SkImage to dst. Copy starts at (srcX, srcY), and
+        does not exceed SkImage (width(), height()).
+
+        dst specifies width, height, SkColorType, SkAlphaType, SkColorSpace, pixel storage,
+        and row bytes of destination. dst.rowBytes() specifics the gap from one destination
+        row to the next. Returns true if pixels are copied. Returns false if:
+        - dst pixel storage equals nullptr
+        - dst.rowBytes is less than SkImageInfo::minRowBytes
+        - SkPixelRef is nullptr
+
+        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
+        If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
+        If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
+        match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false if width() or height() is zero or negative.
+        Returns false if abs(srcX) >= Image width(), or if abs(srcY) >= Image height().
+
+        If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+        @param dst          destination SkPixmap: SkImageInfo, pixels, row bytes
+        @param srcX         column index whose absolute value is less than width()
+        @param srcY         row index whose absolute value is less than height()
+        @param cachingHint  one of: kAllow_CachingHint, kDisallow_CachingHint
+        @return             true if pixels are copied to dst
+    */
+    bool readPixels(const SkPixmap& dst, int srcX, int srcY,
+                    CachingHint cachingHint = kAllow_CachingHint) const;
+
+    /** Copies SkImage to dst, scaling pixels to fit dst.width() and dst.height(), and
+        converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
+        pixels are copied. Returns false if dst.addr() is nullptr, or dst.rowBytes() is
+        less than dst SkImageInfo::minRowBytes.
+
+        Pixels are copied only if pixel conversion is possible. If SkImage SkColorType is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.colorType() must match.
+        If SkImage SkColorType is kGray_8_SkColorType, dst.colorSpace() must match.
+        If SkImage SkAlphaType is kOpaque_SkAlphaType, dst.alphaType() must
+        match. If SkImage SkColorSpace is nullptr, dst.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        Scales the image, with filterQuality, to match dst.width() and dst.height().
+        filterQuality kNone_SkFilterQuality is fastest, typically implemented with
+        nearest neighbor filter. kLow_SkFilterQuality is typically implemented with
+        bilerp filter. kMedium_SkFilterQuality is typically implemented with
+        bilerp filter, and mip-map filter when size is reduced.
+        kHigh_SkFilterQuality is slowest, typically implemented with bicubic filter.
+
+        If cachingHint is kAllow_CachingHint, pixels may be retained locally.
+        If cachingHint is kDisallow_CachingHint, pixels are not added to the local cache.
+
+        @param dst            destination SkPixmap: SkImageInfo, pixels, row bytes
+        @param filterQuality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+                              kMedium_SkFilterQuality, kHigh_SkFilterQuality
+        @param cachingHint    one of: kAllow_CachingHint, kDisallow_CachingHint
+        @return               true if pixels are scaled to fit dst
+    */
+    bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality,
+                     CachingHint cachingHint = kAllow_CachingHint) const;
+
+    /** Encodes SkImage pixels, returning result as SkData.
+
+        Returns nullptr if encoding fails, or if encodedImageFormat is not supported.
+
+        SkImage encoding in a format requires both building with one or more of:
+        SK_HAS_JPEG_LIBRARY, SK_HAS_PNG_LIBRARY, SK_HAS_WEBP_LIBRARY; and platform support
+        for the encoded format.
+
+        If SK_BUILD_FOR_MAC or SK_BUILD_FOR_IOS is defined, encodedImageFormat can
+        additionally be one of: SkEncodedImageFormat::kICO, SkEncodedImageFormat::kBMP,
+        SkEncodedImageFormat::kGIF.
+
+        quality is a platform and format specific metric trading off size and encoding
+        error. When used, quality equaling 100 encodes with the least error. quality may
+        be ignored by the encoder.
+
+        @param encodedImageFormat  one of: SkEncodedImageFormat::kJPEG, SkEncodedImageFormat::kPNG,
+                                   SkEncodedImageFormat::kWEBP
+        @param quality             encoder specific metric with 100 equaling best
+        @return                    encoded SkImage, or nullptr
+    */
+    sk_sp<SkData> encodeToData(SkEncodedImageFormat encodedImageFormat, int quality) const;
+
+    /** Encodes SkImage pixels, returning result as SkData. Returns existing encoded data
+        if present; otherwise, SkImage is encoded with SkEncodedImageFormat::kPNG. Skia
+        must be built with SK_HAS_PNG_LIBRARY to encode SkImage.
+
+        Returns nullptr if existing encoded data is missing or invalid, and
+        encoding fails.
+
+        @return  encoded SkImage, or nullptr
+    */
+    sk_sp<SkData> encodeToData() const;
+
+    /** Returns encoded SkImage pixels as SkData, if SkImage was created from supported
+        encoded stream format. Platform support for formats vary and may require building
+        with one or more of: SK_HAS_JPEG_LIBRARY, SK_HAS_PNG_LIBRARY, SK_HAS_WEBP_LIBRARY.
+
+        Returns nullptr if SkImage contents are not encoded.
+
+        @return  encoded SkImage, or nullptr
+    */
+    sk_sp<SkData> refEncodedData() const;
+
+    /** Returns subset of SkImage. subset must be fully contained by SkImage dimensions().
+        The implementation may share pixels, or may copy them.
+
+        Returns nullptr if subset is empty, or subset is not contained by bounds, or
+        pixels in SkImage could not be read or copied.
+
+        @param subset  bounds of returned SkImage
+        @return        partial or full SkImage, or nullptr
+    */
+    sk_sp<SkImage> makeSubset(const SkIRect& subset) const;
+
+    /** Returns SkImage backed by GPU texture associated with context. Returned SkImage is
+        compatible with SkSurface created with dstColorSpace. The returned SkImage respects
+        mipMapped setting; if mipMapped equals GrMipMapped::kYes, the backing texture
+        allocates mip map levels. Returns original SkImage if context
+        and dstColorSpace match and mipMapped is compatible with backing GPU texture.
+
+        Returns nullptr if context is nullptr, or if SkImage was created with another
+        GrContext.
+
+        @param context        GPU context
+        @param dstColorSpace  range of colors of matching SkSurface on GPU
+        @param mipMapped      whether created SkImage texture must allocate mip map levels
+        @return               created SkImage, or nullptr
+    */
+    sk_sp<SkImage> makeTextureImage(GrContext* context, SkColorSpace* dstColorSpace,
+                                    GrMipMapped mipMapped = GrMipMapped::kNo) const;
+
+    /** Returns raster image or lazy image. Copies SkImage backed by GPU texture into
+        CPU memory if needed. Returns original SkImage if decoded in raster bitmap,
+        or if encoded in a stream.
+
+        Returns nullptr if backed by GPU texture and copy fails.
+
+        @return  raster image, lazy image, or nullptr
+    */
+    sk_sp<SkImage> makeNonTextureImage() const;
+
+    /** Returns raster image. Copies SkImage backed by GPU texture into CPU memory,
+        or decodes SkImage from lazy image. Returns original SkImage if decoded in
+        raster bitmap.
+
+        Returns nullptr if copy, decode, or pixel read fails.
+
+        @return  raster image, or nullptr
+    */
+    sk_sp<SkImage> makeRasterImage() const;
+
+    /** Creates filtered SkImage. filter processes original SkImage, potentially changing
+        color, position, and size. subset is the bounds of original SkImage processed
+        by filter. clipBounds is the expected bounds of the filtered SkImage. outSubset
+        is required storage for the actual bounds of the filtered SkImage. offset is
+        required storage for translation of returned SkImage.
+
+        Returns nullptr if SkImage could not be created. If nullptr is returned, outSubset
+        and offset are undefined.
+
+        Useful for animation of SkImageFilter that varies size from frame to frame.
+        Returned SkImage is created larger than required by filter so that GPU texture
+        can be reused with different sized effects. outSubset describes the valid bounds
+        of GPU texture returned. offset translates the returned SkImage to keep subsequent
+        animation frames aligned with respect to each other.
+
+        @param filter      how SkImage is sampled when transformed
+        @param subset      bounds of SkImage processed by filter
+        @param clipBounds  expected bounds of filtered SkImage
+        @param outSubset   storage for returned SkImage bounds
+        @param offset      storage for returned SkImage translation
+        @return            filtered SkImage, or nullptr
+    */
+    sk_sp<SkImage> makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
+                                  const SkIRect& clipBounds, SkIRect* outSubset,
+                                  SkIPoint* offset) const;
+
+    /** Defines a callback function, taking one parameter of type GrBackendTexture with
+        no return value. Function is called when back-end texture is to be released.
+    */
+    typedef std::function<void(GrBackendTexture)> BackendTextureReleaseProc;
+
+    /** Creates a GrBackendTexture from the provided SkImage. Returns true and
+        stores result in backendTexture and backendTextureReleaseProc if
+        texture is created; otherwise, returns false and leaves
+        backendTexture and backendTextureReleaseProc unmodified.
+
+        Call backendTextureReleaseProc after deleting backendTexture.
+        backendTextureReleaseProc cleans up auxiliary data related to returned
+        backendTexture. The caller must delete returned backendTexture after use.
+
+        If SkImage is both texture backed and singly referenced, image is returned in
+        backendTexture without conversion or making a copy. SkImage is singly referenced
+        if its was transferred solely using std::move().
+
+        If SkImage is not texture backed, returns texture with SkImage contents.
+
+        @param context                    GPU context
+        @param image                      SkImage used for texture
+        @param backendTexture             storage for back-end texture
+        @param backendTextureReleaseProc  storage for clean up function
+        @return                           true if back-end texture was created
+    */
+    static bool MakeBackendTextureFromSkImage(GrContext* context,
+                                              sk_sp<SkImage> image,
+                                              GrBackendTexture* backendTexture,
+                                              BackendTextureReleaseProc* backendTextureReleaseProc);
+
+    /** Deprecated.
+     */
+    enum LegacyBitmapMode {
+        kRO_LegacyBitmapMode, //!< returned bitmap is read-only and immutable
+    };
+
+    /** Deprecated.
+        Creates raster SkBitmap with same pixels as SkImage. If legacyBitmapMode is
+        kRO_LegacyBitmapMode, returned bitmap is read-only and immutable.
+        Returns true if SkBitmap is stored in bitmap. Returns false and resets bitmap if
+        SkBitmap write did not succeed.
+
+        @param bitmap            storage for legacy SkBitmap
+        @param legacyBitmapMode  bitmap is read-only and immutable
+        @return                  true if SkBitmap was created
+    */
+    bool asLegacyBitmap(SkBitmap* bitmap,
+                        LegacyBitmapMode legacyBitmapMode = kRO_LegacyBitmapMode) const;
+
+    /** Returns true if SkImage is backed by an image-generator or other service that creates
+        and caches its pixels or texture on-demand.
+
+        @return  true if SkImage is created as needed
+    */
+    bool isLazyGenerated() const;
+
+    /** Creates SkImage in target SkColorSpace.
+        Returns nullptr if SkImage could not be created.
+
+        Returns original SkImage if it is in target SkColorSpace.
+        Otherwise, converts pixels from SkImage SkColorSpace to target SkColorSpace.
+        If SkImage colorSpace() returns nullptr, SkImage SkColorSpace is assumed to be sRGB.
+
+        @param target  SkColorSpace describing color range of returned SkImage
+        @return        created SkImage in target SkColorSpace
+    */
+    sk_sp<SkImage> makeColorSpace(sk_sp<SkColorSpace> target) const;
+
+private:
+    SkImage(int width, int height, uint32_t uniqueID);
+    friend class SkImage_Base;
+
+    const int       fWidth;
+    const int       fHeight;
+    const uint32_t  fUniqueID;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 68 - 0
skia/include/core/SkImageEncoder.h

@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageEncoder_DEFINED
+#define SkImageEncoder_DEFINED
+
+#include "SkBitmap.h"
+#include "SkData.h"
+#include "SkEncodedImageFormat.h"
+#include "SkStream.h"
+
+/**
+ * Encode SkPixmap in the given binary image format.
+ *
+ * @param  dst     results are written to this stream.
+ * @param  src     source pixels.
+ * @param  format  image format, not all formats are supported.
+ * @param  quality range from 0-100, this is supported by jpeg and webp.
+ *                 higher values correspond to improved visual quality, but less compression.
+ *
+ * @return false iff input is bad or format is unsupported.
+ *
+ * Will always return false if Skia is compiled without image
+ * encoders.
+ *
+ * Note that webp encodes will use webp lossy compression.
+ *
+ * For examples of encoding an image to a file or to a block of memory,
+ * see tools/sk_tool_utils.h.
+ */
+SK_API bool SkEncodeImage(SkWStream* dst, const SkPixmap& src,
+                          SkEncodedImageFormat format, int quality);
+
+/**
+ * The following helper function wraps SkEncodeImage().
+ */
+inline bool SkEncodeImage(SkWStream* dst, const SkBitmap& src, SkEncodedImageFormat f, int q) {
+    SkPixmap pixmap;
+    return src.peekPixels(&pixmap) && SkEncodeImage(dst, pixmap, f, q);
+}
+
+/**
+ * Encode SkPixmap in the given binary image format.
+ *
+ * @param  src     source pixels.
+ * @param  format  image format, not all formats are supported.
+ * @param  quality range from 0-100, this is supported by jpeg and webp.
+ *                 higher values correspond to improved visual quality, but less compression.
+ *
+ * @return encoded data or nullptr if input is bad or format is unsupported.
+ *
+ * Will always return nullptr if Skia is compiled without image
+ * encoders.
+ *
+ * Note that webp encodes will use webp lossy compression.
+ */
+SK_API sk_sp<SkData> SkEncodePixmap(const SkPixmap& src, SkEncodedImageFormat format, int quality);
+
+/**
+ *  Helper that extracts the pixmap from the bitmap, and then calls SkEncodePixmap()
+ */
+SK_API sk_sp<SkData> SkEncodeBitmap(const SkBitmap& src, SkEncodedImageFormat format, int quality);
+
+#endif  // SkImageEncoder_DEFINED

+ 479 - 0
skia/include/core/SkImageFilter.h

@@ -0,0 +1,479 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageFilter_DEFINED
+#define SkImageFilter_DEFINED
+
+#include "../private/SkTArray.h"
+#include "../private/SkTemplates.h"
+#include "../private/SkMutex.h"
+#include "SkColorSpace.h"
+#include "SkFilterQuality.h"
+#include "SkFlattenable.h"
+#include "SkImageInfo.h"
+#include "SkMatrix.h"
+#include "SkRect.h"
+
+class GrContext;
+class GrFragmentProcessor;
+class SkColorFilter;
+class SkColorSpaceXformer;
+struct SkIPoint;
+class SkSpecialImage;
+class SkImageFilterCache;
+struct SkImageFilterCacheKey;
+
+/**
+ *  Base class for image filters. If one is installed in the paint, then
+ *  all drawing occurs as usual, but it is as if the drawing happened into an
+ *  offscreen (before the xfermode is applied). This offscreen bitmap will
+ *  then be handed to the imagefilter, who in turn creates a new bitmap which
+ *  is what will finally be drawn to the device (using the original xfermode).
+ */
+class SK_API SkImageFilter : public SkFlattenable {
+public:
+    // Extra information about the output of a filter DAG. For now, this is just the color space
+    // (of the original requesting device). This is used when constructing intermediate rendering
+    // surfaces, so that we ensure we land in a surface that's similar/compatible to the final
+    // consumer of the DAG's output.
+    class OutputProperties {
+    public:
+        explicit OutputProperties(SkColorType colorType, SkColorSpace* colorSpace)
+            : fColorType(colorType), fColorSpace(colorSpace) {}
+
+        SkColorType colorType() const { return fColorType; }
+        SkColorSpace* colorSpace() const { return fColorSpace; }
+
+    private:
+        SkColorType fColorType;
+        // This will be a pointer to the device's color space, and our lifetime is bounded by
+        // the device, so we can store a bare pointer.
+        SkColorSpace* fColorSpace;
+    };
+
+    class Context {
+    public:
+        Context(const SkMatrix& ctm, const SkIRect& clipBounds, SkImageFilterCache* cache,
+                const OutputProperties& outputProperties)
+            : fCTM(ctm)
+            , fClipBounds(clipBounds)
+            , fCache(cache)
+            , fOutputProperties(outputProperties)
+        {}
+
+        const SkMatrix& ctm() const { return fCTM; }
+        const SkIRect& clipBounds() const { return fClipBounds; }
+        SkImageFilterCache* cache() const { return fCache; }
+        const OutputProperties& outputProperties() const { return fOutputProperties; }
+
+        /**
+         *  Since a context can be build directly, its constructor has no chance to
+         *  "return null" if it's given invalid or unsupported inputs. Call this to
+         *  know of the the context can be used.
+         *
+         *  The SkImageFilterCache Key, for example, requires a finite ctm (no infinities
+         *  or NaN), so that test is part of isValid.
+         */
+        bool isValid() const { return fCTM.isFinite(); }
+
+    private:
+        SkMatrix               fCTM;
+        SkIRect                fClipBounds;
+        SkImageFilterCache*    fCache;
+        OutputProperties       fOutputProperties;
+    };
+
+    class CropRect {
+    public:
+        enum CropEdge {
+            kHasLeft_CropEdge   = 0x01,
+            kHasTop_CropEdge    = 0x02,
+            kHasWidth_CropEdge  = 0x04,
+            kHasHeight_CropEdge = 0x08,
+            kHasAll_CropEdge    = 0x0F,
+        };
+        CropRect() {}
+        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge)
+            : fRect(rect), fFlags(flags) {}
+        uint32_t flags() const { return fFlags; }
+        const SkRect& rect() const { return fRect; }
+
+        /**
+         *  Apply this cropRect to the imageBounds. If a given edge of the cropRect is not
+         *  set, then the corresponding edge from imageBounds will be used. If "embiggen"
+         *  is true, the crop rect is allowed to enlarge the size of the rect, otherwise
+         *  it may only reduce the rect. Filters that can affect transparent black should
+         *  pass "true", while all other filters should pass "false".
+         *
+         *  Note: imageBounds is in "device" space, as the output cropped rectangle will be,
+         *  so the matrix is ignored for those. It is only applied the croprect's bounds.
+         */
+        void applyTo(const SkIRect& imageBounds, const SkMatrix& matrix, bool embiggen,
+                     SkIRect* cropped) const;
+
+    private:
+        SkRect fRect;
+        uint32_t fFlags;
+    };
+
+    enum TileUsage {
+        kPossible_TileUsage,    //!< the created device may be drawn tiled
+        kNever_TileUsage,       //!< the created device will never be drawn tiled
+    };
+
+    /**
+     *  Request a new filtered image to be created from the src image.
+     *
+     *  The context contains the environment in which the filter is occurring.
+     *  It includes the clip bounds, CTM and cache.
+     *
+     *  Offset is the amount to translate the resulting image relative to the
+     *  src when it is drawn. This is an out-param.
+     *
+     *  If the result image cannot be created, or the result would be
+     *  transparent black, return null, in which case the offset parameter
+     *  should be ignored by the caller.
+     *
+     *  TODO: Right now the imagefilters sometimes return empty result bitmaps/
+     *        specialimages. That doesn't seem quite right.
+     */
+    sk_sp<SkSpecialImage> filterImage(SkSpecialImage* src, const Context& context,
+                                      SkIPoint* offset) const;
+
+    enum MapDirection {
+        kForward_MapDirection,
+        kReverse_MapDirection,
+    };
+    /**
+     * Map a device-space rect recursively forward or backward through the
+     * filter DAG. kForward_MapDirection is used to determine which pixels of
+     * the destination canvas a source image rect would touch after filtering.
+     * kReverse_MapDirection is used to determine which rect of the source
+     * image would be required to fill the given rect (typically, clip bounds).
+     * Used for clipping and temp-buffer allocations, so the result need not
+     * be exact, but should never be smaller than the real answer. The default
+     * implementation recursively unions all input bounds, or returns the
+     * source rect if no inputs.
+     *
+     * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward
+     * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting
+     * answer may be incorrect.
+     */
+    SkIRect filterBounds(const SkIRect& src, const SkMatrix& ctm,
+                         MapDirection, const SkIRect* inputRect = nullptr) const;
+
+#if SK_SUPPORT_GPU
+    static sk_sp<SkSpecialImage> DrawWithFP(GrContext* context,
+                                            std::unique_ptr<GrFragmentProcessor> fp,
+                                            const SkIRect& bounds,
+                                            const OutputProperties& outputProperties);
+#endif
+
+    /**
+     *  Returns whether this image filter is a color filter and puts the color filter into the
+     *  "filterPtr" parameter if it can. Does nothing otherwise.
+     *  If this returns false, then the filterPtr is unchanged.
+     *  If this returns true, then if filterPtr is not null, it must be set to a ref'd colorfitler
+     *  (i.e. it may not be set to NULL).
+     */
+    bool isColorFilterNode(SkColorFilter** filterPtr) const {
+        return this->onIsColorFilterNode(filterPtr);
+    }
+
+    // DEPRECATED : use isColorFilterNode() instead
+    bool asColorFilter(SkColorFilter** filterPtr) const {
+        return this->isColorFilterNode(filterPtr);
+    }
+
+    void removeKey(const SkImageFilterCacheKey& key) const;
+
+    /**
+     *  Returns true (and optionally returns a ref'd filter) if this imagefilter can be completely
+     *  replaced by the returned colorfilter. i.e. the two effects will affect drawing in the
+     *  same way.
+     */
+    bool asAColorFilter(SkColorFilter** filterPtr) const;
+
+    /**
+     *  Returns the number of inputs this filter will accept (some inputs can
+     *  be NULL).
+     */
+    int countInputs() const { return fInputs.count(); }
+
+    /**
+     *  Returns the input filter at a given index, or NULL if no input is
+     *  connected.  The indices used are filter-specific.
+     */
+    SkImageFilter* getInput(int i) const {
+        SkASSERT(i < fInputs.count());
+        return fInputs[i].get();
+    }
+
+    /**
+     *  Returns whether any edges of the crop rect have been set. The crop
+     *  rect is set at construction time, and determines which pixels from the
+     *  input image will be processed, and which pixels in the output image will be allowed.
+     *  The size of the crop rect should be
+     *  used as the size of the destination image. The origin of this rect
+     *  should be used to offset access to the input images, and should also
+     *  be added to the "offset" parameter in onFilterImage.
+     */
+    bool cropRectIsSet() const { return fCropRect.flags() != 0x0; }
+
+    CropRect getCropRect() const { return fCropRect; }
+
+    // Default impl returns union of all input bounds.
+    virtual SkRect computeFastBounds(const SkRect& bounds) const;
+
+    // Can this filter DAG compute the resulting bounds of an object-space rectangle?
+    bool canComputeFastBounds() const;
+
+    /**
+     *  If this filter can be represented by another filter + a localMatrix, return that filter,
+     *  else return null.
+     */
+    sk_sp<SkImageFilter> makeWithLocalMatrix(const SkMatrix& matrix) const;
+
+    /**
+     *  ImageFilters can natively handle scaling and translate components in the CTM. Only some of
+     *  them can handle affine (or more complex) matrices. This call returns true iff the filter
+     *  and all of its (non-null) inputs can handle these more complex matrices.
+     */
+    bool canHandleComplexCTM() const;
+
+    /**
+     * Return an imagefilter which transforms its input by the given matrix.
+     */
+    static sk_sp<SkImageFilter> MakeMatrixFilter(const SkMatrix& matrix,
+                                                 SkFilterQuality quality,
+                                                 sk_sp<SkImageFilter> input);
+
+    static void RegisterFlattenables();
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkImageFilter_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkImageFilter_Type;
+    }
+
+    static sk_sp<SkImageFilter> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkImageFilter>(static_cast<SkImageFilter*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkImageFilter_Type, data, size, procs).release()));
+    }
+
+protected:
+    class Common {
+    public:
+        /**
+         *  Attempt to unflatten the cropRect and the expected number of input filters.
+         *  If any number of input filters is valid, pass -1.
+         *  If this fails (i.e. corrupt buffer or contents) then return false and common will
+         *  be left uninitialized.
+         *  If this returns true, then inputCount() is the number of found input filters, each
+         *  of which may be NULL or a valid imagefilter.
+         */
+        bool unflatten(SkReadBuffer&, int expectedInputs);
+
+        const CropRect& cropRect() const { return fCropRect; }
+        int             inputCount() const { return fInputs.count(); }
+        sk_sp<SkImageFilter>* inputs() { return fInputs.begin(); }
+
+        sk_sp<SkImageFilter> getInput(int index) { return fInputs[index]; }
+
+    private:
+        CropRect fCropRect;
+        // most filters accept at most 2 input-filters
+        SkSTArray<2, sk_sp<SkImageFilter>, true> fInputs;
+    };
+
+    SkImageFilter(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);
+
+    ~SkImageFilter() override;
+
+    /**
+     *  Constructs a new SkImageFilter read from an SkReadBuffer object.
+     *
+     *  @param inputCount    The exact number of inputs expected for this SkImageFilter object.
+     *                       -1 can be used if the filter accepts any number of inputs.
+     *  @param rb            SkReadBuffer object from which the SkImageFilter is read.
+     */
+    explicit SkImageFilter(int inputCount, SkReadBuffer& rb);
+
+    void flatten(SkWriteBuffer&) const override;
+
+    const CropRect* getCropRectIfSet() const {
+        return this->cropRectIsSet() ? &fCropRect : nullptr;
+    }
+
+    /**
+     *  This is the virtual which should be overridden by the derived class
+     *  to perform image filtering.
+     *
+     *  src is the original primitive bitmap. If the filter has a connected
+     *  input, it should recurse on that input and use that in place of src.
+     *
+     *  The matrix is the current matrix on the canvas.
+     *
+     *  Offset is the amount to translate the resulting image relative to the
+     *  src when it is drawn. This is an out-param.
+     *
+     *  If the result image cannot be created (either because of error or if, say, the result
+     *  is entirely clipped out), this should return nullptr.
+     *  Callers that affect transparent black should explicitly handle nullptr
+     *  results and press on. In the error case this behavior will produce a better result
+     *  than nothing and is necessary for the clipped out case.
+     *  If the return value is nullptr then offset should be ignored.
+     */
+    virtual sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* src, const Context&,
+                                                SkIPoint* offset) const = 0;
+
+    /**
+     * This function recurses into its inputs with the given rect (first
+     * argument), calls filterBounds() with the given map direction on each,
+     * and returns the union of those results. If a derived class has special
+     * recursion requirements (e.g., it has an input which does not participate
+     * in bounds computation), it can be overridden here.
+     * In kReverse mode, 'inputRect' is the device-space bounds of the input pixels. In kForward
+     * mode it should always be null. If 'inputRect' is null in kReverse mode the resulting
+     * answer may be incorrect.
+     *
+     * Note that this function is *not* responsible for mapping the rect for
+     * this node's filter bounds requirements (i.e., calling
+     * onFilterNodeBounds()); that is handled by filterBounds().
+     */
+    virtual SkIRect onFilterBounds(const SkIRect&, const SkMatrix& ctm,
+                                   MapDirection, const SkIRect* inputRect) const;
+
+    /**
+     * Performs a forwards or reverse mapping of the given rect to accommodate
+     * this filter's margin requirements. kForward_MapDirection is used to
+     * determine the destination pixels which would be touched by filtering
+     * the given source rect (e.g., given source bitmap bounds,
+     * determine the optimal bounds of the filtered offscreen bitmap).
+     * kReverse_MapDirection is used to determine which pixels of the
+     * input(s) would be required to fill the given destination rect
+     * (e.g., clip bounds). NOTE: these operations may not be the
+     * inverse of the other. For example, blurring expands the given rect
+     * in both forward and reverse directions. Unlike
+     * onFilterBounds(), this function is non-recursive.
+     * In kReverse mode, 'inputRect' will be the device space bounds of the input pixels. In
+     * kForward mode, 'inputRect' should always be null. If 'inputRect' is null in kReverse mode
+     * the resulting answer may be incorrect.
+     */
+    virtual SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix& ctm,
+                                       MapDirection, const SkIRect* inputRect) const;
+
+    // Helper function which invokes filter processing on the input at the
+    // specified "index". If the input is null, it returns "src" and leaves
+    // "offset" untouched. If the input is non-null, it
+    // calls filterImage() on that input, and returns the result.
+    sk_sp<SkSpecialImage> filterInput(int index,
+                                      SkSpecialImage* src,
+                                      const Context&,
+                                      SkIPoint* offset) const;
+
+    /**
+     *  Return true (and return a ref'd colorfilter) if this node in the DAG is just a
+     *  colorfilter w/o CropRect constraints.
+     */
+    virtual bool onIsColorFilterNode(SkColorFilter** /*filterPtr*/) const {
+        return false;
+    }
+
+    /**
+     *  Override this to describe the behavior of your subclass - as a leaf node. The caller will
+     *  take care of calling your inputs (and return false if any of them could not handle it).
+     */
+    virtual bool onCanHandleComplexCTM() const { return false; }
+
+    /** Given a "srcBounds" rect, computes destination bounds for this filter.
+     *  "dstBounds" are computed by transforming the crop rect by the context's
+     *  CTM, applying it to the initial bounds, and intersecting the result with
+     *  the context's clip bounds.  "srcBounds" (if non-null) are computed by
+     *  intersecting the initial bounds with "dstBounds", to ensure that we never
+     *  sample outside of the crop rect (this restriction may be relaxed in the
+     *  future).
+     */
+    bool applyCropRect(const Context&, const SkIRect& srcBounds, SkIRect* dstBounds) const;
+
+    /** A variant of the above call which takes the original source bitmap and
+     *  source offset. If the resulting crop rect is not entirely contained by
+     *  the source bitmap's bounds, it creates a new bitmap in "result" and
+     *  pads the edges with transparent black. In that case, the srcOffset is
+     *  modified to be the same as the bounds, since no further adjustment is
+     *  needed by the caller. This version should only be used by filters
+     *  which are not capable of processing a smaller source bitmap into a
+     *  larger destination.
+     */
+    sk_sp<SkSpecialImage> applyCropRectAndPad(const Context&, SkSpecialImage* src,
+                                              SkIPoint* srcOffset, SkIRect* bounds) const;
+
+    /**
+     *  Creates a modified Context for use when recursing up the image filter DAG.
+     *  The clip bounds are adjusted to accommodate any margins that this
+     *  filter requires by calling this node's
+     *  onFilterNodeBounds(..., kReverse_MapDirection).
+     */
+    Context mapContext(const Context& ctx) const;
+
+#if SK_SUPPORT_GPU
+    /**
+     *  Returns a version of the passed-in image (possibly the original), that is in a colorspace
+     *  with the same gamut as the one from the OutputProperties. This allows filters that do many
+     *  texture samples to guarantee that any color space conversion has happened before running.
+     */
+    static sk_sp<SkSpecialImage> ImageToColorSpace(SkSpecialImage* src, const OutputProperties&);
+#endif
+
+    /**
+     *  Returns an image filter transformed into a new color space via the |xformer|.
+     */
+    sk_sp<SkImageFilter> makeColorSpace(SkColorSpaceXformer* xformer) const {
+        return this->onMakeColorSpace(xformer);
+    }
+    virtual sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const = 0;
+
+    sk_sp<SkImageFilter> refMe() const {
+        return sk_ref_sp(const_cast<SkImageFilter*>(this));
+    }
+
+    // If 'srcBounds' will sample outside the border of 'originalSrcBounds' (i.e., the sample
+    // will wrap around to the other side) we must preserve the far side of the src along that
+    // axis (e.g., if we will sample beyond the left edge of the src, the right side must be
+    // preserved for the repeat sampling to work).
+    static SkIRect DetermineRepeatedSrcBound(const SkIRect& srcBounds,
+                                             const SkIVector& filterOffset,
+                                             const SkISize& filterSize,
+                                             const SkIRect& originalSrcBounds);
+
+private:
+    // For makeColorSpace().
+    friend class SkColorSpaceXformer;
+
+    friend class SkGraphics;
+
+    static void PurgeCache();
+
+    void init(sk_sp<SkImageFilter> const* inputs, int inputCount, const CropRect* cropRect);
+
+    bool usesSrcInput() const { return fUsesSrcInput; }
+    virtual bool affectsTransparentBlack() const { return false; }
+
+    SkAutoSTArray<2, sk_sp<SkImageFilter>> fInputs;
+
+    bool fUsesSrcInput;
+    CropRect fCropRect;
+    uint32_t fUniqueID; // Globally unique
+
+    typedef SkFlattenable INHERITED;
+};
+
+#endif

+ 207 - 0
skia/include/core/SkImageGenerator.h

@@ -0,0 +1,207 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkImageGenerator_DEFINED
+#define SkImageGenerator_DEFINED
+
+#include "SkBitmap.h"
+#include "SkColor.h"
+#include "SkImage.h"
+#include "SkImageInfo.h"
+#include "SkYUVAIndex.h"
+#include "SkYUVASizeInfo.h"
+
+class GrContext;
+class GrContextThreadSafeProxy;
+class GrTextureProxy;
+class GrSamplerState;
+class SkBitmap;
+class SkData;
+class SkMatrix;
+class SkPaint;
+class SkPicture;
+
+class SK_API SkImageGenerator {
+public:
+    /**
+     *  The PixelRef which takes ownership of this SkImageGenerator
+     *  will call the image generator's destructor.
+     */
+    virtual ~SkImageGenerator() { }
+
+    uint32_t uniqueID() const { return fUniqueID; }
+
+    /**
+     *  Return a ref to the encoded (i.e. compressed) representation
+     *  of this data.
+     *
+     *  If non-NULL is returned, the caller is responsible for calling
+     *  unref() on the data when it is finished.
+     */
+    sk_sp<SkData> refEncodedData() {
+        return this->onRefEncodedData();
+    }
+
+    /**
+     *  Return the ImageInfo associated with this generator.
+     */
+    const SkImageInfo& getInfo() const { return fInfo; }
+
+    /**
+     *  Can this generator be used to produce images that will be drawable to the specified context
+     *  (or to CPU, if context is nullptr)?
+     */
+    bool isValid(GrContext* context) const {
+        return this->onIsValid(context);
+    }
+
+    /**
+     *  Decode into the given pixels, a block of memory of size at
+     *  least (info.fHeight - 1) * rowBytes + (info.fWidth *
+     *  bytesPerPixel)
+     *
+     *  Repeated calls to this function should give the same results,
+     *  allowing the PixelRef to be immutable.
+     *
+     *  @param info A description of the format
+     *         expected by the caller.  This can simply be identical
+     *         to the info returned by getInfo().
+     *
+     *         This contract also allows the caller to specify
+     *         different output-configs, which the implementation can
+     *         decide to support or not.
+     *
+     *         A size that does not match getInfo() implies a request
+     *         to scale. If the generator cannot perform this scale,
+     *         it will return false.
+     *
+     *  @return true on success.
+     */
+    bool getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes);
+
+    /**
+     *  If decoding to YUV is supported, this returns true.  Otherwise, this
+     *  returns false and does not modify any of the parameters.
+     *
+     *  @param sizeInfo    Output parameter indicating the sizes and required
+     *                     allocation widths of the Y, U, V, and A planes.
+     *  @param yuvaIndices How the YUVA planes are organized/used
+     *  @param colorSpace  Output parameter.
+     */
+    bool queryYUVA8(SkYUVASizeInfo* sizeInfo,
+                    SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
+                    SkYUVColorSpace* colorSpace) const;
+
+    /**
+     *  Returns true on success and false on failure.
+     *  This always attempts to perform a full decode.  If the client only
+     *  wants size, it should call queryYUVA8().
+     *
+     *  @param sizeInfo    Needs to exactly match the values returned by the
+     *                     query, except the WidthBytes may be larger than the
+     *                     recommendation (but not smaller).
+     *  @param yuvaIndices Needs to exactly match the values returned by the query.
+     *  @param planes      Memory for the Y, U, V, and A planes. Note that, depending on the
+     *                     settings in yuvaIndices, anywhere from 1..4 planes could be returned.
+     */
+    bool getYUVA8Planes(const SkYUVASizeInfo& sizeInfo,
+                        const SkYUVAIndex yuvaIndices[SkYUVAIndex::kIndexCount],
+                        void* planes[]);
+
+#if SK_SUPPORT_GPU
+    /**
+     *  If the generator can natively/efficiently return its pixels as a GPU image (backed by a
+     *  texture) this will return that image. If not, this will return NULL.
+     *
+     *  This routine also supports retrieving only a subset of the pixels. That subset is specified
+     *  by the following rectangle:
+     *
+     *      subset = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height())
+     *
+     *  If subset is not contained inside the generator's bounds, this returns false.
+     *
+     *      whole = SkIRect::MakeWH(getInfo().width(), getInfo().height())
+     *      if (!whole.contains(subset)) {
+     *          return false;
+     *      }
+     *
+     *  Regarding the GrContext parameter:
+     *
+     *  It must be non-NULL. The generator should only succeed if:
+     *  - its internal context is the same
+     *  - it can somehow convert its texture into one that is valid for the provided context.
+     *
+     *  If the willNeedMipMaps flag is true, the generator should try to create a TextureProxy that
+     *  at least has the mip levels allocated and the base layer filled in. If this is not possible,
+     *  the generator is allowed to return a non mipped proxy, but this will have some additional
+     *  overhead in later allocating mips and copying of the base layer.
+     */
+    sk_sp<GrTextureProxy> generateTexture(GrContext*, const SkImageInfo& info,
+                                          const SkIPoint& origin,
+                                          bool willNeedMipMaps);
+#endif
+
+    /**
+     *  If the default image decoder system can interpret the specified (encoded) data, then
+     *  this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
+     *  the caller is still responsible for managing their ownership of the data.
+     */
+    static std::unique_ptr<SkImageGenerator> MakeFromEncoded(sk_sp<SkData>);
+
+    /** Return a new image generator backed by the specified picture.  If the size is empty or
+     *  the picture is NULL, this returns NULL.
+     *  The optional matrix and paint arguments are passed to drawPicture() at rasterization
+     *  time.
+     */
+    static std::unique_ptr<SkImageGenerator> MakeFromPicture(const SkISize&, sk_sp<SkPicture>,
+                                                             const SkMatrix*, const SkPaint*,
+                                                             SkImage::BitDepth,
+                                                             sk_sp<SkColorSpace>);
+
+protected:
+    static constexpr int kNeedNewImageUniqueID = 0;
+
+    SkImageGenerator(const SkImageInfo& info, uint32_t uniqueId = kNeedNewImageUniqueID);
+
+    virtual sk_sp<SkData> onRefEncodedData() { return nullptr; }
+    struct Options {};
+    virtual bool onGetPixels(const SkImageInfo&, void*, size_t, const Options&) { return false; }
+    virtual bool onIsValid(GrContext*) const { return true; }
+    virtual bool onQueryYUVA8(SkYUVASizeInfo*, SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                              SkYUVColorSpace*) const { return false; }
+    virtual bool onGetYUVA8Planes(const SkYUVASizeInfo&, const SkYUVAIndex[SkYUVAIndex::kIndexCount],
+                                  void*[4] /*planes*/) { return false; }
+#if SK_SUPPORT_GPU
+    enum class TexGenType {
+        kNone,           //image generator does not implement onGenerateTexture
+        kCheap,          //onGenerateTexture is implemented and it is fast (does not render offscreen)
+        kExpensive,      //onGenerateTexture is implemented and it is relatively slow
+    };
+
+    virtual TexGenType onCanGenerateTexture() const { return TexGenType::kNone; }
+    virtual sk_sp<GrTextureProxy> onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&,
+                                                    bool willNeedMipMaps);  // returns nullptr
+#endif
+
+private:
+    const SkImageInfo fInfo;
+    const uint32_t fUniqueID;
+
+    friend class SkImage_Lazy;
+
+    // This is our default impl, which may be different on different platforms.
+    // It is called from NewFromEncoded() after it has checked for any runtime factory.
+    // The SkData will never be NULL, as that will have been checked by NewFromEncoded.
+    static std::unique_ptr<SkImageGenerator> MakeFromEncodedImpl(sk_sp<SkData>);
+
+    SkImageGenerator(SkImageGenerator&&) = delete;
+    SkImageGenerator(const SkImageGenerator&) = delete;
+    SkImageGenerator& operator=(SkImageGenerator&&) = delete;
+    SkImageGenerator& operator=(const SkImageGenerator&) = delete;
+};
+
+#endif  // SkImageGenerator_DEFINED

+ 623 - 0
skia/include/core/SkImageInfo.h

@@ -0,0 +1,623 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkImageInfo.h and docs/SkImageInfo_Reference.bmh
+   on 2018-07-13 08:15:11. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkImageInfo_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkImageInfo_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkImageInfo.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkImageInfo_DEFINED
+#define SkImageInfo_DEFINED
+
+#include "SkColorSpace.h"
+#include "SkMath.h"
+#include "SkRect.h"
+#include "SkSize.h"
+
+#include "../private/SkTFitsIn.h"
+#include "../private/SkTo.h"
+
+class SkReadBuffer;
+class SkWriteBuffer;
+
+/** \enum SkImageInfo::SkAlphaType
+    Describes how to interpret the alpha component of a pixel. A pixel may
+    be opaque, or alpha, describing multiple levels of transparency.
+
+    In simple blending, alpha weights the draw color and the destination
+    color to create a new color. If alpha describes a weight from zero to one:
+
+    new color = draw color * alpha + destination color * (1 - alpha)
+
+    In practice alpha is encoded in two or more bits, where 1.0 equals all bits set.
+
+    RGB may have alpha included in each component value; the stored
+    value is the original RGB multiplied by alpha. Premultiplied color
+    components improve performance.
+*/
+enum SkAlphaType {
+    kUnknown_SkAlphaType,                          //!< uninitialized
+    kOpaque_SkAlphaType,                           //!< pixel is opaque
+    kPremul_SkAlphaType,                           //!< pixel components are premultiplied by alpha
+    kUnpremul_SkAlphaType,                         //!< pixel components are independent of alpha
+    kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value
+};
+
+/** Returns true if SkAlphaType equals kOpaque_SkAlphaType. kOpaque_SkAlphaType is a
+    hint that the SkColorType is opaque, or that all alpha values are set to
+    their 1.0 equivalent. If SkAlphaType is kOpaque_SkAlphaType, and SkColorType is not
+    opaque, then the result of drawing any pixel with a alpha value less than
+    1.0 is undefined.
+
+    @param at  one of:
+               kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+               kUnpremul_SkAlphaType
+    @return    true if at equals kOpaque_SkAlphaType
+*/
+static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
+    return kOpaque_SkAlphaType == at;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Temporary macro that allows us to add new color types without breaking Chrome compile. */
+#define SK_EXTENDED_COLOR_TYPES
+
+/** \enum SkImageInfo::SkColorType
+    Describes how pixel bits encode color. A pixel may be an alpha mask, a
+    grayscale, RGB, or ARGB.
+
+    kN32_SkColorType selects the native 32-bit ARGB format. On little endian
+    processors, pixels containing 8-bit ARGB components pack into 32-bit
+    kBGRA_8888_SkColorType. On big endian processors, pixels pack into 32-bit
+    kRGBA_8888_SkColorType.
+*/
+enum SkColorType {
+    kUnknown_SkColorType,      //!< uninitialized
+    kAlpha_8_SkColorType,      //!< pixel with alpha in 8-bit byte
+    kRGB_565_SkColorType,      //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
+    kARGB_4444_SkColorType,    //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word
+    kRGBA_8888_SkColorType,    //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word
+    kRGB_888x_SkColorType,     //!< pixel with 8 bits each for red, green, blue; in 32-bit word
+    kBGRA_8888_SkColorType,    //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word
+    kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
+    kRGB_101010x_SkColorType,  //!< pixel with 10 bits each for red, green, blue; in 32-bit word
+    kGray_8_SkColorType,       //!< pixel with grayscale level in 8-bit byte
+    kRGBA_F16_SkColorType,   //!< pixel with half floats for red, green, blue, alpha; in 64-bit word
+    kRGBA_F32_SkColorType,     //!< pixel using C float for red, green, blue, alpha; in 128-bit word
+    kLastEnum_SkColorType     = kRGBA_F32_SkColorType,//!< last valid value
+
+#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
+    kN32_SkColorType          = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding
+
+#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+    kN32_SkColorType          = kRGBA_8888_SkColorType,//!< native ARGB 32-bit encoding
+
+#else
+    #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
+#endif
+};
+
+/** Returns the number of bytes required to store a pixel, including unused padding.
+    Returns zero if ct is kUnknown_SkColorType or invalid.
+
+    @param ct  one of:
+               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+               kGray_8_SkColorType, kRGBA_F16_SkColorType
+    @return    bytes per pixel
+*/
+SK_API int SkColorTypeBytesPerPixel(SkColorType ct);
+
+/** Returns true if SkColorType always decodes alpha to 1.0, making the pixel
+    fully opaque. If true, SkColorType does not reserve bits to encode alpha.
+
+    @param ct  one of:
+               kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+               kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+               kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+               kGray_8_SkColorType, kRGBA_F16_SkColorType
+    @return    true if alpha is always set to 1.0
+*/
+SK_API bool SkColorTypeIsAlwaysOpaque(SkColorType ct);
+
+/** Returns true if canonical can be set to a valid SkAlphaType for colorType. If
+    there is more than one valid canonical SkAlphaType, set to alphaType, if valid.
+    If true is returned and canonical is not nullptr, store valid SkAlphaType.
+
+    Returns false only if alphaType is kUnknown_SkAlphaType, color type is not
+    kUnknown_SkColorType, and SkColorType is not always opaque. If false is returned,
+    canonical is ignored.
+
+    For kUnknown_SkColorType: set canonical to kUnknown_SkAlphaType and return true.
+    For kAlpha_8_SkColorType: set canonical to kPremul_SkAlphaType or
+    kOpaque_SkAlphaType and return true if alphaType is not kUnknown_SkAlphaType.
+    For kRGB_565_SkColorType, kRGB_888x_SkColorType, kRGB_101010x_SkColorType, and
+    kGray_8_SkColorType: set canonical to kOpaque_SkAlphaType and return true.
+    For kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType,
+    kRGBA_1010102_SkColorType, and kRGBA_F16_SkColorType: set canonical to alphaType
+    and return true if alphaType is not kUnknown_SkAlphaType.
+
+    @param colorType  one of:
+                      kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+                      kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                      kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+                      kGray_8_SkColorType, kRGBA_F16_SkColorType
+    @param alphaType  one of:
+                      kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                      kUnpremul_SkAlphaType
+    @param canonical  storage for SkAlphaType
+    @return           true if valid SkAlphaType can be associated with colorType
+*/
+SK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
+                                         SkAlphaType* canonical = nullptr);
+
+/** \enum SkImageInfo::SkYUVColorSpace
+    Describes color range of YUV pixels. The color mapping from YUV to RGB varies
+    depending on the source. YUV pixels may be generated by JPEG images, standard
+    video streams, or high definition video streams. Each has its own mapping from
+    YUV and RGB.
+
+    JPEG YUV values encode the full range of 0 to 255 for all three components.
+    Video YUV values range from 16 to 235 for all three components. Details of
+    encoding and conversion to RGB are described in YCbCr color space.
+*/
+enum SkYUVColorSpace {
+    kJPEG_SkYUVColorSpace,                               //!< describes full range
+    kRec601_SkYUVColorSpace,                             //!< describes SDTV range
+    kRec709_SkYUVColorSpace,                             //!< describes HDTV range
+    kLastEnum_SkYUVColorSpace = kRec709_SkYUVColorSpace, //!< last valid value
+};
+
+/** \struct SkImageInfo
+    Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface
+    can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and
+    SkPixmap, but not from SkImage and SkSurface. For example, SkImage and SkSurface
+    implementations may defer pixel depth, so may not completely specify SkImageInfo.
+
+    SkImageInfo contains dimensions, the pixel integral width and height. It encodes
+    how pixel bits describe alpha, transparency; color components red, blue,
+    and green; and SkColorSpace, the range and linearity of colors.
+*/
+struct SK_API SkImageInfo {
+public:
+
+    /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
+        a width and height of zero, and no SkColorSpace.
+
+        @return  empty SkImageInfo
+    */
+    SkImageInfo()
+        : fColorSpace(nullptr)
+        , fDimensions{0, 0}
+        , fColorType(kUnknown_SkColorType)
+        , fAlphaType(kUnknown_SkAlphaType)
+    {}
+
+    /** Creates SkImageInfo from integral dimensions width and height, SkColorType ct,
+        SkAlphaType at, and optionally SkColorSpace cs.
+
+        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+        defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+        Parameters are not validated to see if their values are legal, or that the
+        combination is supported.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @param ct      one of:
+                       kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+                       kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                       kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+                       kGray_8_SkColorType, kRGBA_F16_SkColorType
+        @param at      one of:
+                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                       kUnpremul_SkAlphaType
+        @param cs      range of colors; may be nullptr
+        @return        created SkImageInfo
+    */
+    static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
+                            sk_sp<SkColorSpace> cs = nullptr) {
+        return SkImageInfo(width, height, ct, at, std::move(cs));
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+        SkAlphaType at, and optionally SkColorSpace cs. kN32_SkColorType will equal either
+        kBGRA_8888_SkColorType or kRGBA_8888_SkColorType, whichever is optimal.
+
+        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+        defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+        Parameters are not validated to see if their values are legal, or that the
+        combination is supported.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @param at      one of:
+                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                       kUnpremul_SkAlphaType
+        @param cs      range of colors; may be nullptr
+        @return        created SkImageInfo
+    */
+    static SkImageInfo MakeN32(int width, int height, SkAlphaType at,
+                               sk_sp<SkColorSpace> cs = nullptr) {
+        return Make(width, height, kN32_SkColorType, at, std::move(cs));
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+        SkAlphaType at, with sRGB SkColorSpace.
+
+        Parameters are not validated to see if their values are legal, or that the
+        combination is supported.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @param at      one of:
+                       kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                       kUnpremul_SkAlphaType
+        @return        created SkImageInfo
+    */
+    static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
+
+    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+        kPremul_SkAlphaType, with optional SkColorSpace.
+
+        If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace
+        defaults to sRGB, mapping into SkSurface SkColorSpace.
+
+        Parameters are not validated to see if their values are legal, or that the
+        combination is supported.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @param cs      range of colors; may be nullptr
+        @return        created SkImageInfo
+    */
+    static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) {
+        return Make(width, height, kN32_SkColorType, kPremul_SkAlphaType, std::move(cs));
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType,
+        kPremul_SkAlphaType, with SkColorSpace set to nullptr.
+
+        If SkImageInfo is part of drawing source: SkColorSpace defaults to sRGB, mapping
+        into SkSurface SkColorSpace.
+
+        Parameters are not validated to see if their values are legal, or that the
+        combination is supported.
+
+        @param size  width and height, each must be zero or greater
+        @return      created SkImageInfo
+    */
+    static SkImageInfo MakeN32Premul(const SkISize& size) {
+        return MakeN32Premul(size.width(), size.height());
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height, kAlpha_8_SkColorType,
+        kPremul_SkAlphaType, with SkColorSpace set to nullptr.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @return        created SkImageInfo
+    */
+    static SkImageInfo MakeA8(int width, int height) {
+        return Make(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height, kUnknown_SkColorType,
+        kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
+
+        Returned SkImageInfo as part of source does not draw, and as part of destination
+        can not be drawn to.
+
+        @param width   pixel column count; must be zero or greater
+        @param height  pixel row count; must be zero or greater
+        @return        created SkImageInfo
+    */
+    static SkImageInfo MakeUnknown(int width, int height) {
+        return Make(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr);
+    }
+
+    /** Creates SkImageInfo from integral dimensions width and height set to zero,
+        kUnknown_SkColorType, kUnknown_SkAlphaType, with SkColorSpace set to nullptr.
+
+        Returned SkImageInfo as part of source does not draw, and as part of destination
+        can not be drawn to.
+
+        @return  created SkImageInfo
+    */
+    static SkImageInfo MakeUnknown() {
+        return MakeUnknown(0, 0);
+    }
+
+    /** Returns pixel count in each row.
+
+        @return  pixel width
+    */
+    int width() const { return fDimensions.width(); }
+
+    /** Returns pixel row count.
+
+        @return  pixel height
+    */
+    int height() const { return fDimensions.height(); }
+
+    /** Returns SkColorType, one of:
+        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+        kGray_8_SkColorType, kRGBA_F16_SkColorType.
+
+        @return  SkColorType
+    */
+    SkColorType colorType() const { return fColorType; }
+
+    /** Returns SkAlphaType, one of:
+        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+        kUnpremul_SkAlphaType.
+
+        @return  SkAlphaType
+    */
+    SkAlphaType alphaType() const { return fAlphaType; }
+
+    /** Returns SkColorSpace, the range of colors. The reference count of
+        SkColorSpace is unchanged. The returned SkColorSpace is immutable.
+
+        @return  SkColorSpace, or nullptr
+    */
+    SkColorSpace* colorSpace() const { return fColorSpace.get(); }
+
+    /** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer
+        tracks the number of objects sharing this SkColorSpace reference so the memory
+        is released when the owners destruct.
+
+        The returned SkColorSpace is immutable.
+
+        @return  SkColorSpace wrapped in a smart pointer
+    */
+    sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
+
+    /** Returns if SkImageInfo describes an empty area of pixels by checking if either
+        width or height is zero or smaller.
+
+        @return  true if either dimension is zero or smaller
+    */
+    bool isEmpty() const { return fDimensions.isEmpty(); }
+
+    /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their
+        alpha value is implicitly or explicitly 1.0. If true, and all pixels are
+        not opaque, Skia may draw incorrectly.
+
+        Does not check if SkColorType allows alpha, or if any pixel value has
+        transparency.
+
+        @return  true if SkAlphaType is kOpaque_SkAlphaType
+    */
+    bool isOpaque() const {
+        return SkAlphaTypeIsOpaque(fAlphaType);
+    }
+
+    /** Returns SkISize { width(), height() }.
+
+        @return  integral size of width() and height()
+    */
+    SkISize dimensions() const { return fDimensions; }
+
+    /** Returns SkIRect { 0, 0, width(), height() }.
+
+        @return  integral rectangle from origin to width() and height()
+    */
+    SkIRect bounds() const { return SkIRect::MakeSize(fDimensions); }
+
+    /** Returns true if associated SkColorSpace is not nullptr, and SkColorSpace gamma
+        is approximately the same as sRGB.
+        This includes the
+
+        @return  true if SkColorSpace gamma is approximately the same as sRGB
+    */
+    bool gammaCloseToSRGB() const {
+        return fColorSpace && fColorSpace->gammaCloseToSRGB();
+    }
+
+    /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType,
+        with dimensions set to width and height.
+
+        @param newWidth   pixel column count; must be zero or greater
+        @param newHeight  pixel row count; must be zero or greater
+        @return           created SkImageInfo
+    */
+    SkImageInfo makeWH(int newWidth, int newHeight) const {
+        return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace);
+    }
+
+    /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height,
+        with SkAlphaType set to newAlphaType.
+
+        Created SkImageInfo contains newAlphaType even if it is incompatible with
+        SkColorType, in which case SkAlphaType in SkImageInfo is ignored.
+
+        @param newAlphaType  one of:
+                             kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+                             kUnpremul_SkAlphaType
+        @return              created SkImageInfo
+    */
+    SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
+        return Make(this->width(), this->height(), fColorType, newAlphaType, fColorSpace);
+    }
+
+    /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height,
+        with SkColorType set to newColorType.
+
+        @param newColorType  one of:
+                             kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+                             kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+                             kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType,
+                             kRGB_101010x_SkColorType, kGray_8_SkColorType, kRGBA_F16_SkColorType
+        @return              created SkImageInfo
+    */
+    SkImageInfo makeColorType(SkColorType newColorType) const {
+        return Make(this->width(), this->height(), newColorType, fAlphaType, fColorSpace);
+    }
+
+    /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height,
+        with SkColorSpace set to cs.
+
+        @param cs  range of colors; may be nullptr
+        @return    created SkImageInfo
+    */
+    SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {
+        return Make(this->width(), this->height(), fColorType, fAlphaType, std::move(cs));
+    }
+
+    /** Returns number of bytes per pixel required by SkColorType.
+        Returns zero if colorType( is kUnknown_SkColorType.
+
+        @return  bytes in pixel
+    */
+    int bytesPerPixel() const;
+
+    /** Returns bit shift converting row bytes to row pixels.
+        Returns zero for kUnknown_SkColorType.
+
+        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+    */
+    int shiftPerPixel() const;
+
+    /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
+        specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
+        in 31 bits.
+
+        @return  width() times bytesPerPixel() as unsigned 64-bit integer
+    */
+    uint64_t minRowBytes64() const { return sk_64_mul(this->width(), this->bytesPerPixel()); }
+
+    /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which
+        specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit
+        in 31 bits.
+
+        @return  width() times bytesPerPixel() as signed 32-bit integer
+    */
+    size_t minRowBytes() const {
+        uint64_t minRowBytes = this->minRowBytes64();
+        if (!SkTFitsIn<int32_t>(minRowBytes)) {
+            return 0;
+        }
+        return SkTo<int32_t>(minRowBytes);
+    }
+
+    /** Returns byte offset of pixel from pixel base address.
+
+        Asserts in debug build if x or y is outside of bounds. Does not assert if
+        rowBytes is smaller than minRowBytes(), even though result may be incorrect.
+
+        @param x         column index, zero or greater, and less than width()
+        @param y         row index, zero or greater, and less than height()
+        @param rowBytes  size of pixel row or larger
+        @return          offset within pixel array
+    */
+    size_t computeOffset(int x, int y, size_t rowBytes) const;
+
+    /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
+        SkAlphaType, and SkColorSpace are equivalent.
+
+        @param other  SkImageInfo to compare
+        @return       true if SkImageInfo equals other
+    */
+    bool operator==(const SkImageInfo& other) const {
+        return fDimensions == other.fDimensions &&
+               fColorType == other.fColorType && fAlphaType == other.fAlphaType &&
+               SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());
+    }
+
+    /** Compares SkImageInfo with other, and returns true if width, height, SkColorType,
+        SkAlphaType, and SkColorSpace are not equivalent.
+
+        @param other  SkImageInfo to compare
+        @return       true if SkImageInfo is not equal to other
+    */
+    bool operator!=(const SkImageInfo& other) const {
+        return !(*this == other);
+    }
+
+    /** Returns storage required by pixel array, given SkImageInfo dimensions, SkColorType,
+        and rowBytes. rowBytes is assumed to be at least as large as minRowBytes().
+
+        Returns zero if height is zero.
+        Returns SIZE_MAX if answer exceeds the range of size_t.
+
+        @param rowBytes  size of pixel row or larger
+        @return          memory required by pixel buffer
+    */
+    size_t computeByteSize(size_t rowBytes) const;
+
+    /** Returns storage required by pixel array, given SkImageInfo dimensions, and
+        SkColorType. Uses minRowBytes() to compute bytes for pixel row.
+
+        Returns zero if height is zero.
+        Returns SIZE_MAX if answer exceeds the range of size_t.
+
+        @return  least memory required by pixel buffer
+    */
+    size_t computeMinByteSize() const {
+        return this->computeByteSize(this->minRowBytes());
+    }
+
+    /** Returns true if byteSize equals SIZE_MAX. computeByteSize() and
+        computeMinByteSize() return SIZE_MAX if size_t can not hold buffer size.
+
+        @param byteSize  result of computeByteSize() or computeMinByteSize()
+        @return          true if computeByteSize() or computeMinByteSize() result exceeds size_t
+    */
+    static bool ByteSizeOverflowed(size_t byteSize) {
+        return SIZE_MAX == byteSize;
+    }
+
+    /** Returns true if rowBytes is smaller than width times pixel size.
+
+        @param rowBytes  size of pixel row or larger
+        @return          true if rowBytes is large enough to contain pixel row
+    */
+    bool validRowBytes(size_t rowBytes) const {
+        return rowBytes >= this->minRowBytes64();
+    }
+
+    /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType,
+        a width and height of zero, and no SkColorSpace.
+    */
+    void reset() {
+        fColorSpace = nullptr;
+        fDimensions = {0, 0};
+        fColorType = kUnknown_SkColorType;
+        fAlphaType = kUnknown_SkAlphaType;
+    }
+
+    /** Asserts if internal values are illegal or inconsistent. Only available if
+        SK_DEBUG is defined at compile time.
+    */
+    SkDEBUGCODE(void validate() const;)
+
+private:
+    sk_sp<SkColorSpace> fColorSpace;
+    SkISize             fDimensions;
+    SkColorType         fColorType;
+    SkAlphaType         fAlphaType;
+
+    SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs)
+        : fColorSpace(std::move(cs))
+        , fDimensions{width, height}
+        , fColorType(ct)
+        , fAlphaType(at)
+    {}
+};
+
+#endif

+ 195 - 0
skia/include/core/SkLights.h

@@ -0,0 +1,195 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkLights_DEFINED
+#define SkLights_DEFINED
+
+#include "SkPoint3.h"
+#include "SkRefCnt.h"
+#include "../private/SkTArray.h"
+
+class SkColorSpaceXformer;
+class SkReadBuffer;
+class SkWriteBuffer;
+
+/** \class SkLights
+    SkLights encapsulates a set of directional, point and ambient lights for use with the
+    SkLightingShader.
+*/
+class SK_API SkLights  : public SkRefCnt {
+public:
+    class Light {
+    public:
+        enum LightType {
+            kDirectional_LightType,
+            kPoint_LightType
+        };
+
+        Light(const Light& other)
+                : fType(other.fType)
+                , fColor(other.fColor)
+                , fDirOrPos(other.fDirOrPos)
+                , fIntensity(other.fIntensity) {}
+
+        Light(Light&& other)
+                : fType(other.fType)
+                , fColor(other.fColor)
+                , fDirOrPos(other.fDirOrPos)
+                , fIntensity(other.fIntensity) {}
+
+        static Light MakeDirectional(const SkColor3f& color, const SkVector3& dir) {
+            Light light(kDirectional_LightType, color, dir, 0.0f);
+            if (!light.fDirOrPos.normalize()) {
+                light.fDirOrPos.set(0.0f, 0.0f, 1.0f);
+            }
+            return light;
+        }
+
+        static Light MakePoint(const SkColor3f& color, const SkPoint3& pos, SkScalar intensity) {
+            return Light(kPoint_LightType, color, pos, intensity);
+        }
+
+        LightType type() const { return fType; }
+        const SkColor3f& color() const { return fColor; }
+        const SkVector3& dir() const {
+            SkASSERT(kDirectional_LightType == fType);
+            return fDirOrPos;
+        }
+        const SkPoint3& pos() const {
+            SkASSERT(kPoint_LightType == fType);
+            return fDirOrPos;
+        }
+        SkScalar intensity() const {
+            SkASSERT(kPoint_LightType == fType);
+            return fIntensity;
+        }
+
+        Light& operator=(const Light& other) {
+            if (this == &other) {
+                return *this;
+            }
+
+            fType = other.fType;
+            fColor = other.fColor;
+            fDirOrPos = other.fDirOrPos;
+            fIntensity = other.fIntensity;
+            return *this;
+        }
+
+        bool operator==(const Light& other) {
+            return (fType      == other.fType) &&
+                   (fColor     == other.fColor) &&
+                   (fDirOrPos  == other.fDirOrPos) &&
+                   (fIntensity == other.fIntensity);
+        }
+
+        bool operator!=(const Light& other) { return !(this->operator==(other)); }
+
+    private:
+        friend class SkLights;
+
+        Light(LightType type, const SkColor3f& color, const SkVector3& dirOrPos,
+              SkScalar intensity)
+                : fType(type)
+                , fColor(color)
+                , fDirOrPos(dirOrPos)
+                , fIntensity(intensity) {}
+
+        LightType   fType;
+        SkColor3f   fColor;           // linear (unpremul) color. Range is 0..1 in each channel.
+
+        SkVector3   fDirOrPos;        // For directional lights, holds the direction towards the
+                                      // light (+Z is out of the screen).
+                                      // If degenerate, it will be replaced with (0, 0, 1).
+                                      // For point lights, holds location of point light
+
+        SkScalar    fIntensity;       // For point lights, dictates the light intensity.
+                                      // Simply a multiplier to the final light output value.
+    };
+
+    class Builder {
+    public:
+        Builder() : fLights(new SkLights) {}
+
+        void add(const Light& light) {
+            if (fLights) {
+                fLights->fLights.push_back(light);
+            }
+        }
+
+        void add(Light&& light) {
+            if (fLights) {
+                fLights->fLights.push_back(std::move(light));
+            }
+        }
+
+        void setAmbientLightColor(const SkColor3f& color) {
+            if (fLights) {
+                fLights->fAmbientLightColor = color;
+            }
+        }
+
+        sk_sp<SkLights> finish() {
+            return std::move(fLights);
+        }
+
+    private:
+        sk_sp<SkLights> fLights;
+    };
+
+    /** Returns number of lights not including the ambient light.
+
+        @return number of lights not including the ambient light
+    */
+    int numLights() const { return fLights.count(); }
+
+    /** Returns the index-th light.
+
+        @param index  the index of the desired light
+        @return       the index-th light
+    */
+    const Light& light(int index) const { return fLights[index]; }
+
+    /** Returns the ambient light.
+
+        @return the ambient light
+    */
+    const SkColor3f& ambientLightColor() const {
+        return fAmbientLightColor;
+    }
+
+    /**
+     *  Recreate an SkLights object that was serialized into a buffer.
+     *
+     *  @param  SkReadBuffer Serialized blob data.
+     *  @return A new SkLights representing the serialized data, or NULL if the buffer is
+     *          invalid.
+     */
+    static sk_sp<SkLights> MakeFromBuffer(SkReadBuffer& buf);
+
+    /**
+     *  Serialize to a buffer.
+     *
+     *  @param  buffer the write buffer to write out to
+     */
+    void flatten(SkWriteBuffer& buf) const;
+
+private:
+    friend class SkLightingShaderImpl;
+
+    SkLights() : fAmbientLightColor(SkColor3f::Make(0.0f, 0.0f, 0.0f)) {}
+
+    sk_sp<SkLights> makeColorSpace(SkColorSpaceXformer* xformer) const;
+
+    SkTArray<Light> fLights;
+    SkColor3f       fAmbientLightColor;
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 93 - 0
skia/include/core/SkMallocPixelRef.h

@@ -0,0 +1,93 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMallocPixelRef_DEFINED
+#define SkMallocPixelRef_DEFINED
+
+#include "SkPixelRef.h"
+#include "SkRefCnt.h"
+#include "SkTypes.h"
+class SkData;
+struct SkImageInfo;
+
+/** We explicitly use the same allocator for our pixels that SkMask does,
+    so that we can freely assign memory allocated by one class to the other.
+*/
+class SK_API SkMallocPixelRef : public SkPixelRef {
+public:
+    /**
+     *  Return a new SkMallocPixelRef with the provided pixel storage, rowBytes,
+     *  and optional colortable. The caller is responsible for managing the
+     *  lifetime of the pixel storage buffer, as this pixelref will not try
+     *  to delete it.
+     *
+     *  Returns NULL on failure.
+     */
+    static sk_sp<SkPixelRef> MakeDirect(const SkImageInfo&, void* addr, size_t rowBytes);
+
+    /**
+     *  Return a new SkMallocPixelRef, automatically allocating storage for the
+     *  pixels. If rowBytes are 0, an optimal value will be chosen automatically.
+     *  If rowBytes is > 0, then it will be respected, or NULL will be returned
+     *  if rowBytes is invalid for the specified info.
+     *
+     *  This pixelref will ref() the specified colortable (if not NULL).
+     *
+     *  Returns NULL on failure.
+     */
+    static sk_sp<SkPixelRef> MakeAllocate(const SkImageInfo&, size_t rowBytes);
+
+    /**
+     *  Identical to MakeAllocate, except all pixel bytes are zeroed.
+     */
+    static sk_sp<SkPixelRef> MakeZeroed(const SkImageInfo&, size_t rowBytes);
+
+    /**
+     *  Return a new SkMallocPixelRef with the provided pixel storage,
+     *  rowBytes, and optional colortable. On destruction, ReleaseProc
+     *  will be called.
+     *
+     *  If ReleaseProc is NULL, the pixels will never be released. This
+     *  can be useful if the pixels were stack allocated. However, such an
+     *  SkMallocPixelRef must not live beyond its pixels (e.g. by copying
+     *  an SkBitmap pointing to it, or drawing to an SkPicture).
+     *
+     *  Returns NULL on failure.
+     */
+    typedef void (*ReleaseProc)(void* addr, void* context);
+    static sk_sp<SkPixelRef> MakeWithProc(const SkImageInfo& info, size_t rowBytes, void* addr,
+                                          ReleaseProc proc, void* context);
+
+    /**
+     *  Return a new SkMallocPixelRef that will use the provided
+     *  SkData, rowBytes, and optional colortable as pixel storage.
+     *  The SkData will be ref()ed and on destruction of the PielRef,
+     *  the SkData will be unref()ed.
+     *
+     *  Returns NULL on failure.
+     */
+    static sk_sp<SkPixelRef> MakeWithData(const SkImageInfo&, size_t rowBytes, sk_sp<SkData> data);
+
+protected:
+    ~SkMallocPixelRef() override;
+
+private:
+    // Uses alloc to implement NewAllocate or NewZeroed.
+    static sk_sp<SkPixelRef> MakeUsing(void*(*alloc)(size_t),
+                                       const SkImageInfo&,
+                                       size_t rowBytes);
+
+    ReleaseProc fReleaseProc;
+    void*       fReleaseProcContext;
+
+    SkMallocPixelRef(const SkImageInfo&, void* addr, size_t rb, ReleaseProc proc, void* context);
+
+    typedef SkPixelRef INHERITED;
+};
+
+
+#endif

+ 77 - 0
skia/include/core/SkMaskFilter.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMaskFilter_DEFINED
+#define SkMaskFilter_DEFINED
+
+#include "SkBlurTypes.h"
+#include "SkCoverageMode.h"
+#include "SkFlattenable.h"
+#include "SkScalar.h"
+
+class SkMatrix;
+struct SkRect;
+class SkString;
+
+/** \class SkMaskFilter
+
+    SkMaskFilter is the base class for object that perform transformations on
+    the mask before drawing it. An example subclass is Blur.
+*/
+class SK_API SkMaskFilter : public SkFlattenable {
+public:
+    /** Create a blur maskfilter.
+     *  @param style      The SkBlurStyle to use
+     *  @param sigma      Standard deviation of the Gaussian blur to apply. Must be > 0.
+     *  @param respectCTM if true the blur's sigma is modified by the CTM.
+     *  @return The new blur maskfilter
+     */
+    static sk_sp<SkMaskFilter> MakeBlur(SkBlurStyle style, SkScalar sigma,
+                                        bool respectCTM = true);
+
+    /**
+     *  Construct a maskfilter whose effect is to first apply the inner filter and then apply
+     *  the outer filter to the result of the inner's. Returns nullptr on failure.
+     */
+    static sk_sp<SkMaskFilter> MakeCompose(sk_sp<SkMaskFilter> outer, sk_sp<SkMaskFilter> inner);
+
+    /**
+     *  Compose two maskfilters together using a coverage mode. Returns nullptr on failure.
+     */
+    static sk_sp<SkMaskFilter> MakeCombine(sk_sp<SkMaskFilter> filterA, sk_sp<SkMaskFilter> filterB,
+                                           SkCoverageMode mode);
+
+    /**
+     *  Construct a maskfilter with an additional transform.
+     *
+     *  Note: unlike shader local matrices, this transform composes next to the CTM.
+     *
+     *    TotalMatrix = CTM x MaskFilterMatrix x (optional/downstream) ShaderLocalMatrix
+     */
+    sk_sp<SkMaskFilter> makeWithMatrix(const SkMatrix&) const;
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkMaskFilter_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkMaskFilter_Type;
+    }
+
+    static sk_sp<SkMaskFilter> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkMaskFilter>(static_cast<SkMaskFilter*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkMaskFilter_Type, data, size, procs).release()));
+    }
+
+private:
+    static void RegisterFlattenables();
+    friend class SkFlattenable;
+};
+
+#endif

+ 75 - 0
skia/include/core/SkMath.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMath_DEFINED
+#define SkMath_DEFINED
+
+#include "SkTypes.h"
+
+// 64bit -> 32bit utilities
+
+// Handy util that can be passed two ints, and will automatically promote to
+// 64bits before the multiply, so the caller doesn't have to remember to cast
+// e.g. (int64_t)a * b;
+static inline int64_t sk_64_mul(int64_t a, int64_t b) {
+    return a * b;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/** Given an integer and a positive (max) integer, return the value
+ *  pinned against 0 and max, inclusive.
+ *  @param value    The value we want returned pinned between [0...max]
+ *  @param max      The positive max value
+ *  @return 0 if value < 0, max if value > max, else value
+ */
+static inline int SkClampMax(int value, int max) {
+    // ensure that max is positive
+    SkASSERT(max >= 0);
+    if (value < 0) {
+        value = 0;
+    }
+    if (value > max) {
+        value = max;
+    }
+    return value;
+}
+
+/**
+ *  Returns true if value is a power of 2. Does not explicitly check for
+ *  value <= 0.
+ */
+template <typename T> constexpr inline bool SkIsPow2(T value) {
+    return (value & (value - 1)) == 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  Return a*b/((1 << shift) - 1), rounding any fractional bits.
+ *  Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8
+ */
+static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) {
+    SkASSERT(a <= 32767);
+    SkASSERT(b <= 32767);
+    SkASSERT(shift > 0 && shift <= 8);
+    unsigned prod = a*b + (1 << (shift - 1));
+    return (prod + (prod >> shift)) >> shift;
+}
+
+/**
+ *  Return a*b/255, rounding any fractional bits.
+ *  Only valid if a and b are unsigned and <= 32767.
+ */
+static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) {
+    SkASSERT(a <= 32767);
+    SkASSERT(b <= 32767);
+    unsigned prod = a*b + 128;
+    return (prod + (prod >> 8)) >> 8;
+}
+
+#endif

+ 1863 - 0
skia/include/core/SkMatrix.h

@@ -0,0 +1,1863 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkMatrix.h and docs/SkMatrix_Reference.bmh
+   on 2018-09-13 13:59:55. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkMatrix_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkMatrix_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkMatrix.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkMatrix_DEFINED
+#define SkMatrix_DEFINED
+
+#include "../private/SkMacros.h"
+#include "../private/SkTo.h"
+#include "SkRect.h"
+
+struct SkRSXform;
+struct SkPoint3;
+class SkString;
+
+/** \class SkMatrix
+    SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping
+    SkPoint and vectors with translation, scaling, skewing, rotation, and
+    perspective.
+
+    SkMatrix elements are in row major order. SkMatrix does not have a constructor,
+    so it must be explicitly initialized. setIdentity() initializes SkMatrix
+    so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll()
+    initializes all SkMatrix elements with the corresponding mapping.
+
+    SkMatrix includes a hidden variable that classifies the type of matrix to
+    improve performance. SkMatrix is not thread safe unless getType() is called first.
+*/
+SK_BEGIN_REQUIRE_DENSE
+class SK_API SkMatrix {
+public:
+
+    /** Sets SkMatrix to scale by (sx, sy). Returned matrix is:
+
+            | sx  0  0 |
+            |  0 sy  0 |
+            |  0  0  1 |
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+        @return    SkMatrix with scale
+    */
+    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
+        SkMatrix m;
+        m.setScale(sx, sy);
+        return m;
+    }
+
+    /** Sets SkMatrix to scale by (scale, scale). Returned matrix is:
+
+            | scale   0   0 |
+            |   0   scale 0 |
+            |   0     0   1 |
+
+        @param scale  horizontal and vertical scale factor
+        @return       SkMatrix with scale
+    */
+    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
+        SkMatrix m;
+        m.setScale(scale, scale);
+        return m;
+    }
+
+    /** Sets SkMatrix to translate by (dx, dy). Returned matrix is:
+
+            | 1 0 dx |
+            | 0 1 dy |
+            | 0 0  1 |
+
+        @param dx  horizontal translation
+        @param dy  vertical translation
+        @return    SkMatrix with translation
+    */
+    static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
+        SkMatrix m;
+        m.setTranslate(dx, dy);
+        return m;
+    }
+
+    /** Sets SkMatrix to:
+
+            | scaleX  skewX transX |
+            |  skewY scaleY transY |
+            |  pers0  pers1  pers2 |
+
+        @param scaleX  horizontal scale factor
+        @param skewX   horizontal skew factor
+        @param transX  horizontal translation
+        @param skewY   vertical skew factor
+        @param scaleY  vertical scale factor
+        @param transY  vertical translation
+        @param pers0   input x-axis perspective factor
+        @param pers1   input y-axis perspective factor
+        @param pers2   perspective scale factor
+        @return        SkMatrix constructed from parameters
+    */
+    static SkMatrix SK_WARN_UNUSED_RESULT MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
+                                                  SkScalar skewY,  SkScalar scaleY, SkScalar transY,
+                                                  SkScalar pers0, SkScalar pers1, SkScalar pers2) {
+        SkMatrix m;
+        m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, pers0, pers1, pers2);
+        return m;
+    }
+
+    /** \enum SkMatrix::TypeMask
+        Enum of bit fields for mask returned by getType().
+        Used to identify the complexity of SkMatrix, to optimize performance.
+    */
+    enum TypeMask {
+        kIdentity_Mask    = 0,    //!< identity SkMatrix; all bits clear
+        kTranslate_Mask   = 0x01, //!< translation SkMatrix
+        kScale_Mask       = 0x02, //!< scale SkMatrix
+        kAffine_Mask      = 0x04, //!< skew or rotate SkMatrix
+        kPerspective_Mask = 0x08, //!< perspective SkMatrix
+    };
+
+    /** Returns a bit field describing the transformations the matrix may
+        perform. The bit field is computed conservatively, so it may include
+        false positives. For example, when kPerspective_Mask is set, all
+        other bits are set.
+
+        @return  kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
+                 kAffine_Mask, kPerspective_Mask
+    */
+    TypeMask getType() const {
+        if (fTypeMask & kUnknown_Mask) {
+            fTypeMask = this->computeTypeMask();
+        }
+        // only return the public masks
+        return (TypeMask)(fTypeMask & 0xF);
+    }
+
+    /** Returns true if SkMatrix is identity.  Identity matrix is:
+
+            | 1 0 0 |
+            | 0 1 0 |
+            | 0 0 1 |
+
+        @return  true if SkMatrix has no effect
+    */
+    bool isIdentity() const {
+        return this->getType() == 0;
+    }
+
+    /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity,
+        contain only scale elements, only translate elements, or both. SkMatrix form is:
+
+            | scale-x    0    translate-x |
+            |    0    scale-y translate-y |
+            |    0       0         1      |
+
+        @return  true if SkMatrix is identity; or scales, translates, or both
+    */
+    bool isScaleTranslate() const {
+        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
+    }
+
+    /** Returns true if SkMatrix is identity, or translates. SkMatrix form is:
+
+            | 1 0 translate-x |
+            | 0 1 translate-y |
+            | 0 0      1      |
+
+        @return  true if SkMatrix is identity, or translates
+    */
+    bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); }
+
+    /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
+        or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
+        cases, SkMatrix may also have translation. SkMatrix form is either:
+
+            | scale-x    0    translate-x |
+            |    0    scale-y translate-y |
+            |    0       0         1      |
+
+        or
+
+            |    0     rotate-x translate-x |
+            | rotate-y    0     translate-y |
+            |    0        0          1      |
+
+        for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
+
+        Also called preservesAxisAlignment(); use the one that provides better inline
+        documentation.
+
+        @return  true if SkMatrix maps one SkRect into another
+    */
+    bool rectStaysRect() const {
+        if (fTypeMask & kUnknown_Mask) {
+            fTypeMask = this->computeTypeMask();
+        }
+        return (fTypeMask & kRectStaysRect_Mask) != 0;
+    }
+
+    /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
+        or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
+        cases, SkMatrix may also have translation. SkMatrix form is either:
+
+            | scale-x    0    translate-x |
+            |    0    scale-y translate-y |
+            |    0       0         1      |
+
+        or
+
+            |    0     rotate-x translate-x |
+            | rotate-y    0     translate-y |
+            |    0        0          1      |
+
+        for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
+
+        Also called rectStaysRect(); use the one that provides better inline
+        documentation.
+
+        @return  true if SkMatrix maps one SkRect into another
+    */
+    bool preservesAxisAlignment() const { return this->rectStaysRect(); }
+
+    /** Returns true if the matrix contains perspective elements. SkMatrix form is:
+
+            |       --            --              --          |
+            |       --            --              --          |
+            | perspective-x  perspective-y  perspective-scale |
+
+        where perspective-x or perspective-y is non-zero, or perspective-scale is
+        not one. All other elements may have any value.
+
+        @return  true if SkMatrix is in most general form
+    */
+    bool hasPerspective() const {
+        return SkToBool(this->getPerspectiveTypeMaskOnly() &
+                        kPerspective_Mask);
+    }
+
+    /** Returns true if SkMatrix contains only translation, rotation, reflection, and
+        uniform scale.
+        Returns false if SkMatrix contains different scales, skewing, perspective, or
+        degenerate forms that collapse to a line or point.
+
+        Describes that the SkMatrix makes rendering with and without the matrix are
+        visually alike; a transformed circle remains a circle. Mathematically, this is
+        referred to as similarity of a Euclidean space, or a similarity transformation.
+
+        Preserves right angles, keeping the arms of the angle equal lengths.
+
+        @param tol  to be deprecated
+        @return     true if SkMatrix only rotates, uniformly scales, translates
+    */
+    bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
+
+    /** Returns true if SkMatrix contains only translation, rotation, reflection, and
+        scale. Scale may differ along rotated axes.
+        Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse
+        to a line or point.
+
+        Preserves right angles, but not requiring that the arms of the angle
+        retain equal lengths.
+
+        @param tol  to be deprecated
+        @return     true if SkMatrix only rotates, scales, translates
+    */
+    bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
+
+    /** SkMatrix organizes its values in row order. These members correspond to
+        each value in SkMatrix.
+    */
+    static constexpr int kMScaleX = 0; //!< horizontal scale factor
+    static constexpr int kMSkewX  = 1; //!< horizontal skew factor
+    static constexpr int kMTransX = 2; //!< horizontal translation
+    static constexpr int kMSkewY  = 3; //!< vertical skew factor
+    static constexpr int kMScaleY = 4; //!< vertical scale factor
+    static constexpr int kMTransY = 5; //!< vertical translation
+    static constexpr int kMPersp0 = 6; //!< input x perspective factor
+    static constexpr int kMPersp1 = 7; //!< input y perspective factor
+    static constexpr int kMPersp2 = 8; //!< perspective bias
+
+    /** Affine arrays are in column major order to match the matrix used by
+        PDF and XPS.
+    */
+    static constexpr int kAScaleX = 0; //!< horizontal scale factor
+    static constexpr int kASkewY  = 1; //!< vertical skew factor
+    static constexpr int kASkewX  = 2; //!< horizontal skew factor
+    static constexpr int kAScaleY = 3; //!< vertical scale factor
+    static constexpr int kATransX = 4; //!< horizontal translation
+    static constexpr int kATransY = 5; //!< vertical translation
+
+    /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
+        defined.
+
+        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+                      kMPersp0, kMPersp1, kMPersp2
+        @return       value corresponding to index
+    */
+    SkScalar operator[](int index) const {
+        SkASSERT((unsigned)index < 9);
+        return fMat[index];
+    }
+
+    /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
+        defined.
+
+        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+                      kMPersp0, kMPersp1, kMPersp2
+        @return       value corresponding to index
+    */
+    SkScalar get(int index) const {
+        SkASSERT((unsigned)index < 9);
+        return fMat[index];
+    }
+
+    /** Returns scale factor multiplied by x-axis input, contributing to x-axis output.
+        With mapPoints(), scales SkPoint along the x-axis.
+
+        @return  horizontal scale factor
+    */
+    SkScalar getScaleX() const { return fMat[kMScaleX]; }
+
+    /** Returns scale factor multiplied by y-axis input, contributing to y-axis output.
+        With mapPoints(), scales SkPoint along the y-axis.
+
+        @return  vertical scale factor
+    */
+    SkScalar getScaleY() const { return fMat[kMScaleY]; }
+
+    /** Returns scale factor multiplied by x-axis input, contributing to y-axis output.
+        With mapPoints(), skews SkPoint along the y-axis.
+        Skewing both axes can rotate SkPoint.
+
+        @return  vertical skew factor
+    */
+    SkScalar getSkewY() const { return fMat[kMSkewY]; }
+
+    /** Returns scale factor multiplied by y-axis input, contributing to x-axis output.
+        With mapPoints(), skews SkPoint along the x-axis.
+        Skewing both axes can rotate SkPoint.
+
+        @return  horizontal scale factor
+    */
+    SkScalar getSkewX() const { return fMat[kMSkewX]; }
+
+    /** Returns translation contributing to x-axis output.
+        With mapPoints(), moves SkPoint along the x-axis.
+
+        @return  horizontal translation factor
+    */
+    SkScalar getTranslateX() const { return fMat[kMTransX]; }
+
+    /** Returns translation contributing to y-axis output.
+        With mapPoints(), moves SkPoint along the y-axis.
+
+        @return  vertical translation factor
+    */
+    SkScalar getTranslateY() const { return fMat[kMTransY]; }
+
+    /** Returns factor scaling input x-axis relative to input y-axis.
+
+        @return  input x-axis perspective factor
+    */
+    SkScalar getPerspX() const { return fMat[kMPersp0]; }
+
+    /** Returns factor scaling input y-axis relative to input x-axis.
+
+        @return  input y-axis perspective factor
+    */
+    SkScalar getPerspY() const { return fMat[kMPersp1]; }
+
+    /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is
+        defined. Clears internal cache anticipating that caller will change SkMatrix value.
+
+        Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix
+        value must be followed by dirtyMatrixTypeCache().
+
+        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+                      kMPersp0, kMPersp1, kMPersp2
+        @return       writable value corresponding to index
+    */
+    SkScalar& operator[](int index) {
+        SkASSERT((unsigned)index < 9);
+        this->setTypeMask(kUnknown_Mask);
+        return fMat[index];
+    }
+
+    /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is
+        defined. Safer than operator[]; internal cache is always maintained.
+
+        @param index  one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+                      kMPersp0, kMPersp1, kMPersp2
+        @param value  scalar to store in SkMatrix
+    */
+    void set(int index, SkScalar value) {
+        SkASSERT((unsigned)index < 9);
+        fMat[index] = value;
+        this->setTypeMask(kUnknown_Mask);
+    }
+
+    /** Sets horizontal scale factor.
+
+        @param v  horizontal scale factor to store
+    */
+    void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
+
+    /** Sets vertical scale factor.
+
+        @param v  vertical scale factor to store
+    */
+    void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
+
+    /** Sets vertical skew factor.
+
+        @param v  vertical skew factor to store
+    */
+    void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
+
+    /** Sets horizontal skew factor.
+
+        @param v  horizontal skew factor to store
+    */
+    void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
+
+    /** Sets horizontal translation.
+
+        @param v  horizontal translation to store
+    */
+    void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
+
+    /** Sets vertical translation.
+
+        @param v  vertical translation to store
+    */
+    void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
+
+    /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values
+        inversely proportional to input y-axis values.
+
+        @param v  perspective factor
+    */
+    void setPerspX(SkScalar v) { this->set(kMPersp0, v); }
+
+    /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values
+        inversely proportional to input x-axis values.
+
+        @param v  perspective factor
+    */
+    void setPerspY(SkScalar v) { this->set(kMPersp1, v); }
+
+    /** Sets all values from parameters. Sets matrix to:
+
+            | scaleX  skewX transX |
+            |  skewY scaleY transY |
+            | persp0 persp1 persp2 |
+
+        @param scaleX  horizontal scale factor to store
+        @param skewX   horizontal skew factor to store
+        @param transX  horizontal translation to store
+        @param skewY   vertical skew factor to store
+        @param scaleY  vertical scale factor to store
+        @param transY  vertical translation to store
+        @param persp0  input x-axis values perspective factor to store
+        @param persp1  input y-axis values perspective factor to store
+        @param persp2  perspective scale factor to store
+    */
+    void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
+                SkScalar skewY,  SkScalar scaleY, SkScalar transY,
+                SkScalar persp0, SkScalar persp1, SkScalar persp2) {
+        fMat[kMScaleX] = scaleX;
+        fMat[kMSkewX]  = skewX;
+        fMat[kMTransX] = transX;
+        fMat[kMSkewY]  = skewY;
+        fMat[kMScaleY] = scaleY;
+        fMat[kMTransY] = transY;
+        fMat[kMPersp0] = persp0;
+        fMat[kMPersp1] = persp1;
+        fMat[kMPersp2] = persp2;
+        this->setTypeMask(kUnknown_Mask);
+    }
+
+    /** Copies nine scalar values contained by SkMatrix into buffer, in member value
+        ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+        kMPersp0, kMPersp1, kMPersp2.
+
+        @param buffer  storage for nine scalar values
+    */
+    void get9(SkScalar buffer[9]) const {
+        memcpy(buffer, fMat, 9 * sizeof(SkScalar));
+    }
+
+    /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order:
+        kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
+        kMPersp2.
+
+        Sets matrix to:
+
+            | buffer[0] buffer[1] buffer[2] |
+            | buffer[3] buffer[4] buffer[5] |
+            | buffer[6] buffer[7] buffer[8] |
+
+        In the future, set9 followed by get9 may not return the same values. Since SkMatrix
+        maps non-homogeneous coordinates, scaling all nine values produces an equivalent
+        transformation, possibly improving precision.
+
+        @param buffer  nine scalar values
+    */
+    void set9(const SkScalar buffer[9]);
+
+    /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
+
+            | 1 0 0 |
+            | 0 1 0 |
+            | 0 0 1 |
+
+        Also called setIdentity(); use the one that provides better inline
+        documentation.
+    */
+    void reset();
+
+    /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
+
+            | 1 0 0 |
+            | 0 1 0 |
+            | 0 0 1 |
+
+        Also called reset(); use the one that provides better inline
+        documentation.
+    */
+    void setIdentity() { this->reset(); }
+
+    /** Sets SkMatrix to translate by (dx, dy).
+
+        @param dx  horizontal translation
+        @param dy  vertical translation
+    */
+    void setTranslate(SkScalar dx, SkScalar dy);
+
+    /** Sets SkMatrix to translate by (v.fX, v.fY).
+
+        @param v  vector containing horizontal and vertical translation
+    */
+    void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
+
+    /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py).
+        The pivot point is unchanged when mapped with SkMatrix.
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0).
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+    */
+    void setScale(SkScalar sx, SkScalar sy);
+
+    /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py).
+        The pivot point is unchanged when mapped with SkMatrix.
+
+        Positive degrees rotates clockwise.
+
+        @param degrees  angle of axes relative to upright axes
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
+    */
+    void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0).
+        Positive degrees rotates clockwise.
+
+        @param degrees  angle of axes relative to upright axes
+    */
+    void setRotate(SkScalar degrees);
+
+    /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
+        The pivot point is unchanged when mapped with SkMatrix.
+
+        Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+        Vector length specifies scale.
+
+        @param sinValue  rotation vector x-axis component
+        @param cosValue  rotation vector y-axis component
+        @param px        pivot on x-axis
+        @param py        pivot on y-axis
+    */
+    void setSinCos(SkScalar sinValue, SkScalar cosValue,
+                   SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
+
+        Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+        Vector length specifies scale.
+
+        @param sinValue  rotation vector x-axis component
+        @param cosValue  rotation vector y-axis component
+    */
+    void setSinCos(SkScalar sinValue, SkScalar cosValue);
+
+    /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form.
+
+        Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative
+        to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled
+        by vector, then translated by (rsxForm.fTx, rsxForm.fTy).
+
+        @param rsxForm  compressed SkRSXform matrix
+        @return         reference to SkMatrix
+    */
+    SkMatrix& setRSXform(const SkRSXform& rsxForm);
+
+    /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py).
+        The pivot point is unchanged when mapped with SkMatrix.
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0).
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+    */
+    void setSkew(SkScalar kx, SkScalar ky);
+
+    /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this.
+
+        Given:
+
+                | A B C |      | J K L |
+            a = | D E F |, b = | M N O |
+                | G H I |      | P Q R |
+
+        sets SkMatrix to:
+
+                    | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+            a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+                    | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+        @param a  SkMatrix on left side of multiply expression
+        @param b  SkMatrix on right side of multiply expression
+    */
+    void setConcat(const SkMatrix& a, const SkMatrix& b);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy).
+        This can be thought of as moving the point to be mapped before applying SkMatrix.
+
+        Given:
+
+                     | A B C |               | 1 0 dx |
+            Matrix = | D E F |,  T(dx, dy) = | 0 1 dy |
+                     | G H I |               | 0 0  1 |
+
+        sets SkMatrix to:
+
+                                 | A B C | | 1 0 dx |   | A B A*dx+B*dy+C |
+            Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |
+                                 | G H I | | 0 0  1 |   | G H G*dx+H*dy+I |
+
+        @param dx  x-axis translation before applying SkMatrix
+        @param dy  y-axis translation before applying SkMatrix
+    */
+    void preTranslate(SkScalar dx, SkScalar dy);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
+        about pivot point (px, py).
+        This can be thought of as scaling about a pivot point before applying SkMatrix.
+
+        Given:
+
+                     | A B C |                       | sx  0 dx |
+            Matrix = | D E F |,  S(sx, sy, px, py) = |  0 sy dy |
+                     | G H I |                       |  0  0  1 |
+
+        where
+
+            dx = px - sx * px
+            dy = py - sy * py
+
+        sets SkMatrix to:
+
+                                         | A B C | | sx  0 dx |   | A*sx B*sy A*dx+B*dy+C |
+            Matrix * S(sx, sy, px, py) = | D E F | |  0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
+                                         | G H I | |  0  0  1 |   | G*sx H*sy G*dx+H*dy+I |
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
+        about pivot point (0, 0).
+        This can be thought of as scaling about the origin before applying SkMatrix.
+
+        Given:
+
+                     | A B C |               | sx  0  0 |
+            Matrix = | D E F |,  S(sx, sy) = |  0 sy  0 |
+                     | G H I |               |  0  0  1 |
+
+        sets SkMatrix to:
+
+                                 | A B C | | sx  0  0 |   | A*sx B*sy C |
+            Matrix * S(sx, sy) = | D E F | |  0 sy  0 | = | D*sx E*sy F |
+                                 | G H I | |  0  0  1 |   | G*sx H*sy I |
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+    */
+    void preScale(SkScalar sx, SkScalar sy);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
+        about pivot point (px, py).
+        This can be thought of as rotating about a pivot point before applying SkMatrix.
+
+        Positive degrees rotates clockwise.
+
+        Given:
+
+                     | A B C |                        | c -s dx |
+            Matrix = | D E F |,  R(degrees, px, py) = | s  c dy |
+                     | G H I |                        | 0  0  1 |
+
+        where
+
+            c  = cos(degrees)
+            s  = sin(degrees)
+            dx =  s * py + (1 - c) * px
+            dy = -s * px + (1 - c) * py
+
+        sets SkMatrix to:
+
+                                          | A B C | | c -s dx |   | Ac+Bs -As+Bc A*dx+B*dy+C |
+            Matrix * R(degrees, px, py) = | D E F | | s  c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
+                                          | G H I | | 0  0  1 |   | Gc+Hs -Gs+Hc G*dx+H*dy+I |
+
+        @param degrees  angle of axes relative to upright axes
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
+    */
+    void preRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
+        about pivot point (0, 0).
+        This can be thought of as rotating about the origin before applying SkMatrix.
+
+        Positive degrees rotates clockwise.
+
+        Given:
+
+                     | A B C |                        | c -s 0 |
+            Matrix = | D E F |,  R(degrees, px, py) = | s  c 0 |
+                     | G H I |                        | 0  0 1 |
+
+        where
+
+            c  = cos(degrees)
+            s  = sin(degrees)
+
+        sets SkMatrix to:
+
+                                          | A B C | | c -s 0 |   | Ac+Bs -As+Bc C |
+            Matrix * R(degrees, px, py) = | D E F | | s  c 0 | = | Dc+Es -Ds+Ec F |
+                                          | G H I | | 0  0 1 |   | Gc+Hs -Gs+Hc I |
+
+        @param degrees  angle of axes relative to upright axes
+    */
+    void preRotate(SkScalar degrees);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
+        about pivot point (px, py).
+        This can be thought of as skewing about a pivot point before applying SkMatrix.
+
+        Given:
+
+                     | A B C |                       |  1 kx dx |
+            Matrix = | D E F |,  K(kx, ky, px, py) = | ky  1 dy |
+                     | G H I |                       |  0  0  1 |
+
+        where
+
+            dx = -kx * py
+            dy = -ky * px
+
+        sets SkMatrix to:
+
+                                         | A B C | |  1 kx dx |   | A+B*ky A*kx+B A*dx+B*dy+C |
+            Matrix * K(kx, ky, px, py) = | D E F | | ky  1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
+                                         | G H I | |  0  0  1 |   | G+H*ky G*kx+H G*dx+H*dy+I |
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
+        about pivot point (0, 0).
+        This can be thought of as skewing about the origin before applying SkMatrix.
+
+        Given:
+
+                     | A B C |               |  1 kx 0 |
+            Matrix = | D E F |,  K(kx, ky) = | ky  1 0 |
+                     | G H I |               |  0  0 1 |
+
+        sets SkMatrix to:
+
+                                 | A B C | |  1 kx 0 |   | A+B*ky A*kx+B C |
+            Matrix * K(kx, ky) = | D E F | | ky  1 0 | = | D+E*ky D*kx+E F |
+                                 | G H I | |  0  0 1 |   | G+H*ky G*kx+H I |
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+    */
+    void preSkew(SkScalar kx, SkScalar ky);
+
+    /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other.
+        This can be thought of mapping by other before applying SkMatrix.
+
+        Given:
+
+                     | A B C |          | J K L |
+            Matrix = | D E F |, other = | M N O |
+                     | G H I |          | P Q R |
+
+        sets SkMatrix to:
+
+                             | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+            Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+                             | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+        @param other  SkMatrix on right side of multiply expression
+    */
+    void preConcat(const SkMatrix& other);
+
+    /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix.
+        This can be thought of as moving the point to be mapped after applying SkMatrix.
+
+        Given:
+
+                     | J K L |               | 1 0 dx |
+            Matrix = | M N O |,  T(dx, dy) = | 0 1 dy |
+                     | P Q R |               | 0 0  1 |
+
+        sets SkMatrix to:
+
+                                 | 1 0 dx | | J K L |   | J+dx*P K+dx*Q L+dx*R |
+            T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |
+                                 | 0 0  1 | | P Q R |   |      P      Q      R |
+
+        @param dx  x-axis translation after applying SkMatrix
+        @param dy  y-axis translation after applying SkMatrix
+    */
+    void postTranslate(SkScalar dx, SkScalar dy);
+
+    /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
+        (px, py), multiplied by SkMatrix.
+        This can be thought of as scaling about a pivot point after applying SkMatrix.
+
+        Given:
+
+                     | J K L |                       | sx  0 dx |
+            Matrix = | M N O |,  S(sx, sy, px, py) = |  0 sy dy |
+                     | P Q R |                       |  0  0  1 |
+
+        where
+
+            dx = px - sx * px
+            dy = py - sy * py
+
+        sets SkMatrix to:
+
+                                         | sx  0 dx | | J K L |   | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
+            S(sx, sy, px, py) * Matrix = |  0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
+                                         |  0  0  1 | | P Q R |   |         P         Q         R |
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
+        (0, 0), multiplied by SkMatrix.
+        This can be thought of as scaling about the origin after applying SkMatrix.
+
+        Given:
+
+                     | J K L |               | sx  0  0 |
+            Matrix = | M N O |,  S(sx, sy) = |  0 sy  0 |
+                     | P Q R |               |  0  0  1 |
+
+        sets SkMatrix to:
+
+                                 | sx  0  0 | | J K L |   | sx*J sx*K sx*L |
+            S(sx, sy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |
+                                 |  0  0  1 | | P Q R |   |    P    Q    R |
+
+        @param sx  horizontal scale factor
+        @param sy  vertical scale factor
+    */
+    void postScale(SkScalar sx, SkScalar sy);
+
+    /** Sets SkMatrix to SkMatrix constructed from scaling by (1/divx, 1/divy),
+        about pivot point (px, py), multiplied by SkMatrix.
+
+        Returns false if either divx or divy is zero.
+
+        Given:
+
+                     | J K L |                   | sx  0  0 |
+            Matrix = | M N O |,  I(divx, divy) = |  0 sy  0 |
+                     | P Q R |                   |  0  0  1 |
+
+        where
+
+            sx = 1 / divx
+            sy = 1 / divy
+
+        sets SkMatrix to:
+
+                                     | sx  0  0 | | J K L |   | sx*J sx*K sx*L |
+            I(divx, divy) * Matrix = |  0 sy  0 | | M N O | = | sy*M sy*N sy*O |
+                                     |  0  0  1 | | P Q R |   |    P    Q    R |
+
+        @param divx  integer divisor for inverse scale in x
+        @param divy  integer divisor for inverse scale in y
+        @return      true on successful scale
+    */
+    bool postIDiv(int divx, int divy);
+
+    /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
+        (px, py), multiplied by SkMatrix.
+        This can be thought of as rotating about a pivot point after applying SkMatrix.
+
+        Positive degrees rotates clockwise.
+
+        Given:
+
+                     | J K L |                        | c -s dx |
+            Matrix = | M N O |,  R(degrees, px, py) = | s  c dy |
+                     | P Q R |                        | 0  0  1 |
+
+        where
+
+            c  = cos(degrees)
+            s  = sin(degrees)
+            dx =  s * py + (1 - c) * px
+            dy = -s * px + (1 - c) * py
+
+        sets SkMatrix to:
+
+                                          |c -s dx| |J K L|   |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
+            R(degrees, px, py) * Matrix = |s  c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
+                                          |0  0  1| |P Q R|   |         P          Q          R|
+
+        @param degrees  angle of axes relative to upright axes
+        @param px       pivot on x-axis
+        @param py       pivot on y-axis
+    */
+    void postRotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
+        (0, 0), multiplied by SkMatrix.
+        This can be thought of as rotating about the origin after applying SkMatrix.
+
+        Positive degrees rotates clockwise.
+
+        Given:
+
+                     | J K L |                        | c -s 0 |
+            Matrix = | M N O |,  R(degrees, px, py) = | s  c 0 |
+                     | P Q R |                        | 0  0 1 |
+
+        where
+
+            c  = cos(degrees)
+            s  = sin(degrees)
+
+        sets SkMatrix to:
+
+                                          | c -s dx | | J K L |   | cJ-sM cK-sN cL-sO |
+            R(degrees, px, py) * Matrix = | s  c dy | | M N O | = | sJ+cM sK+cN sL+cO |
+                                          | 0  0  1 | | P Q R |   |     P     Q     R |
+
+        @param degrees  angle of axes relative to upright axes
+    */
+    void postRotate(SkScalar degrees);
+
+    /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
+        (px, py), multiplied by SkMatrix.
+        This can be thought of as skewing about a pivot point after applying SkMatrix.
+
+        Given:
+
+                     | J K L |                       |  1 kx dx |
+            Matrix = | M N O |,  K(kx, ky, px, py) = | ky  1 dy |
+                     | P Q R |                       |  0  0  1 |
+
+        where
+
+            dx = -kx * py
+            dy = -ky * px
+
+        sets SkMatrix to:
+
+                                         | 1 kx dx| |J K L|   |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
+            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|
+                                         | 0  0  1| |P Q R|   |          P           Q           R|
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+        @param px  pivot on x-axis
+        @param py  pivot on y-axis
+    */
+    void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
+
+    /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
+        (0, 0), multiplied by SkMatrix.
+        This can be thought of as skewing about the origin after applying SkMatrix.
+
+        Given:
+
+                     | J K L |               |  1 kx 0 |
+            Matrix = | M N O |,  K(kx, ky) = | ky  1 0 |
+                     | P Q R |               |  0  0 1 |
+
+        sets SkMatrix to:
+
+                                 |  1 kx 0 | | J K L |   | J+kx*M K+kx*N L+kx*O |
+            K(kx, ky) * Matrix = | ky  1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |
+                                 |  0  0 1 | | P Q R |   |      P      Q      R |
+
+        @param kx  horizontal skew factor
+        @param ky  vertical skew factor
+    */
+    void postSkew(SkScalar kx, SkScalar ky);
+
+    /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix.
+        This can be thought of mapping by other after applying SkMatrix.
+
+        Given:
+
+                     | J K L |           | A B C |
+            Matrix = | M N O |,  other = | D E F |
+                     | P Q R |           | G H I |
+
+        sets SkMatrix to:
+
+                             | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+            other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+                             | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+        @param other  SkMatrix on left side of multiply expression
+    */
+    void postConcat(const SkMatrix& other);
+
+    /** \enum SkMatrix::ScaleToFit
+        ScaleToFit describes how SkMatrix is constructed to map one SkRect to another.
+        ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling,
+        or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies
+        how SkMatrix maps to the side or center of the destination SkRect.
+    */
+    enum ScaleToFit {
+        kFill_ScaleToFit,   //!< scales in x and y to fill destination SkRect
+        kStart_ScaleToFit,  //!< scales and aligns to left and top
+        kCenter_ScaleToFit, //!< scales and aligns to center
+        kEnd_ScaleToFit,    //!< scales and aligns to right and bottom
+    };
+
+    /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether
+        mapping completely fills dst or preserves the aspect ratio, and how to align
+        src within dst. Returns false if src is empty, and sets SkMatrix to identity.
+        Returns true if dst is empty, and sets SkMatrix to:
+
+            | 0 0 0 |
+            | 0 0 0 |
+            | 0 0 1 |
+
+        @param src  SkRect to map from
+        @param dst  SkRect to map to
+        @param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,
+                    kCenter_ScaleToFit, kEnd_ScaleToFit
+        @return     true if SkMatrix can represent SkRect mapping
+    */
+    bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
+
+    /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects
+        whether mapping completely fills dst or preserves the aspect ratio, and how to
+        align src within dst. Returns the identity SkMatrix if src is empty. If dst is
+        empty, returns SkMatrix set to:
+
+            | 0 0 0 |
+            | 0 0 0 |
+            | 0 0 1 |
+
+        @param src  SkRect to map from
+        @param dst  SkRect to map to
+        @param stf  one of: kFill_ScaleToFit, kStart_ScaleToFit,
+                    kCenter_ScaleToFit, kEnd_ScaleToFit
+        @return     SkMatrix mapping src to dst
+    */
+    static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
+        SkMatrix m;
+        m.setRectToRect(src, dst, stf);
+        return m;
+    }
+
+    /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less.
+
+        If count is zero, sets SkMatrix to identity and returns true.
+        If count is one, sets SkMatrix to translate and returns true.
+        If count is two or more, sets SkMatrix to map SkPoint if possible; returns false
+        if SkMatrix cannot be constructed. If count is four, SkMatrix may include
+        perspective.
+
+        @param src    SkPoint to map from
+        @param dst    SkPoint to map to
+        @param count  number of SkPoint in src and dst
+        @return       true if SkMatrix was constructed successfully
+    */
+    bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
+
+    /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted.
+        Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix
+        maps from destination to source. If SkMatrix can not be inverted, inverse is
+        unchanged.
+
+        @param inverse  storage for inverted SkMatrix; may be nullptr
+        @return         true if SkMatrix can be inverted
+    */
+    bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
+        // Allow the trivial case to be inlined.
+        if (this->isIdentity()) {
+            if (inverse) {
+                inverse->reset();
+            }
+            return true;
+        }
+        return this->invertNonIdentity(inverse);
+    }
+
+    /** Fills affine with identity values in column major order.
+        Sets affine to:
+
+            | 1 0 0 |
+            | 0 1 0 |
+
+        Affine 3 by 2 matrices in column major order are used by OpenGL and XPS.
+
+        @param affine  storage for 3 by 2 affine matrix
+    */
+    static void SetAffineIdentity(SkScalar affine[6]);
+
+    /** Fills affine in column major order. Sets affine to:
+
+            | scale-x  skew-x translate-x |
+            | skew-y  scale-y translate-y |
+
+        If SkMatrix contains perspective, returns false and leaves affine unchanged.
+
+        @param affine  storage for 3 by 2 affine matrix; may be nullptr
+        @return        true if SkMatrix does not contain perspective
+    */
+    bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;
+
+    /** Sets SkMatrix to affine values, passed in column major order. Given affine,
+        column, then row, as:
+
+            | scale-x  skew-x translate-x |
+            |  skew-y scale-y translate-y |
+
+        SkMatrix is set, row, then column, to:
+
+            | scale-x  skew-x translate-x |
+            |  skew-y scale-y translate-y |
+            |       0       0           1 |
+
+        @param affine  3 by 2 affine matrix
+    */
+    void setAffine(const SkScalar affine[6]);
+
+    /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater
+        length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given:
+
+                     | A B C |        | x |
+            Matrix = | D E F |,  pt = | y |
+                     | G H I |        | 1 |
+
+        where
+
+            for (i = 0; i < count; ++i) {
+                x = src[i].fX
+                y = src[i].fY
+            }
+
+        each dst SkPoint is computed as:
+
+                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
+            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
+
+        src and dst may point to the same storage.
+
+        @param dst    storage for mapped SkPoint
+        @param src    SkPoint to transform
+        @param count  number of SkPoint to transform
+    */
+    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
+        SkASSERT((dst && src && count > 0) || 0 == count);
+        // no partial overlap
+        SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
+        this->getMapPtsProc()(*this, dst, src, count);
+    }
+
+    /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying
+        each SkPoint by SkMatrix. Given:
+
+                     | A B C |        | x |
+            Matrix = | D E F |,  pt = | y |
+                     | G H I |        | 1 |
+
+        where
+
+            for (i = 0; i < count; ++i) {
+                x = pts[i].fX
+                y = pts[i].fY
+            }
+
+        each resulting pts SkPoint is computed as:
+
+                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
+            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
+
+        @param pts    storage for mapped SkPoint
+        @param count  number of SkPoint to transform
+    */
+    void mapPoints(SkPoint pts[], int count) const {
+        this->mapPoints(pts, pts, count);
+    }
+
+    /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or
+        greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given:
+
+                     | A B C |         | x |
+            Matrix = | D E F |,  src = | y |
+                     | G H I |         | z |
+
+        each resulting dst SkPoint is computed as:
+
+                           |A B C| |x|
+            Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
+                           |G H I| |z|
+
+        @param dst    storage for mapped SkPoint3 array
+        @param src    SkPoint3 array to transform
+        @param count  items in SkPoint3 array to transform
+    */
+    void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
+
+    /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:
+
+                     | A B C |        | x |
+            Matrix = | D E F |,  pt = | y |
+                     | G H I |        | 1 |
+
+        result is computed as:
+
+                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
+            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
+
+        @param x       x-axis value of SkPoint to map
+        @param y       y-axis value of SkPoint to map
+        @param result  storage for mapped SkPoint
+    */
+    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
+        SkASSERT(result);
+        this->getMapXYProc()(*this, x, y, result);
+    }
+
+    /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:
+
+                     | A B C |        | x |
+            Matrix = | D E F |,  pt = | y |
+                     | G H I |        | 1 |
+
+        result is computed as:
+
+                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
+            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
+
+        @param x  x-axis value of SkPoint to map
+        @param y  y-axis value of SkPoint to map
+        @return   mapped SkPoint
+    */
+    SkPoint mapXY(SkScalar x, SkScalar y) const {
+        SkPoint result;
+        this->getMapXYProc()(*this, x, y, &result);
+        return result;
+    }
+
+    /** Maps src vector array of length count to vector SkPoint array of equal or greater
+        length. Vectors are mapped by multiplying each vector by SkMatrix, treating
+        SkMatrix translation as zero. Given:
+
+                     | A B 0 |         | x |
+            Matrix = | D E 0 |,  src = | y |
+                     | G H I |         | 1 |
+
+        where
+
+            for (i = 0; i < count; ++i) {
+                x = src[i].fX
+                y = src[i].fY
+            }
+
+        each dst vector is computed as:
+
+                           |A B 0| |x|                            Ax+By     Dx+Ey
+            Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
+                           |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
+
+        src and dst may point to the same storage.
+
+        @param dst    storage for mapped vectors
+        @param src    vectors to transform
+        @param count  number of vectors to transform
+    */
+    void mapVectors(SkVector dst[], const SkVector src[], int count) const;
+
+    /** Maps vecs vector array of length count in place, multiplying each vector by
+        SkMatrix, treating SkMatrix translation as zero. Given:
+
+                     | A B 0 |         | x |
+            Matrix = | D E 0 |,  vec = | y |
+                     | G H I |         | 1 |
+
+        where
+
+            for (i = 0; i < count; ++i) {
+                x = vecs[i].fX
+                y = vecs[i].fY
+            }
+
+        each result vector is computed as:
+
+                           |A B 0| |x|                            Ax+By     Dx+Ey
+            Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
+                           |G H I| |1|                           Gx+Hy+I   Gx+Hy+I
+
+        @param vecs   vectors to transform, and storage for mapped vectors
+        @param count  number of vectors to transform
+    */
+    void mapVectors(SkVector vecs[], int count) const {
+        this->mapVectors(vecs, vecs, count);
+    }
+
+    /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix,
+        treating SkMatrix translation as zero. Given:
+
+                     | A B 0 |         | dx |
+            Matrix = | D E 0 |,  vec = | dy |
+                     | G H I |         |  1 |
+
+        each result vector is computed as:
+
+                       |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
+        Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
+                       |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
+
+        @param dx      x-axis value of vector to map
+        @param dy      y-axis value of vector to map
+        @param result  storage for mapped vector
+    */
+    void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
+        SkVector vec = { dx, dy };
+        this->mapVectors(result, &vec, 1);
+    }
+
+    /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero.
+        Given:
+
+                     | A B 0 |         | dx |
+            Matrix = | D E 0 |,  vec = | dy |
+                     | G H I |         |  1 |
+
+        each result vector is computed as:
+
+                       |A B 0| |dx|                                        A*dx+B*dy     D*dx+E*dy
+        Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
+                       |G H I| | 1|                                       G*dx+H*dy+I   G*dx+*dHy+I
+
+        @param dx  x-axis value of vector to map
+        @param dy  y-axis value of vector to map
+        @return    mapped vector
+    */
+    SkVector mapVector(SkScalar dx, SkScalar dy) const {
+        SkVector vec = { dx, dy };
+        this->mapVectors(&vec, &vec, 1);
+        return vec;
+    }
+
+    /** Sets dst to bounds of src corners mapped by SkMatrix.
+        Returns true if mapped corners are dst corners.
+
+        Returned value is the same as calling rectStaysRect().
+
+        @param dst  storage for bounds of mapped SkPoint
+        @param src  SkRect to map
+        @return     true if dst is equivalent to mapped src
+    */
+    bool mapRect(SkRect* dst, const SkRect& src) const;
+
+    /** Sets rect to bounds of rect corners mapped by SkMatrix.
+        Returns true if mapped corners are computed rect corners.
+
+        Returned value is the same as calling rectStaysRect().
+
+        @param rect  rectangle to map, and storage for bounds of mapped corners
+        @return      true if result is equivalent to mapped rect
+    */
+    bool mapRect(SkRect* rect) const {
+        return this->mapRect(rect, *rect);
+    }
+
+    /** Returns bounds of src corners mapped by SkMatrix.
+
+        @param src  rectangle to map
+        @return     mapped bounds
+    */
+    SkRect mapRect(const SkRect& src) const {
+        SkRect dst;
+        (void)this->mapRect(&dst, src);
+        return dst;
+    }
+
+    /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each
+        rect corner by SkMatrix. rect corner is processed in this order:
+        (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
+        (rect.fLeft, rect.fBottom).
+
+        rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;
+        rect.fTop may be greater than or equal to rect.fBottom.
+
+        Given:
+
+                     | A B C |        | x |
+            Matrix = | D E F |,  pt = | y |
+                     | G H I |        | 1 |
+
+        where pt is initialized from each of (rect.fLeft, rect.fTop),
+        (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),
+        each dst SkPoint is computed as:
+
+                          |A B C| |x|                               Ax+By+C   Dx+Ey+F
+            Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
+                          |G H I| |1|                               Gx+Hy+I   Gx+Hy+I
+
+        @param dst   storage for mapped corner SkPoint
+        @param rect  SkRect to map
+    */
+    void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
+        // This could potentially be faster if we only transformed each x and y of the rect once.
+        rect.toQuad(dst);
+        this->mapPoints(dst, 4);
+    }
+
+    /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains
+        elements other than scale or translate: asserts if SK_DEBUG is defined;
+        otherwise, results are undefined.
+
+        @param dst  storage for bounds of mapped SkPoint
+        @param src  SkRect to map
+    */
+    void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
+
+    /** Returns geometric mean radius of ellipse formed by constructing circle of
+        size radius, and mapping constructed circle with SkMatrix. The result squared is
+        equal to the major axis length times the minor axis length.
+        Result is not meaningful if SkMatrix contains perspective elements.
+
+        @param radius  circle size to map
+        @return        average mapped radius
+    */
+    SkScalar mapRadius(SkScalar radius) const;
+
+    /** Returns true if a unit step on x-axis at some y-axis value mapped through SkMatrix
+        can be represented by a constant vector. Returns true if getType() returns
+        kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask.
+
+        May return true if getType() returns kPerspective_Mask, but only when SkMatrix
+        does not include rotation or skewing along the y-axis.
+
+        @return  true if SkMatrix does not have complex perspective
+    */
+    bool isFixedStepInX() const;
+
+    /** Returns vector representing a unit step on x-axis at y mapped through SkMatrix.
+        If isFixedStepInX() is false, returned value is undefined.
+
+        @param y  position of line parallel to x-axis
+        @return   vector advance of mapped unit step on x-axis
+    */
+    SkVector fixedStepInX(SkScalar y) const;
+
+    /** Returns true if SkMatrix equals m, using an efficient comparison.
+
+        Returns false when the sign of zero values is the different; when one
+        matrix has positive zero value and the other has negative zero value.
+
+        Returns true even when both SkMatrix contain NaN.
+
+        NaN never equals any value, including itself. To improve performance, NaN values
+        are treated as bit patterns that are equal if their bit patterns are equal.
+
+        @param m  SkMatrix to compare
+        @return   true if m and SkMatrix are represented by identical bit patterns
+    */
+    bool cheapEqualTo(const SkMatrix& m) const {
+        return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
+    }
+
+    /** Compares a and b; returns true if a and b are numerically equal. Returns true
+        even if sign of zero values are different. Returns false if either SkMatrix
+        contains NaN, even if the other SkMatrix also contains NaN.
+
+        @param a  SkMatrix to compare
+        @param b  SkMatrix to compare
+        @return   true if SkMatrix a and SkMatrix b are numerically equal
+    */
+    friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
+
+    /** Compares a and b; returns true if a and b are not numerically equal. Returns false
+        even if sign of zero values are different. Returns true if either SkMatrix
+        contains NaN, even if the other SkMatrix also contains NaN.
+
+        @param a  SkMatrix to compare
+        @param b  SkMatrix to compare
+        @return   true if SkMatrix a and SkMatrix b are numerically not equal
+    */
+    friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
+        return !(a == b);
+    }
+
+    /** Writes text representation of SkMatrix to standard output. Floating point values
+        are written with limited precision; it may not be possible to reconstruct
+        original SkMatrix from output.
+    */
+    void dump() const;
+
+    /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and
+        skewing elements.
+        Returns -1 if scale factor overflows or SkMatrix contains perspective.
+
+        @return  minimum scale factor
+    */
+    SkScalar getMinScale() const;
+
+    /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and
+        skewing elements.
+        Returns -1 if scale factor overflows or SkMatrix contains perspective.
+
+        @return  maximum scale factor
+    */
+    SkScalar getMaxScale() const;
+
+    /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
+        maximum scaling factor. Scaling factors are computed by decomposing
+        the SkMatrix scaling and skewing elements.
+
+        Returns true if scaleFactors are found; otherwise, returns false and sets
+        scaleFactors to undefined values.
+
+        @param scaleFactors  storage for minimum and maximum scale factors
+        @return              true if scale factors were computed correctly
+    */
+    bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
+
+    /** Decomposes SkMatrix into scale components and whatever remains. Returns false if
+        SkMatrix could not be decomposed.
+
+        Sets scale to portion of SkMatrix that scale axes. Sets remaining to SkMatrix
+        with scaling factored out. remaining may be passed as nullptr
+        to determine if SkMatrix can be decomposed without computing remainder.
+
+        Returns true if scale components are found. scale and remaining are
+        unchanged if SkMatrix contains perspective; scale factors are not finite, or
+        are nearly zero.
+
+        On success: Matrix = scale * Remaining.
+
+        @param scale      axes scaling factors; may be nullptr
+        @param remaining  SkMatrix without scaling; may be nullptr
+        @return           true if scale can be computed
+    */
+    bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;
+
+    /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to:
+
+            | 1 0 0 |
+            | 0 1 0 |
+            | 0 0 1 |
+
+        @return  const identity SkMatrix
+    */
+    static const SkMatrix& I();
+
+    /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set
+        to:
+
+            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+            | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+
+        @return  const invalid SkMatrix
+    */
+    static const SkMatrix& InvalidMatrix();
+
+    /** Returns SkMatrix a multiplied by SkMatrix b.
+
+        Given:
+
+                | A B C |      | J K L |
+            a = | D E F |, b = | M N O |
+                | G H I |      | P Q R |
+
+        sets SkMatrix to:
+
+                    | A B C |   | J K L |   | AJ+BM+CP AK+BN+CQ AL+BO+CR |
+            a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
+                    | G H I |   | P Q R |   | GJ+HM+IP GK+HN+IQ GL+HO+IR |
+
+        @param a  SkMatrix on left side of multiply expression
+        @param b  SkMatrix on right side of multiply expression
+        @return   SkMatrix computed from a times b
+    */
+    static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
+        SkMatrix result;
+        result.setConcat(a, b);
+        return result;
+    }
+
+    /** Sets internal cache to unknown state. Use to force update after repeated
+        modifications to SkMatrix element reference returned by operator[](int index).
+    */
+    void dirtyMatrixTypeCache() {
+        this->setTypeMask(kUnknown_Mask);
+    }
+
+    /** Initializes SkMatrix with scale and translate elements.
+
+            | sx  0 tx |
+            |  0 sy ty |
+            |  0  0  1 |
+
+        @param sx  horizontal scale factor to store
+        @param sy  vertical scale factor to store
+        @param tx  horizontal translation to store
+        @param ty  vertical translation to store
+    */
+    void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
+        fMat[kMScaleX] = sx;
+        fMat[kMSkewX]  = 0;
+        fMat[kMTransX] = tx;
+
+        fMat[kMSkewY]  = 0;
+        fMat[kMScaleY] = sy;
+        fMat[kMTransY] = ty;
+
+        fMat[kMPersp0] = 0;
+        fMat[kMPersp1] = 0;
+        fMat[kMPersp2] = 1;
+
+        unsigned mask = 0;
+        if (sx != 1 || sy != 1) {
+            mask |= kScale_Mask;
+        }
+        if (tx || ty) {
+            mask |= kTranslate_Mask;
+        }
+        this->setTypeMask(mask | kRectStaysRect_Mask);
+    }
+
+    /** Returns true if all elements of the matrix are finite. Returns false if any
+        element is infinity, or NaN.
+
+        @return  true if matrix has only finite elements
+    */
+    bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
+
+private:
+    /** Set if the matrix will map a rectangle to another rectangle. This
+        can be true if the matrix is scale-only, or rotates a multiple of
+        90 degrees.
+
+        This bit will be set on identity matrices
+    */
+    static constexpr int kRectStaysRect_Mask = 0x10;
+
+    /** Set if the perspective bit is valid even though the rest of
+        the matrix is Unknown.
+    */
+    static constexpr int kOnlyPerspectiveValid_Mask = 0x40;
+
+    static constexpr int kUnknown_Mask = 0x80;
+
+    static constexpr int kORableMasks = kTranslate_Mask |
+                                        kScale_Mask |
+                                        kAffine_Mask |
+                                        kPerspective_Mask;
+
+    static constexpr int kAllMasks = kTranslate_Mask |
+                                     kScale_Mask |
+                                     kAffine_Mask |
+                                     kPerspective_Mask |
+                                     kRectStaysRect_Mask;
+
+    SkScalar         fMat[9];
+    mutable uint32_t fTypeMask;
+
+    static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
+
+    uint8_t computeTypeMask() const;
+    uint8_t computePerspectiveTypeMask() const;
+
+    void setTypeMask(int mask) {
+        // allow kUnknown or a valid mask
+        SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
+                 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
+                 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
+        fTypeMask = SkToU8(mask);
+    }
+
+    void orTypeMask(int mask) {
+        SkASSERT((mask & kORableMasks) == mask);
+        fTypeMask = SkToU8(fTypeMask | mask);
+    }
+
+    void clearTypeMask(int mask) {
+        // only allow a valid mask
+        SkASSERT((mask & kAllMasks) == mask);
+        fTypeMask = fTypeMask & ~mask;
+    }
+
+    TypeMask getPerspectiveTypeMaskOnly() const {
+        if ((fTypeMask & kUnknown_Mask) &&
+            !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
+            fTypeMask = this->computePerspectiveTypeMask();
+        }
+        return (TypeMask)(fTypeMask & 0xF);
+    }
+
+    /** Returns true if we already know that the matrix is identity;
+        false otherwise.
+    */
+    bool isTriviallyIdentity() const {
+        if (fTypeMask & kUnknown_Mask) {
+            return false;
+        }
+        return ((fTypeMask & 0xF) == 0);
+    }
+
+    inline void updateTranslateMask() {
+        if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
+            fTypeMask |= kTranslate_Mask;
+        } else {
+            fTypeMask &= ~kTranslate_Mask;
+        }
+    }
+
+    typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
+                                 SkPoint* result);
+
+    static MapXYProc GetMapXYProc(TypeMask mask) {
+        SkASSERT((mask & ~kAllMasks) == 0);
+        return gMapXYProcs[mask & kAllMasks];
+    }
+
+    MapXYProc getMapXYProc() const {
+        return GetMapXYProc(this->getType());
+    }
+
+    typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
+                                  const SkPoint src[], int count);
+
+    static MapPtsProc GetMapPtsProc(TypeMask mask) {
+        SkASSERT((mask & ~kAllMasks) == 0);
+        return gMapPtsProcs[mask & kAllMasks];
+    }
+
+    MapPtsProc getMapPtsProc() const {
+        return GetMapPtsProc(this->getType());
+    }
+
+    bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
+
+    static bool Poly2Proc(const SkPoint[], SkMatrix*);
+    static bool Poly3Proc(const SkPoint[], SkMatrix*);
+    static bool Poly4Proc(const SkPoint[], SkMatrix*);
+
+    static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+    static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
+
+    static const MapXYProc gMapXYProcs[];
+
+    static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
+    static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+    static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
+                               int count);
+    static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
+    static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
+
+    static const MapPtsProc gMapPtsProcs[];
+
+    // return the number of bytes written, whether or not buffer is null
+    size_t writeToMemory(void* buffer) const;
+    /**
+     * Reads data from the buffer parameter
+     *
+     * @param buffer Memory to read from
+     * @param length Amount of memory available in the buffer
+     * @return number of bytes read (must be a multiple of 4) or
+     *         0 if there was not enough memory available
+     */
+    size_t readFromMemory(const void* buffer, size_t length);
+
+    friend class SkPerspIter;
+    friend class SkMatrixPriv;
+    friend class SkReader32;
+    friend class SerializationTest;
+};
+SK_END_REQUIRE_DENSE
+
+#endif

+ 495 - 0
skia/include/core/SkMatrix44.h

@@ -0,0 +1,495 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMatrix44_DEFINED
+#define SkMatrix44_DEFINED
+
+#include "SkMatrix.h"
+#include "SkScalar.h"
+
+#include <atomic>
+#include <cstring>
+
+#ifdef SK_MSCALAR_IS_DOUBLE
+#ifdef SK_MSCALAR_IS_FLOAT
+    #error "can't define MSCALAR both as DOUBLE and FLOAT"
+#endif
+    typedef double SkMScalar;
+
+    static inline double SkFloatToMScalar(float x) {
+        return static_cast<double>(x);
+    }
+    static inline float SkMScalarToFloat(double x) {
+        return static_cast<float>(x);
+    }
+    static inline double SkDoubleToMScalar(double x) {
+        return x;
+    }
+    static inline double SkMScalarToDouble(double x) {
+        return x;
+    }
+    static inline double SkMScalarAbs(double x) {
+        return fabs(x);
+    }
+    static const SkMScalar SK_MScalarPI = 3.141592653589793;
+
+    #define SkMScalarFloor(x)           sk_double_floor(x)
+    #define SkMScalarCeil(x)            sk_double_ceil(x)
+    #define SkMScalarRound(x)           sk_double_round(x)
+
+    #define SkMScalarFloorToInt(x)      sk_double_floor2int(x)
+    #define SkMScalarCeilToInt(x)       sk_double_ceil2int(x)
+    #define SkMScalarRoundToInt(x)      sk_double_round2int(x)
+
+
+#elif defined SK_MSCALAR_IS_FLOAT
+#ifdef SK_MSCALAR_IS_DOUBLE
+    #error "can't define MSCALAR both as DOUBLE and FLOAT"
+#endif
+    typedef float SkMScalar;
+
+    static inline float SkFloatToMScalar(float x) {
+        return x;
+    }
+    static inline float SkMScalarToFloat(float x) {
+        return x;
+    }
+    static inline float SkDoubleToMScalar(double x) {
+        return sk_double_to_float(x);
+    }
+    static inline double SkMScalarToDouble(float x) {
+        return static_cast<double>(x);
+    }
+    static inline float SkMScalarAbs(float x) {
+        return sk_float_abs(x);
+    }
+    static const SkMScalar SK_MScalarPI = 3.14159265f;
+
+    #define SkMScalarFloor(x)           sk_float_floor(x)
+    #define SkMScalarCeil(x)            sk_float_ceil(x)
+    #define SkMScalarRound(x)           sk_float_round(x)
+
+    #define SkMScalarFloorToInt(x)      sk_float_floor2int(x)
+    #define SkMScalarCeilToInt(x)       sk_float_ceil2int(x)
+    #define SkMScalarRoundToInt(x)      sk_float_round2int(x)
+
+#endif
+
+#define SkIntToMScalar(n)       static_cast<SkMScalar>(n)
+
+#define SkMScalarToScalar(x)    SkMScalarToFloat(x)
+#define SkScalarToMScalar(x)    SkFloatToMScalar(x)
+
+static const SkMScalar SK_MScalar1 = 1;
+
+///////////////////////////////////////////////////////////////////////////////
+
+struct SkVector4 {
+    SkScalar fData[4];
+
+    SkVector4() {
+        this->set(0, 0, 0, 1);
+    }
+    SkVector4(const SkVector4& src) {
+        memcpy(fData, src.fData, sizeof(fData));
+    }
+    SkVector4(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+        fData[0] = x;
+        fData[1] = y;
+        fData[2] = z;
+        fData[3] = w;
+    }
+
+    SkVector4& operator=(const SkVector4& src) {
+        memcpy(fData, src.fData, sizeof(fData));
+        return *this;
+    }
+
+    bool operator==(const SkVector4& v) {
+        return fData[0] == v.fData[0] && fData[1] == v.fData[1] &&
+               fData[2] == v.fData[2] && fData[3] == v.fData[3];
+    }
+    bool operator!=(const SkVector4& v) {
+        return !(*this == v);
+    }
+    bool equals(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+        return fData[0] == x && fData[1] == y &&
+               fData[2] == z && fData[3] == w;
+    }
+
+    void set(SkScalar x, SkScalar y, SkScalar z, SkScalar w = SK_Scalar1) {
+        fData[0] = x;
+        fData[1] = y;
+        fData[2] = z;
+        fData[3] = w;
+    }
+};
+
+/** \class SkMatrix44
+
+    The SkMatrix44 class holds a 4x4 matrix.
+
+    SkMatrix44 is not thread safe unless you've first called SkMatrix44::getType().
+*/
+class SK_API SkMatrix44 {
+public:
+
+    enum Uninitialized_Constructor {
+        kUninitialized_Constructor
+    };
+    enum Identity_Constructor {
+        kIdentity_Constructor
+    };
+
+    SkMatrix44(Uninitialized_Constructor) {}  // ironically, cannot be constexpr
+
+    constexpr SkMatrix44(Identity_Constructor)
+        : fMat{{ 1, 0, 0, 0, },
+               { 0, 1, 0, 0, },
+               { 0, 0, 1, 0, },
+               { 0, 0, 0, 1, }}
+        , fTypeMask(kIdentity_Mask)
+    {}
+
+    constexpr SkMatrix44() : SkMatrix44{kIdentity_Constructor} {}
+
+    SkMatrix44(const SkMatrix44& src) {
+        memcpy(fMat, src.fMat, sizeof(fMat));
+        fTypeMask.store(src.fTypeMask, std::memory_order_relaxed);
+    }
+
+    SkMatrix44(const SkMatrix44& a, const SkMatrix44& b) {
+        this->setConcat(a, b);
+    }
+
+    SkMatrix44& operator=(const SkMatrix44& src) {
+        if (&src != this) {
+            memcpy(fMat, src.fMat, sizeof(fMat));
+            fTypeMask.store(src.fTypeMask, std::memory_order_relaxed);
+        }
+        return *this;
+    }
+
+    bool operator==(const SkMatrix44& other) const;
+    bool operator!=(const SkMatrix44& other) const {
+        return !(other == *this);
+    }
+
+    /* When converting from SkMatrix44 to SkMatrix, the third row and
+     * column is dropped.  When converting from SkMatrix to SkMatrix44
+     * the third row and column remain as identity:
+     * [ a b c ]      [ a b 0 c ]
+     * [ d e f ]  ->  [ d e 0 f ]
+     * [ g h i ]      [ 0 0 1 0 ]
+     *                [ g h 0 i ]
+     */
+    SkMatrix44(const SkMatrix&);
+    SkMatrix44& operator=(const SkMatrix& src);
+    operator SkMatrix() const;
+
+    /**
+     *  Return a reference to a const identity matrix
+     */
+    static const SkMatrix44& I();
+
+    enum TypeMask {
+        kIdentity_Mask      = 0,
+        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
+        kScale_Mask         = 0x02,  //!< set if the matrix has any scale != 1
+        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
+        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
+    };
+
+    /**
+     *  Returns a bitfield describing the transformations the matrix may
+     *  perform. The bitfield is computed conservatively, so it may include
+     *  false positives. For example, when kPerspective_Mask is true, all
+     *  other bits may be set to true even in the case of a pure perspective
+     *  transform.
+     */
+    inline TypeMask getType() const {
+        if (fTypeMask.load(std::memory_order_relaxed) & kUnknown_Mask) {
+            fTypeMask.store(this->computeTypeMask(), std::memory_order_relaxed);
+        }
+        SkASSERT(!(fTypeMask & kUnknown_Mask));
+        return (TypeMask)fTypeMask.load(std::memory_order_relaxed);
+    }
+
+    /**
+     *  Return true if the matrix is identity.
+     */
+    inline bool isIdentity() const {
+        return kIdentity_Mask == this->getType();
+    }
+
+    /**
+     *  Return true if the matrix contains translate or is identity.
+     */
+    inline bool isTranslate() const {
+        return !(this->getType() & ~kTranslate_Mask);
+    }
+
+    /**
+     *  Return true if the matrix only contains scale or translate or is identity.
+     */
+    inline bool isScaleTranslate() const {
+        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
+    }
+
+    /**
+     *  Returns true if the matrix only contains scale or is identity.
+     */
+    inline bool isScale() const {
+            return !(this->getType() & ~kScale_Mask);
+    }
+
+    inline bool hasPerspective() const {
+        return SkToBool(this->getType() & kPerspective_Mask);
+    }
+
+    void setIdentity();
+    inline void reset() { this->setIdentity();}
+
+    /**
+     *  get a value from the matrix. The row,col parameters work as follows:
+     *  (0, 0)  scale-x
+     *  (0, 3)  translate-x
+     *  (3, 0)  perspective-x
+     */
+    inline SkMScalar get(int row, int col) const {
+        SkASSERT((unsigned)row <= 3);
+        SkASSERT((unsigned)col <= 3);
+        return fMat[col][row];
+    }
+
+    /**
+     *  set a value in the matrix. The row,col parameters work as follows:
+     *  (0, 0)  scale-x
+     *  (0, 3)  translate-x
+     *  (3, 0)  perspective-x
+     */
+    inline void set(int row, int col, SkMScalar value) {
+        SkASSERT((unsigned)row <= 3);
+        SkASSERT((unsigned)col <= 3);
+        fMat[col][row] = value;
+        this->dirtyTypeMask();
+    }
+
+    inline double getDouble(int row, int col) const {
+        return SkMScalarToDouble(this->get(row, col));
+    }
+    inline void setDouble(int row, int col, double value) {
+        this->set(row, col, SkDoubleToMScalar(value));
+    }
+    inline float getFloat(int row, int col) const {
+        return SkMScalarToFloat(this->get(row, col));
+    }
+    inline void setFloat(int row, int col, float value) {
+        this->set(row, col, SkFloatToMScalar(value));
+    }
+
+    /** These methods allow one to efficiently read matrix entries into an
+     *  array. The given array must have room for exactly 16 entries. Whenever
+     *  possible, they will try to use memcpy rather than an entry-by-entry
+     *  copy.
+     *
+     *  Col major indicates that consecutive elements of columns will be stored
+     *  contiguously in memory.  Row major indicates that consecutive elements
+     *  of rows will be stored contiguously in memory.
+     */
+    void asColMajorf(float[]) const;
+    void asColMajord(double[]) const;
+    void asRowMajorf(float[]) const;
+    void asRowMajord(double[]) const;
+
+    /** These methods allow one to efficiently set all matrix entries from an
+     *  array. The given array must have room for exactly 16 entries. Whenever
+     *  possible, they will try to use memcpy rather than an entry-by-entry
+     *  copy.
+     *
+     *  Col major indicates that input memory will be treated as if consecutive
+     *  elements of columns are stored contiguously in memory.  Row major
+     *  indicates that input memory will be treated as if consecutive elements
+     *  of rows are stored contiguously in memory.
+     */
+    void setColMajorf(const float[]);
+    void setColMajord(const double[]);
+    void setRowMajorf(const float[]);
+    void setRowMajord(const double[]);
+
+#ifdef SK_MSCALAR_IS_FLOAT
+    void setColMajor(const SkMScalar data[]) { this->setColMajorf(data); }
+    void setRowMajor(const SkMScalar data[]) { this->setRowMajorf(data); }
+#else
+    void setColMajor(const SkMScalar data[]) { this->setColMajord(data); }
+    void setRowMajor(const SkMScalar data[]) { this->setRowMajord(data); }
+#endif
+
+    /* This sets the top-left of the matrix and clears the translation and
+     * perspective components (with [3][3] set to 1).  m_ij is interpreted
+     * as the matrix entry at row = i, col = j. */
+    void set3x3(SkMScalar m_00, SkMScalar m_10, SkMScalar m_20,
+                SkMScalar m_01, SkMScalar m_11, SkMScalar m_21,
+                SkMScalar m_02, SkMScalar m_12, SkMScalar m_22);
+    void set3x3RowMajorf(const float[]);
+
+    void setTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+    void preTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+    void postTranslate(SkMScalar dx, SkMScalar dy, SkMScalar dz);
+
+    void setScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+    void preScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+    void postScale(SkMScalar sx, SkMScalar sy, SkMScalar sz);
+
+    inline void setScale(SkMScalar scale) {
+        this->setScale(scale, scale, scale);
+    }
+    inline void preScale(SkMScalar scale) {
+        this->preScale(scale, scale, scale);
+    }
+    inline void postScale(SkMScalar scale) {
+        this->postScale(scale, scale, scale);
+    }
+
+    void setRotateDegreesAbout(SkMScalar x, SkMScalar y, SkMScalar z,
+                               SkMScalar degrees) {
+        this->setRotateAbout(x, y, z, degrees * SK_MScalarPI / 180);
+    }
+
+    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
+        it will be automatically resized.
+     */
+    void setRotateAbout(SkMScalar x, SkMScalar y, SkMScalar z,
+                        SkMScalar radians);
+    /** Rotate about the vector [x,y,z]. Does not check the length of the
+        vector, assuming it is unit-length.
+     */
+    void setRotateAboutUnit(SkMScalar x, SkMScalar y, SkMScalar z,
+                            SkMScalar radians);
+
+    void setConcat(const SkMatrix44& a, const SkMatrix44& b);
+    inline void preConcat(const SkMatrix44& m) {
+        this->setConcat(*this, m);
+    }
+    inline void postConcat(const SkMatrix44& m) {
+        this->setConcat(m, *this);
+    }
+
+    friend SkMatrix44 operator*(const SkMatrix44& a, const SkMatrix44& b) {
+        return SkMatrix44(a, b);
+    }
+
+    /** If this is invertible, return that in inverse and return true. If it is
+        not invertible, return false and leave the inverse parameter in an
+        unspecified state.
+     */
+    bool invert(SkMatrix44* inverse) const;
+
+    /** Transpose this matrix in place. */
+    void transpose();
+
+    /** Apply the matrix to the src vector, returning the new vector in dst.
+        It is legal for src and dst to point to the same memory.
+     */
+    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;
+    inline void mapScalars(SkScalar vec[4]) const {
+        this->mapScalars(vec, vec);
+    }
+
+#ifdef SK_MSCALAR_IS_DOUBLE
+    void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const;
+#elif defined SK_MSCALAR_IS_FLOAT
+    inline void mapMScalars(const SkMScalar src[4], SkMScalar dst[4]) const {
+        this->mapScalars(src, dst);
+    }
+#endif
+    inline void mapMScalars(SkMScalar vec[4]) const {
+        this->mapMScalars(vec, vec);
+    }
+
+    friend SkVector4 operator*(const SkMatrix44& m, const SkVector4& src) {
+        SkVector4 dst;
+        m.mapScalars(src.fData, dst.fData);
+        return dst;
+    }
+
+    /**
+     *  map an array of [x, y, 0, 1] through the matrix, returning an array
+     *  of [x', y', z', w'].
+     *
+     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
+     *  @param count    number of [x, y] pairs in src2
+     *  @param dst4     array of [x', y', z', w'] quads as the output.
+     */
+    void map2(const float src2[], int count, float dst4[]) const;
+    void map2(const double src2[], int count, double dst4[]) const;
+
+    /** Returns true if transformating an axis-aligned square in 2d by this matrix
+        will produce another 2d axis-aligned square; typically means the matrix
+        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
+        degrees into a perpendicular plane collapses a square to a line, but
+        is still considered to be axis-aligned.
+
+        By default, tolerates very slight error due to float imprecisions;
+        a 90-degree rotation can still end up with 10^-17 of
+        "non-axis-aligned" result.
+     */
+    bool preserves2dAxisAlignment(SkMScalar epsilon = SK_ScalarNearlyZero) const;
+
+    void dump() const;
+
+    double determinant() const;
+
+private:
+    /* This is indexed by [col][row]. */
+    SkMScalar                       fMat[4][4];
+    mutable std::atomic<unsigned>   fTypeMask;
+
+    static constexpr int kUnknown_Mask = 0x80;
+
+    static constexpr int kAllPublic_Masks = 0xF;
+
+    void as3x4RowMajorf(float[]) const;
+    void set3x4RowMajorf(const float[]);
+
+    SkMScalar transX() const { return fMat[3][0]; }
+    SkMScalar transY() const { return fMat[3][1]; }
+    SkMScalar transZ() const { return fMat[3][2]; }
+
+    SkMScalar scaleX() const { return fMat[0][0]; }
+    SkMScalar scaleY() const { return fMat[1][1]; }
+    SkMScalar scaleZ() const { return fMat[2][2]; }
+
+    SkMScalar perspX() const { return fMat[0][3]; }
+    SkMScalar perspY() const { return fMat[1][3]; }
+    SkMScalar perspZ() const { return fMat[2][3]; }
+
+    int computeTypeMask() const;
+
+    inline void dirtyTypeMask() {
+        fTypeMask.store(kUnknown_Mask, std::memory_order_relaxed);
+    }
+
+    inline void setTypeMask(int mask) {
+        SkASSERT(0 == (~(kAllPublic_Masks | kUnknown_Mask) & mask));
+        fTypeMask.store(mask, std::memory_order_relaxed);
+    }
+
+    /**
+     *  Does not take the time to 'compute' the typemask. Only returns true if
+     *  we already know that this matrix is identity.
+     */
+    inline bool isTriviallyIdentity() const {
+        return 0 == fTypeMask.load(std::memory_order_relaxed);
+    }
+
+    inline const SkMScalar* values() const { return &fMat[0][0]; }
+
+    friend class SkColorSpace;
+};
+
+#endif

+ 175 - 0
skia/include/core/SkMetaData.h

@@ -0,0 +1,175 @@
+
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef SkMetaData_DEFINED
+#define SkMetaData_DEFINED
+
+#include "SkScalar.h"
+
+class SkRefCnt;
+
+class SK_API SkMetaData {
+public:
+    /**
+     *  Used to manage the life-cycle of a ptr in the metadata. This is option
+     *  in setPtr, and is only invoked when either copying one metadata to
+     *  another, or when the metadata is destroyed.
+     *
+     *  setPtr(name, ptr, proc) {
+     *      fPtr = proc(ptr, true);
+     *  }
+     *
+     *  copy: A = B {
+     *      A.fPtr = B.fProc(B.fPtr, true);
+     *  }
+     *
+     *  ~SkMetaData {
+     *      fProc(fPtr, false);
+     *  }
+     */
+    typedef void* (*PtrProc)(void* ptr, bool doRef);
+
+    /**
+     *  Implements PtrProc for SkRefCnt pointers
+     */
+    static void* RefCntProc(void* ptr, bool doRef);
+
+    SkMetaData();
+    SkMetaData(const SkMetaData& src);
+    ~SkMetaData();
+
+    SkMetaData& operator=(const SkMetaData& src);
+
+    void reset();
+
+    bool findS32(const char name[], int32_t* value = nullptr) const;
+    bool findScalar(const char name[], SkScalar* value = nullptr) const;
+    const SkScalar* findScalars(const char name[], int* count,
+                                SkScalar values[] = nullptr) const;
+    const char* findString(const char name[]) const;
+    bool findPtr(const char name[], void** value = nullptr, PtrProc* = nullptr) const;
+    bool findBool(const char name[], bool* value = nullptr) const;
+    const void* findData(const char name[], size_t* byteCount = nullptr) const;
+
+    bool hasS32(const char name[], int32_t value) const {
+        int32_t v;
+        return this->findS32(name, &v) && v == value;
+    }
+    bool hasScalar(const char name[], SkScalar value) const {
+        SkScalar v;
+        return this->findScalar(name, &v) && v == value;
+    }
+    bool hasString(const char name[], const char value[]) const {
+        const char* v = this->findString(name);
+        return  (v == nullptr && value == nullptr) ||
+                (v != nullptr && value != nullptr && !strcmp(v, value));
+    }
+    bool hasPtr(const char name[], void* value) const {
+        void* v;
+        return this->findPtr(name, &v) && v == value;
+    }
+    bool hasBool(const char name[], bool value) const {
+        bool    v;
+        return this->findBool(name, &v) && v == value;
+    }
+    bool hasData(const char name[], const void* data, size_t byteCount) const {
+        size_t len;
+        const void* ptr = this->findData(name, &len);
+        return ptr && len == byteCount && !memcmp(ptr, data, len);
+    }
+
+    void setS32(const char name[], int32_t value);
+    void setScalar(const char name[], SkScalar value);
+    SkScalar* setScalars(const char name[], int count, const SkScalar values[] = nullptr);
+    void setString(const char name[], const char value[]);
+    void setPtr(const char name[], void* value, PtrProc proc = nullptr);
+    void setBool(const char name[], bool value);
+    // the data is copied from the input pointer.
+    void setData(const char name[], const void* data, size_t byteCount);
+
+    bool removeS32(const char name[]);
+    bool removeScalar(const char name[]);
+    bool removeString(const char name[]);
+    bool removePtr(const char name[]);
+    bool removeBool(const char name[]);
+    bool removeData(const char name[]);
+
+    // helpers for SkRefCnt
+    bool findRefCnt(const char name[], SkRefCnt** ptr = nullptr) {
+        return this->findPtr(name, reinterpret_cast<void**>(ptr));
+    }
+    bool hasRefCnt(const char name[], SkRefCnt* ptr) {
+        return this->hasPtr(name, ptr);
+    }
+    void setRefCnt(const char name[], SkRefCnt* ptr) {
+        this->setPtr(name, ptr, RefCntProc);
+    }
+    bool removeRefCnt(const char name[]) {
+        return this->removePtr(name);
+    }
+
+    enum Type {
+        kS32_Type,
+        kScalar_Type,
+        kString_Type,
+        kPtr_Type,
+        kBool_Type,
+        kData_Type,
+
+        kTypeCount
+    };
+
+    struct Rec;
+    class Iter;
+    friend class Iter;
+
+    class Iter {
+    public:
+        Iter() : fRec(nullptr) {}
+        Iter(const SkMetaData&);
+
+        /** Reset the iterator, so that calling next() will return the first
+            data element. This is done implicitly in the constructor.
+        */
+        void reset(const SkMetaData&);
+
+        /** Each time next is called, it returns the name of the next data element,
+            or null when there are no more elements. If non-null is returned, then the
+            element's type is returned (if not null), and the number of data values
+            is returned in count (if not null).
+        */
+        const char* next(Type*, int* count);
+
+    private:
+        Rec* fRec;
+    };
+
+public:
+    struct Rec {
+        Rec*        fNext;
+        uint16_t    fDataCount; // number of elements
+        uint8_t     fDataLen;   // sizeof a single element
+        uint8_t     fType;
+
+        const void* data() const { return (this + 1); }
+        void*       data() { return (this + 1); }
+        const char* name() const { return (const char*)this->data() + fDataLen * fDataCount; }
+        char*       name() { return (char*)this->data() + fDataLen * fDataCount; }
+
+        static Rec* Alloc(size_t);
+        static void Free(Rec*);
+    };
+    Rec*    fRec;
+
+    const Rec* find(const char name[], Type) const;
+    void* set(const char name[], const void* data, size_t len, Type, int count);
+    bool remove(const char name[], Type);
+};
+
+#endif

+ 9 - 0
skia/include/core/SkMilestone.h

@@ -0,0 +1,9 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SK_MILESTONE
+#define SK_MILESTONE 72
+#endif

+ 75 - 0
skia/include/core/SkMultiPictureDraw.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkMultiPictureDraw_DEFINED
+#define SkMultiPictureDraw_DEFINED
+
+#include "../private/SkTDArray.h"
+#include "SkMatrix.h"
+
+class SkCanvas;
+class SkPaint;
+class SkPicture;
+
+/** \class SkMultiPictureDraw
+
+    The MultiPictureDraw object accepts several picture/canvas pairs and
+    then attempts to optimally draw the pictures into the canvases, sharing
+    as many resources as possible.
+*/
+class SK_API SkMultiPictureDraw {
+public:
+    /**
+     *  Create an object to optimize the drawing of multiple pictures.
+     *  @param reserve Hint for the number of add calls expected to be issued
+     */
+    SkMultiPictureDraw(int reserve = 0);
+    ~SkMultiPictureDraw() { this->reset(); }
+
+    /**
+     *  Add a canvas/picture pair for later rendering.
+     *  @param canvas   the canvas in which to draw picture
+     *  @param picture  the picture to draw into canvas
+     *  @param matrix   if non-NULL, applied to the CTM when drawing
+     *  @param paint    if non-NULL, draw picture to a temporary buffer
+     *                  and then apply the paint when the result is drawn
+     */
+    void add(SkCanvas* canvas,
+             const SkPicture* picture,
+             const SkMatrix* matrix = nullptr,
+             const SkPaint* paint = nullptr);
+
+    /**
+     *  Perform all the previously added draws. This will reset the state
+     *  of this object. If flush is true, all canvases are flushed after
+     *  draw.
+     */
+    void draw(bool flush = false);
+
+    /**
+     *  Abandon all buffered draws and reset to the initial state.
+     */
+    void reset();
+
+private:
+    struct DrawData {
+        SkCanvas*        fCanvas;
+        const SkPicture* fPicture; // reffed
+        SkMatrix         fMatrix;
+        SkPaint*         fPaint;   // owned
+
+        void init(SkCanvas*, const SkPicture*, const SkMatrix*, const SkPaint*);
+        void draw();
+
+        static void Reset(SkTDArray<DrawData>&);
+    };
+
+    SkTDArray<DrawData> fThreadSafeDrawData;
+    SkTDArray<DrawData> fGPUDrawData;
+};
+
+#endif

+ 74 - 0
skia/include/core/SkOverdrawCanvas.h

@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkOverdrawCanvas_DEFINED
+#define SkOverdrawCanvas_DEFINED
+
+#include "SkCanvasVirtualEnforcer.h"
+#include "SkNWayCanvas.h"
+
+/**
+ *  Captures all drawing commands.  Rather than draw the actual content, this device
+ *  increments the alpha channel of each pixel every time it would have been touched
+ *  by a draw call.  This is useful for detecting overdraw.
+ */
+class SK_API SkOverdrawCanvas : public SkCanvasVirtualEnforcer<SkNWayCanvas> {
+public:
+    /* Does not take ownership of canvas */
+    SkOverdrawCanvas(SkCanvas*);
+
+    void onDrawText(const void*, size_t, SkScalar, SkScalar, const SkPaint&) override;
+    void onDrawPosText(const void*, size_t, const SkPoint[], const SkPaint&) override;
+    void onDrawPosTextH(const void*, size_t, const SkScalar[], SkScalar, const SkPaint&) override;
+    void onDrawTextRSXform(const void*, size_t, const SkRSXform[], const SkRect*,
+                           const SkPaint&) override;
+    void onDrawTextBlob(const SkTextBlob*, SkScalar, SkScalar, const SkPaint&) override;
+    void onDrawPatch(const SkPoint[12], const SkColor[4], const SkPoint[4], SkBlendMode,
+                     const SkPaint&) override;
+    void onDrawPaint(const SkPaint&) override;
+    void onDrawRect(const SkRect&, const SkPaint&) override;
+    void onDrawRegion(const SkRegion&, const SkPaint&) override;
+    void onDrawOval(const SkRect&, const SkPaint&) override;
+    void onDrawArc(const SkRect&, SkScalar, SkScalar, bool, const SkPaint&) override;
+    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
+    void onDrawRRect(const SkRRect&, const SkPaint&) override;
+    void onDrawPoints(PointMode, size_t, const SkPoint[], const SkPaint&) override;
+    void onDrawVerticesObject(const SkVertices*, const SkVertices::Bone bones[], int boneCount,
+                              SkBlendMode, const SkPaint&) override;
+    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[],
+                     int, SkBlendMode, const SkRect*, const SkPaint*) override;
+    void onDrawPath(const SkPath&, const SkPaint&) override;
+    void onDrawImage(const SkImage*, SkScalar, SkScalar, const SkPaint*) override;
+    void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
+                         SrcRectConstraint) override;
+    void onDrawImageNine(const SkImage*, const SkIRect&, const SkRect&, const SkPaint*) override;
+    void onDrawImageLattice(const SkImage*, const Lattice&, const SkRect&, const SkPaint*) override;
+    void onDrawImageSet(const ImageSetEntry[], int count, SkFilterQuality, SkBlendMode) override;
+    void onDrawBitmap(const SkBitmap&, SkScalar, SkScalar, const SkPaint*) override;
+    void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
+                          SrcRectConstraint) override;
+    void onDrawBitmapNine(const SkBitmap&, const SkIRect&, const SkRect&, const SkPaint*) override;
+    void onDrawBitmapLattice(const SkBitmap&, const Lattice&, const SkRect&,
+                             const SkPaint*) override;
+    void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
+    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+    void onDrawAnnotation(const SkRect&, const char key[], SkData* value) override;
+    void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
+
+private:
+    void drawPosTextCommon(const void*, size_t, const SkScalar[], int, const SkPoint&,
+                           const SkPaint&);
+
+    inline SkPaint overdrawPaint(const SkPaint& paint);
+
+    SkPaint   fPaint;
+
+    typedef SkCanvasVirtualEnforcer<SkNWayCanvas> INHERITED;
+};
+
+#endif

+ 1427 - 0
skia/include/core/SkPaint.h

@@ -0,0 +1,1427 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkPaint.h and docs/SkPaint_Reference.bmh
+   on 2018-08-28 10:32:58. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkPaint_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkPaint_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkPaint.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkPaint_DEFINED
+#define SkPaint_DEFINED
+
+#include "../private/SkTo.h"
+#include "SkBlendMode.h"
+#include "SkColor.h"
+#include "SkFilterQuality.h"
+#include "SkFontMetrics.h"
+#include "SkFontTypes.h"
+#include "SkMatrix.h"
+#include "SkRefCnt.h"
+
+#define SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
+
+class GrTextBlob;
+class SkAutoDescriptor;
+class SkColorFilter;
+class SkColorSpace;
+class SkData;
+class SkDescriptor;
+class SkDrawLooper;
+class SkGlyph;
+class SkGlyphRunBuilder;
+class SkGlyphRun;
+class SkGlyphRunListPainter;
+struct SkRect;
+class SkGlyphCache;
+class SkImageFilter;
+class SkMaskFilter;
+class SkPath;
+class SkPathEffect;
+struct SkPoint;
+class SkRunFont;
+class SkShader;
+class SkSurfaceProps;
+class SkTextBlob;
+class SkTextBlobRunIterator;
+class SkTypeface;
+
+#ifndef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#define SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+#endif
+
+/** \class SkPaint
+    SkPaint controls options applied when drawing and measuring. SkPaint collects all
+    options outside of the SkCanvas clip and SkCanvas matrix.
+
+    Various options apply to text, strokes and fills, and images.
+
+    Some options may not be implemented on all platforms; in these cases, setting
+    the option has no effect. Some options are conveniences that duplicate SkCanvas
+    functionality; for instance, text size is identical to matrix scale.
+
+    SkPaint options are rarely exclusive; each option modifies a stage of the drawing
+    pipeline and multiple pipeline stages may be affected by a single SkPaint.
+
+    SkPaint collects effects and filters that describe single-pass and multiple-pass
+    algorithms that alter the drawing geometry, color, and transparency. For instance,
+    SkPaint does not directly implement dashing or blur, but contains the objects that do so.
+
+    The objects contained by SkPaint are opaque, and cannot be edited outside of the SkPaint
+    to affect it. The implementation is free to defer computations associated with the
+    SkPaint, or ignore them altogether. For instance, some GPU implementations draw all
+    SkPath geometries with anti-aliasing, regardless of how SkPaint::kAntiAlias_Flag
+    is set in SkPaint.
+
+    SkPaint describes a single color, a single font, a single image quality, and so on.
+    Multiple colors are drawn either by using multiple paints or with objects like
+    SkShader attached to SkPaint.
+*/
+class SK_API SkPaint {
+public:
+
+    /** Constructs SkPaint with default values.
+
+        @return  default initialized SkPaint
+    */
+    SkPaint();
+
+    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
+        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
+        between the original paint and the copy. Objects containing SkRefCnt increment
+        their references by one.
+
+        The referenced objects SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+        SkDrawLooper, and SkImageFilter cannot be modified after they are created.
+        This prevents objects with SkRefCnt from being modified once SkPaint refers to them.
+
+        @param paint  original to copy
+        @return       shallow copy of paint
+    */
+    SkPaint(const SkPaint& paint);
+
+    /** Implements a move constructor to avoid increasing the reference counts
+        of objects referenced by the paint.
+
+        After the call, paint is undefined, and can be safely destructed.
+
+        @param paint  original to move
+        @return       content of paint
+    */
+    SkPaint(SkPaint&& paint);
+
+    /** Decreases SkPaint SkRefCnt of owned objects: SkTypeface, SkPathEffect, SkShader,
+        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter. If the
+        objects containing SkRefCnt go to zero, they are deleted.
+    */
+    ~SkPaint();
+
+    /** Makes a shallow copy of SkPaint. SkTypeface, SkPathEffect, SkShader,
+        SkMaskFilter, SkColorFilter, SkDrawLooper, and SkImageFilter are shared
+        between the original paint and the copy. Objects containing SkRefCnt in the
+        prior destination are decreased by one, and the referenced objects are deleted if the
+        resulting count is zero. Objects containing SkRefCnt in the parameter paint
+        are increased by one. paint is unmodified.
+
+        @param paint  original to copy
+        @return       content of paint
+    */
+    SkPaint& operator=(const SkPaint& paint);
+
+    /** Moves the paint to avoid increasing the reference counts
+        of objects referenced by the paint parameter. Objects containing SkRefCnt in the
+        prior destination are decreased by one; those objects are deleted if the resulting count
+        is zero.
+
+        After the call, paint is undefined, and can be safely destructed.
+
+        @param paint  original to move
+        @return       content of paint
+    */
+    SkPaint& operator=(SkPaint&& paint);
+
+    /** Compares a and b, and returns true if a and b are equivalent. May return false
+        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+        SkDrawLooper, or SkImageFilter have identical contents but different pointers.
+
+        @param a  SkPaint to compare
+        @param b  SkPaint to compare
+        @return   true if SkPaint pair are equivalent
+    */
+    SK_API friend bool operator==(const SkPaint& a, const SkPaint& b);
+
+    /** Compares a and b, and returns true if a and b are not equivalent. May return true
+        if SkTypeface, SkPathEffect, SkShader, SkMaskFilter, SkColorFilter,
+        SkDrawLooper, or SkImageFilter have identical contents but different pointers.
+
+        @param a  SkPaint to compare
+        @param b  SkPaint to compare
+        @return   true if SkPaint pair are not equivalent
+    */
+    friend bool operator!=(const SkPaint& a, const SkPaint& b) {
+        return !(a == b);
+    }
+
+    /** Returns a hash generated from SkPaint values and pointers.
+        Identical hashes guarantee that the paints are
+        equivalent, but differing hashes do not guarantee that the paints have differing
+        contents.
+
+        If operator==(const SkPaint& a, const SkPaint& b) returns true for two paints,
+        their hashes are also equal.
+
+        The hash returned is platform and implementation specific.
+
+        @return  a shallow hash
+    */
+    uint32_t getHash() const;
+
+    /** Sets all SkPaint contents to their initial values. This is equivalent to replacing
+        SkPaint with the result of SkPaint().
+    */
+    void reset();
+
+#ifdef SK_SUPPORT_LEGACY_NESTED_HINTINGENUM
+    /** \enum SkPaint::Hinting
+        Deprecated.
+        Hinting adjusts the glyph outlines so that the shape provides a uniform
+        look at a given point size on font engines that support it. Hinting may have a
+        muted effect or no effect at all depending on the platform.
+
+        The four levels roughly control corresponding features on platforms that use FreeType
+        as the font engine.
+    */
+    enum Hinting : uint8_t {
+        kNo_Hinting     = 0, //!< glyph outlines unchanged
+        kSlight_Hinting = 1, //!< minimal modification to improve constrast
+        kNormal_Hinting = 2, //!< glyph outlines modified to improve constrast
+        kFull_Hinting   = 3, //!< modifies glyph outlines for maximum constrast
+    };
+#endif
+
+    /** Sets level of glyph outline adjustment.
+        Does not check for valid values of hintingLevel.
+
+        @param hintingLevel  one of: SkFontHinting::kNone, SkFontHinting::kSlight,
+                                     SkFontHinting::kNormal, SkFontHinting::kFull
+    */
+    void setHinting(SkFontHinting hintingLevel);
+
+    /** Returns level of glyph outline adjustment.
+
+        @return  one of: SkFontHinting::kNone, SkFontHinting::kSlight, SkFontHinting::kNormal,
+                         SkFontHinting::kFull
+     */
+    SkFontHinting getHinting() const { return (SkFontHinting)fBitfields.fHinting; }
+
+    /** \enum SkPaint::Flags
+        The bit values stored in Flags.
+        The default value for Flags, normally zero, can be changed at compile time
+        with a custom definition of SkPaintDefaults_Flags.
+        All flags can be read and written explicitly; Flags allows manipulating
+        multiple settings at once.
+    */
+    enum Flags {
+        kAntiAlias_Flag          = 0x01,   //!< mask for setting anti-alias
+        kDither_Flag             = 0x04,   //!< mask for setting dither
+        kFakeBoldText_Flag       = 0x20,   //!< mask for setting fake bold
+        kLinearText_Flag         = 0x40,   //!< mask for setting linear text
+        kSubpixelText_Flag       = 0x80,   //!< mask for setting subpixel text
+        kLCDRenderText_Flag      = 0x200,  //!< mask for setting LCD text
+        kEmbeddedBitmapText_Flag = 0x400,  //!< mask for setting font embedded bitmaps
+        kAutoHinting_Flag        = 0x800,  //!< mask for setting auto-hinting
+                                           // 0x1000 used to be kVertical
+        kAllFlags                = 0xFFFF, //!< mask of all Flags
+    };
+
+    #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    /** Private.
+     */
+    enum ReserveFlags {
+        kUnderlineText_ReserveFlag  = 0x08, //!< to be deprecated soon
+        kStrikeThruText_ReserveFlag = 0x10, //!< to be deprecated soon
+    };
+    #endif
+
+    /** Returns paint settings described by SkPaint::Flags. Each setting uses one
+        bit, and can be tested with SkPaint::Flags members.
+
+        @return  zero, one, or more bits described by SkPaint::Flags
+    */
+    uint32_t getFlags() const { return fBitfields.fFlags; }
+
+    /** Replaces SkPaint::Flags with flags, the union of the SkPaint::Flags members.
+        All SkPaint::Flags members may be cleared, or one or more may be set.
+
+        @param flags  union of SkPaint::Flags for SkPaint
+    */
+    void setFlags(uint32_t flags);
+
+    /** Returns true if pixels on the active edges of SkPath may be drawn with partial transparency.
+
+        Equivalent to getFlags() masked with kAntiAlias_Flag.
+
+        @return  kAntiAlias_Flag state
+    */
+    bool isAntiAlias() const {
+        return SkToBool(this->getFlags() & kAntiAlias_Flag);
+    }
+
+    /** Requests, but does not require, that edge pixels draw opaque or with
+        partial transparency.
+
+        Sets kAntiAlias_Flag if aa is true.
+        Clears kAntiAlias_Flag if aa is false.
+
+        @param aa  setting for kAntiAlias_Flag
+    */
+    void setAntiAlias(bool aa);
+
+    /** Returns true if color error may be distributed to smooth color transition.
+
+        Equivalent to getFlags() masked with kDither_Flag.
+
+        @return  kDither_Flag state
+    */
+    bool isDither() const {
+        return SkToBool(this->getFlags() & kDither_Flag);
+    }
+
+    /** Requests, but does not require, to distribute color error.
+
+        Sets kDither_Flag if dither is true.
+        Clears kDither_Flag if dither is false.
+
+        @param dither  setting for kDither_Flag
+    */
+    void setDither(bool dither);
+
+    /** Returns true if text is converted to SkPath before drawing and measuring.
+
+        Equivalent to getFlags() masked with kLinearText_Flag.
+
+        @return  kLinearText_Flag state
+    */
+    bool isLinearText() const {
+        return SkToBool(this->getFlags() & kLinearText_Flag);
+    }
+
+    /** Requests, but does not require, that glyphs are converted to SkPath
+        before drawing and measuring.
+        By default, kLinearText_Flag is clear.
+
+        Sets kLinearText_Flag if linearText is true.
+        Clears kLinearText_Flag if linearText is false.
+
+        @param linearText  setting for kLinearText_Flag
+    */
+    void setLinearText(bool linearText);
+
+    /** Returns true if glyphs at different sub-pixel positions may differ on pixel edge coverage.
+
+        Equivalent to getFlags() masked with kSubpixelText_Flag.
+
+        @return  kSubpixelText_Flag state
+    */
+    bool isSubpixelText() const {
+        return SkToBool(this->getFlags() & kSubpixelText_Flag);
+    }
+
+    /** Requests, but does not require, that glyphs respect sub-pixel positioning.
+
+        Sets kSubpixelText_Flag if subpixelText is true.
+        Clears kSubpixelText_Flag if subpixelText is false.
+
+        @param subpixelText  setting for kSubpixelText_Flag
+    */
+    void setSubpixelText(bool subpixelText);
+
+    /** Returns true if glyphs may use LCD striping to improve glyph edges.
+
+        Returns true if SkPaint::Flags kLCDRenderText_Flag is set.
+
+        @return  kLCDRenderText_Flag state
+    */
+    bool isLCDRenderText() const {
+        return SkToBool(this->getFlags() & kLCDRenderText_Flag);
+    }
+
+    /** Requests, but does not require, that glyphs use LCD striping for glyph edges.
+
+        Sets kLCDRenderText_Flag if lcdText is true.
+        Clears kLCDRenderText_Flag if lcdText is false.
+
+        @param lcdText  setting for kLCDRenderText_Flag
+    */
+    void setLCDRenderText(bool lcdText);
+
+    /** Returns true if font engine may return glyphs from font bitmaps instead of from outlines.
+
+        Equivalent to getFlags() masked with kEmbeddedBitmapText_Flag.
+
+        @return  kEmbeddedBitmapText_Flag state
+    */
+    bool isEmbeddedBitmapText() const {
+        return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
+    }
+
+    /** Requests, but does not require, to use bitmaps in fonts instead of outlines.
+
+        Sets kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is true.
+        Clears kEmbeddedBitmapText_Flag if useEmbeddedBitmapText is false.
+
+        @param useEmbeddedBitmapText  setting for kEmbeddedBitmapText_Flag
+    */
+    void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
+
+    /** Returns true if SkPaint::Hinting is set to SkFontHinting::kNormal or
+        SkFontHinting::kFull, and if platform uses FreeType as the font manager.
+        If true, instructs the font manager to always hint glyphs.
+
+        Equivalent to getFlags() masked with kAutoHinting_Flag.
+
+        @return  kAutoHinting_Flag state
+    */
+    bool isAutohinted() const {
+        return SkToBool(this->getFlags() & kAutoHinting_Flag);
+    }
+
+    /** Sets whether to always hint glyphs.
+        If SkPaint::Hinting is set to SkFontHinting::kNormal or SkFontHinting::kFull
+        and useAutohinter is set, instructs the font manager to always hint glyphs.
+        auto-hinting has no effect if SkPaint::Hinting is set to SkFontHinting::kNone or
+        SkFontHinting::kSlight.
+
+        Only affects platforms that use FreeType as the font manager.
+
+        Sets kAutoHinting_Flag if useAutohinter is true.
+        Clears kAutoHinting_Flag if useAutohinter is false.
+
+        @param useAutohinter  setting for kAutoHinting_Flag
+    */
+    void setAutohinted(bool useAutohinter);
+
+    /** Returns true if approximate bold by increasing the stroke width when creating glyph bitmaps
+        from outlines.
+
+        Equivalent to getFlags() masked with kFakeBoldText_Flag.
+
+        @return  kFakeBoldText_Flag state
+    */
+    bool isFakeBoldText() const {
+        return SkToBool(this->getFlags() & kFakeBoldText_Flag);
+    }
+
+    /** Increases stroke width when creating glyph bitmaps to approximate a bold typeface.
+
+        Sets kFakeBoldText_Flag if fakeBoldText is true.
+        Clears kFakeBoldText_Flag if fakeBoldText is false.
+
+        @param fakeBoldText  setting for kFakeBoldText_Flag
+    */
+    void setFakeBoldText(bool fakeBoldText);
+
+    /** Returns SkFilterQuality, the image filtering level. A lower setting
+        draws faster; a higher setting looks better when the image is scaled.
+
+        @return  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+                 kMedium_SkFilterQuality, kHigh_SkFilterQuality
+    */
+    SkFilterQuality getFilterQuality() const {
+        return (SkFilterQuality)fBitfields.fFilterQuality;
+    }
+
+    /** Sets SkFilterQuality, the image filtering level. A lower setting
+        draws faster; a higher setting looks better when the image is scaled.
+        Does not check to see if quality is valid.
+
+        @param quality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+                        kMedium_SkFilterQuality, kHigh_SkFilterQuality
+    */
+    void setFilterQuality(SkFilterQuality quality);
+
+    /** \enum SkPaint::Style
+        Set Style to fill, stroke, or both fill and stroke geometry.
+        The stroke and fill
+        share all paint attributes; for instance, they are drawn with the same color.
+
+        Use kStrokeAndFill_Style to avoid hitting the same pixels twice with a stroke draw and
+        a fill draw.
+    */
+    enum Style : uint8_t {
+        kFill_Style,          //!< set to fill geometry
+        kStroke_Style,        //!< set to stroke geometry
+        kStrokeAndFill_Style, //!< sets to stroke and fill geometry
+    };
+
+    /** May be used to verify that SkPaint::Style is a legal value.
+    */
+    static constexpr int kStyleCount = kStrokeAndFill_Style + 1;
+
+    /** Returns whether the geometry is filled, stroked, or filled and stroked.
+
+        @return  one of:kFill_Style, kStroke_Style, kStrokeAndFill_Style
+    */
+    Style getStyle() const { return (Style)fBitfields.fStyle; }
+
+    /** Sets whether the geometry is filled, stroked, or filled and stroked.
+        Has no effect if style is not a legal SkPaint::Style value.
+
+        @param style  one of: kFill_Style, kStroke_Style, kStrokeAndFill_Style
+    */
+    void setStyle(Style style);
+
+    /** Retrieves alpha and RGB, unpremultiplied, packed into 32 bits.
+        Use helpers SkColorGetA(), SkColorGetR(), SkColorGetG(), and SkColorGetB() to extract
+        a color component.
+
+        @return  unpremultiplied ARGB
+    */
+    SkColor getColor() const { return fColor4f.toSkColor(); }
+
+    /** Retrieves alpha and RGB, unpremultiplied, as four floating point values. RGB are
+        are extended sRGB values (sRGB gamut, and encoded with the sRGB transfer function).
+
+        @return  unpremultiplied RGBA
+    */
+    SkColor4f getColor4f() const { return fColor4f; }
+
+    /** Sets alpha and RGB used when stroking and filling. The color is a 32-bit value,
+        unpremultiplied, packing 8-bit components for alpha, red, blue, and green.
+
+        @param color  unpremultiplied ARGB
+    */
+    void setColor(SkColor color);
+
+    /** Sets alpha and RGB used when stroking and filling. The color is four floating
+        point values, unpremultiplied. The color values are interpreted as being in
+        the colorSpace. If colorSpace is nullptr, then color is assumed to be in the
+        sRGB color space.
+
+        @param color       unpremultiplied RGBA
+        @param colorSpace  SkColorSpace describing the encoding of color
+    */
+    void setColor4f(const SkColor4f& color, SkColorSpace* colorSpace);
+
+    /** Retrieves alpha from the color used when stroking and filling.
+
+        @return  alpha ranging from zero, fully transparent, to 255, fully opaque
+    */
+    uint8_t getAlpha() const { return sk_float_round2int(fColor4f.fA * 255); }
+
+    /** Replaces alpha, leaving RGB
+        unchanged. An out of range value triggers an assert in the debug
+        build. a is a value from zero to 255.
+        a set to zero makes color fully transparent; a set to 255 makes color
+        fully opaque.
+
+        @param a  alpha component of color
+    */
+    void setAlpha(U8CPU a);
+
+    /** Sets color used when drawing solid fills. The color components range from 0 to 255.
+        The color is unpremultiplied; alpha sets the transparency independent of RGB.
+
+        @param a  amount of alpha, from fully transparent (0) to fully opaque (255)
+        @param r  amount of red, from no red (0) to full red (255)
+        @param g  amount of green, from no green (0) to full green (255)
+        @param b  amount of blue, from no blue (0) to full blue (255)
+    */
+    void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+
+    /** Returns the thickness of the pen used by SkPaint to
+        outline the shape.
+
+        @return  zero for hairline, greater than zero for pen thickness
+    */
+    SkScalar getStrokeWidth() const { return fWidth; }
+
+    /** Sets the thickness of the pen used by the paint to
+        outline the shape.
+        Has no effect if width is less than zero.
+
+        @param width  zero thickness for hairline; greater than zero for pen thickness
+    */
+    void setStrokeWidth(SkScalar width);
+
+    /** Returns the limit at which a sharp corner is drawn beveled.
+
+        @return  zero and greater miter limit
+    */
+    SkScalar getStrokeMiter() const { return fMiterLimit; }
+
+    /** Sets the limit at which a sharp corner is drawn beveled.
+        Valid values are zero and greater.
+        Has no effect if miter is less than zero.
+
+        @param miter  zero and greater miter limit
+    */
+    void setStrokeMiter(SkScalar miter);
+
+    /** \enum SkPaint::Cap
+        Cap draws at the beginning and end of an open path contour.
+    */
+    enum Cap {
+        kButt_Cap,                  //!< no stroke extension
+        kRound_Cap,                 //!< adds circle
+        kSquare_Cap,                //!< adds square
+        kLast_Cap    = kSquare_Cap, //!< largest Cap value
+        kDefault_Cap = kButt_Cap,   //!< equivalent to kButt_Cap
+    };
+
+    /** May be used to verify that SkPaint::Cap is a legal value.
+    */
+    static constexpr int kCapCount = kLast_Cap + 1;
+
+    /** \enum SkPaint::Join
+        Join specifies how corners are drawn when a shape is stroked. Join
+        affects the four corners of a stroked rectangle, and the connected segments in a
+        stroked path.
+
+        Choose miter join to draw sharp corners. Choose round join to draw a circle with a
+        radius equal to the stroke width on top of the corner. Choose bevel join to minimally
+        connect the thick strokes.
+
+        The fill path constructed to describe the stroked path respects the join setting but may
+        not contain the actual join. For instance, a fill path constructed with round joins does
+        not necessarily include circles at each connected segment.
+    */
+    enum Join : uint8_t {
+        kMiter_Join,                 //!< extends to miter limit
+        kRound_Join,                 //!< adds circle
+        kBevel_Join,                 //!< connects outside edges
+        kLast_Join    = kBevel_Join, //!< equivalent to the largest value for Join
+        kDefault_Join = kMiter_Join, //!< equivalent to kMiter_Join
+    };
+
+    /** May be used to verify that SkPaint::Join is a legal value.
+    */
+    static constexpr int kJoinCount = kLast_Join + 1;
+
+    /** Returns the geometry drawn at the beginning and end of strokes.
+
+        @return  one of: kButt_Cap, kRound_Cap, kSquare_Cap
+    */
+    Cap getStrokeCap() const { return (Cap)fBitfields.fCapType; }
+
+    /** Sets the geometry drawn at the beginning and end of strokes.
+
+        @param cap  one of: kButt_Cap, kRound_Cap, kSquare_Cap;
+                    has no effect if cap is not valid
+    */
+    void setStrokeCap(Cap cap);
+
+    /** Returns the geometry drawn at the corners of strokes.
+
+        @return  one of: kMiter_Join, kRound_Join, kBevel_Join
+    */
+    Join getStrokeJoin() const { return (Join)fBitfields.fJoinType; }
+
+    /** Sets the geometry drawn at the corners of strokes.
+
+        @param join  one of: kMiter_Join, kRound_Join, kBevel_Join;
+                     otherwise, has no effect
+    */
+    void setStrokeJoin(Join join);
+
+    /** Returns the filled equivalent of the stroked path.
+
+        @param src       SkPath read to create a filled version
+        @param dst       resulting SkPath; may be the same as src, but may not be nullptr
+        @param cullRect  optional limit passed to SkPathEffect
+        @param resScale  if > 1, increase precision, else if (0 < resScale < 1) reduce precision
+                         to favor speed and size
+        @return          true if the path represents style fill, or false if it represents hairline
+    */
+    bool getFillPath(const SkPath& src, SkPath* dst, const SkRect* cullRect,
+                     SkScalar resScale = 1) const;
+
+    /** Returns the filled equivalent of the stroked path.
+
+        Replaces dst with the src path modified by SkPathEffect and style stroke.
+        SkPathEffect, if any, is not culled. stroke width is created with default precision.
+
+        @param src  SkPath read to create a filled version
+        @param dst  resulting SkPath dst may be the same as src, but may not be nullptr
+        @return     true if the path represents style fill, or false if it represents hairline
+    */
+    bool getFillPath(const SkPath& src, SkPath* dst) const {
+        return this->getFillPath(src, dst, nullptr, 1);
+    }
+
+    /** Returns optional colors used when filling a path, such as a gradient.
+
+        Does not alter SkShader SkRefCnt.
+
+        @return  SkShader if previously set, nullptr otherwise
+    */
+    SkShader* getShader() const { return fShader.get(); }
+
+    /** Returns optional colors used when filling a path, such as a gradient.
+
+        Increases SkShader SkRefCnt by one.
+
+        @return  SkShader if previously set, nullptr otherwise
+    */
+    sk_sp<SkShader> refShader() const;
+
+    /** Sets optional colors used when filling a path, such as a gradient.
+
+        Sets SkShader to shader, decreasing SkRefCnt of the previous SkShader.
+        Increments shader SkRefCnt by one.
+
+        @param shader  how geometry is filled with color; if nullptr, color is used instead
+    */
+    void setShader(sk_sp<SkShader> shader);
+
+    /** Returns SkColorFilter if set, or nullptr.
+        Does not alter SkColorFilter SkRefCnt.
+
+        @return  SkColorFilter if previously set, nullptr otherwise
+    */
+    SkColorFilter* getColorFilter() const { return fColorFilter.get(); }
+
+    /** Returns SkColorFilter if set, or nullptr.
+        Increases SkColorFilter SkRefCnt by one.
+
+        @return  SkColorFilter if set, or nullptr
+    */
+    sk_sp<SkColorFilter> refColorFilter() const;
+
+    /** Sets SkColorFilter to filter, decreasing SkRefCnt of the previous
+        SkColorFilter. Pass nullptr to clear SkColorFilter.
+
+        Increments filter SkRefCnt by one.
+
+        @param colorFilter  SkColorFilter to apply to subsequent draw
+    */
+    void setColorFilter(sk_sp<SkColorFilter> colorFilter);
+
+    /** Returns SkBlendMode.
+        By default, returns SkBlendMode::kSrcOver.
+
+        @return  mode used to combine source color with destination color
+    */
+    SkBlendMode getBlendMode() const { return (SkBlendMode)fBlendMode; }
+
+    /** Returns true if SkBlendMode is SkBlendMode::kSrcOver, the default.
+
+        @return  true if SkBlendMode is SkBlendMode::kSrcOver
+    */
+    bool isSrcOver() const { return (SkBlendMode)fBlendMode == SkBlendMode::kSrcOver; }
+
+    /** Sets SkBlendMode to mode.
+        Does not check for valid input.
+
+        @param mode  SkBlendMode used to combine source color and destination
+    */
+    void setBlendMode(SkBlendMode mode) { fBlendMode = (unsigned)mode; }
+
+    /** Returns SkPathEffect if set, or nullptr.
+        Does not alter SkPathEffect SkRefCnt.
+
+        @return  SkPathEffect if previously set, nullptr otherwise
+    */
+    SkPathEffect* getPathEffect() const { return fPathEffect.get(); }
+
+    /** Returns SkPathEffect if set, or nullptr.
+        Increases SkPathEffect SkRefCnt by one.
+
+        @return  SkPathEffect if previously set, nullptr otherwise
+    */
+    sk_sp<SkPathEffect> refPathEffect() const;
+
+    /** Sets SkPathEffect to pathEffect, decreasing SkRefCnt of the previous
+        SkPathEffect. Pass nullptr to leave the path geometry unaltered.
+
+        Increments pathEffect SkRefCnt by one.
+
+        @param pathEffect  replace SkPath with a modification when drawn
+    */
+    void setPathEffect(sk_sp<SkPathEffect> pathEffect);
+
+    /** Returns SkMaskFilter if set, or nullptr.
+        Does not alter SkMaskFilter SkRefCnt.
+
+        @return  SkMaskFilter if previously set, nullptr otherwise
+    */
+    SkMaskFilter* getMaskFilter() const { return fMaskFilter.get(); }
+
+    /** Returns SkMaskFilter if set, or nullptr.
+
+        Increases SkMaskFilter SkRefCnt by one.
+
+        @return  SkMaskFilter if previously set, nullptr otherwise
+    */
+    sk_sp<SkMaskFilter> refMaskFilter() const;
+
+    /** Sets SkMaskFilter to maskFilter, decreasing SkRefCnt of the previous
+        SkMaskFilter. Pass nullptr to clear SkMaskFilter and leave SkMaskFilter effect on
+        mask alpha unaltered.
+
+        Increments maskFilter SkRefCnt by one.
+
+        @param maskFilter  modifies clipping mask generated from drawn geometry
+    */
+    void setMaskFilter(sk_sp<SkMaskFilter> maskFilter);
+
+    /** Returns SkTypeface if set, or nullptr.
+        Does not alter SkTypeface SkRefCnt.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    SkTypeface* getTypeface() const { return fTypeface.get(); }
+
+    /** Increases SkTypeface SkRefCnt by one.
+
+        @return  SkTypeface if previously set, nullptr otherwise
+    */
+    sk_sp<SkTypeface> refTypeface() const;
+
+    /** Sets SkTypeface to typeface, decreasing SkRefCnt of the previous SkTypeface.
+        Pass nullptr to clear SkTypeface and use the default typeface. Increments
+        typeface SkRefCnt by one.
+
+        @param typeface  font and style used to draw text
+    */
+    void setTypeface(sk_sp<SkTypeface> typeface);
+
+    /** Returns SkImageFilter if set, or nullptr.
+        Does not alter SkImageFilter SkRefCnt.
+
+        @return  SkImageFilter if previously set, nullptr otherwise
+    */
+    SkImageFilter* getImageFilter() const { return fImageFilter.get(); }
+
+    /** Returns SkImageFilter if set, or nullptr.
+        Increases SkImageFilter SkRefCnt by one.
+
+        @return  SkImageFilter if previously set, nullptr otherwise
+    */
+    sk_sp<SkImageFilter> refImageFilter() const;
+
+    /** Sets SkImageFilter to imageFilter, decreasing SkRefCnt of the previous
+        SkImageFilter. Pass nullptr to clear SkImageFilter, and remove SkImageFilter effect
+        on drawing.
+
+        Increments imageFilter SkRefCnt by one.
+
+        @param imageFilter  how SkImage is sampled when transformed
+    */
+    void setImageFilter(sk_sp<SkImageFilter> imageFilter);
+
+    /** Returns SkDrawLooper if set, or nullptr.
+        Does not alter SkDrawLooper SkRefCnt.
+
+        @return  SkDrawLooper if previously set, nullptr otherwise
+    */
+    SkDrawLooper* getDrawLooper() const { return fDrawLooper.get(); }
+
+    /** Returns SkDrawLooper if set, or nullptr.
+        Increases SkDrawLooper SkRefCnt by one.
+
+        @return  SkDrawLooper if previously set, nullptr otherwise
+    */
+    sk_sp<SkDrawLooper> refDrawLooper() const;
+
+    /** Deprecated.
+        (see skbug.com/6259)
+    */
+    SkDrawLooper* getLooper() const { return fDrawLooper.get(); }
+
+    /** Sets SkDrawLooper to drawLooper, decreasing SkRefCnt of the previous
+        drawLooper.  Pass nullptr to clear SkDrawLooper and leave SkDrawLooper effect on
+        drawing unaltered.
+
+        Increments drawLooper SkRefCnt by one.
+
+        @param drawLooper  iterates through drawing one or more time, altering SkPaint
+    */
+    void setDrawLooper(sk_sp<SkDrawLooper> drawLooper);
+
+    /** Deprecated.
+        (see skbug.com/6259)
+    */
+    void setLooper(sk_sp<SkDrawLooper> drawLooper);
+
+    /** Returns text size in points.
+
+        @return  typographic height of text
+    */
+    SkScalar getTextSize() const { return fTextSize; }
+
+    /** Sets text size in points.
+        Has no effect if textSize is not greater than or equal to zero.
+
+        @param textSize  typographic height of text
+    */
+    void setTextSize(SkScalar textSize);
+
+    /** Returns text scale on x-axis.
+        Default value is 1.
+
+        @return  text horizontal scale
+    */
+    SkScalar getTextScaleX() const { return fTextScaleX; }
+
+    /** Sets text scale on x-axis.
+        Default value is 1.
+
+        @param scaleX  text horizontal scale
+    */
+    void setTextScaleX(SkScalar scaleX);
+
+    /** Returns text skew on x-axis.
+        Default value is zero.
+
+        @return  additional shear on x-axis relative to y-axis
+    */
+    SkScalar getTextSkewX() const { return fTextSkewX; }
+
+    /** Sets text skew on x-axis.
+        Default value is zero.
+
+        @param skewX  additional shear on x-axis relative to y-axis
+    */
+    void setTextSkewX(SkScalar skewX);
+
+    /** \enum SkPaint::TextEncoding
+        TextEncoding determines whether text specifies character codes and their encoded
+        size, or glyph indices. Characters are encoded as specified by the Unicode standard.
+
+        Character codes encoded size are specified by UTF-8, UTF-16, or UTF-32.
+        All character code formats are able to represent all of Unicode, differing only
+        in the total storage required.
+
+        UTF-8 (RFC 3629) encodes each character as one or more 8-bit bytes.
+
+        UTF-16 (RFC 2781) encodes each character as one or two 16-bit words.
+
+        UTF-32 encodes each character as one 32-bit word.
+
+        font manager uses font data to convert character code points into glyph indices.
+        A glyph index is a 16-bit word.
+
+        TextEncoding is set to kUTF8_TextEncoding by default.
+    */
+    enum TextEncoding : uint8_t {
+        kUTF8_TextEncoding,    //!< uses bytes to represent UTF-8 or ASCII
+        kUTF16_TextEncoding,   //!< uses two byte words to represent most of Unicode
+        kUTF32_TextEncoding,   //!< uses four byte words to represent all of Unicode
+        kGlyphID_TextEncoding, //!< uses two byte words to represent glyph indices
+    };
+
+    /** Returns SkPaint::TextEncoding.
+        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.
+
+        @return  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
+                 kGlyphID_TextEncoding
+    */
+    TextEncoding getTextEncoding() const {
+      return (TextEncoding)fBitfields.fTextEncoding;
+    }
+
+    /** Sets SkPaint::TextEncoding to encoding.
+        SkPaint::TextEncoding determines how character code points are mapped to font glyph indices.
+        Invalid values for encoding are ignored.
+
+        @param encoding  one of: kUTF8_TextEncoding, kUTF16_TextEncoding, kUTF32_TextEncoding, or
+                         kGlyphID_TextEncoding
+    */
+    void setTextEncoding(TextEncoding encoding);
+    // Experimental
+    void setTextEncoding(SkTextEncoding encoding) {
+        this->setTextEncoding((TextEncoding)encoding);
+    }
+
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+
+#ifdef SK_SUPPORT_LEGACY_FONTMETRICS_IN_PAINT
+    /**
+        SkFontMetrics is filled out by getFontMetrics(). SkFontMetrics contents reflect the values
+        computed by font manager using SkTypeface. Values are set to zero if they are
+        not available.
+
+        All vertical values are relative to the baseline, on a y-axis pointing down.
+        Zero is on the baseline, negative values are above the baseline, and positive
+        values are below the baseline.
+
+        fUnderlineThickness and fUnderlinePosition have a bit set in fFlags if their values
+        are valid, since their value may be zero.
+
+        fStrikeoutThickness and fStrikeoutPosition have a bit set in fFlags if their values
+        are valid, since their value may be zero.
+    */
+    typedef SkFontMetrics FontMetrics;
+#endif
+
+    /** Returns SkFontMetrics associated with SkTypeface.
+        The return value is the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        If metrics is not nullptr, SkFontMetrics is copied to metrics.
+        Results are scaled by text size but does not take into account
+        dimensions required by text scale x, text skew x, fake bold,
+        style stroke, and SkPathEffect.
+
+        @param metrics  storage for SkFontMetrics; may be nullptr
+        @return         recommended spacing between lines
+    */
+    SkScalar getFontMetrics(SkFontMetrics* metrics) const;
+
+    /** Returns the recommended spacing between lines: the sum of metrics
+        descent, ascent, and leading.
+        Result is scaled by text size but does not take into account
+        dimensions required by stroking and SkPathEffect.
+        Returns the same result as getFontMetrics().
+
+        @return  recommended spacing between lines
+    */
+    SkScalar getFontSpacing() const { return this->getFontMetrics(nullptr); }
+
+    /** Converts text into glyph indices.
+        Returns the number of glyph indices represented by text.
+        SkPaint::TextEncoding specifies how text represents characters or glyphs.
+        glyphs may be nullptr, to compute the glyph count.
+
+        Does not check text for valid character codes or valid glyph indices.
+
+        If byteLength equals zero, returns zero.
+        If byteLength includes a partial character, the partial character is ignored.
+
+        If SkPaint::TextEncoding is kUTF8_TextEncoding and
+        text contains an invalid UTF-8 sequence, zero is returned.
+
+        @param text        character storage encoded with SkPaint::TextEncoding
+        @param byteLength  length of character storage in bytes
+        @param glyphs      storage for glyph indices; may be nullptr
+        @return            number of glyphs represented by text of length byteLength
+    */
+    int textToGlyphs(const void* text, size_t byteLength,
+                     SkGlyphID glyphs[]) const;
+
+    /** Returns true if all text corresponds to a non-zero glyph index.
+        Returns false if any characters in text are not supported in
+        SkTypeface.
+
+        If SkPaint::TextEncoding is kGlyphID_TextEncoding,
+        returns true if all glyph indices in text are non-zero;
+        does not check to see if text contains valid glyph indices for SkTypeface.
+
+        Returns true if byteLength is zero.
+
+        @param text        array of characters or glyphs
+        @param byteLength  number of bytes in text array
+        @return            true if all text corresponds to a non-zero glyph index
+    */
+    bool containsText(const void* text, size_t byteLength) const;
+
+    /** Converts glyphs into text if possible.
+        Glyph values without direct Unicode equivalents are mapped to zero.
+        Uses the SkTypeface, but is unaffected
+        by SkPaint::TextEncoding; the text values returned are equivalent to kUTF32_TextEncoding.
+
+        Only supported on platforms that use FreeType as the font engine.
+
+        @param glyphs  array of indices into font
+        @param count   length of glyph array
+        @param text    storage for character codes, one per glyph
+    */
+    void glyphsToUnichars(const SkGlyphID glyphs[], int count, SkUnichar text[]) const;
+
+    /** Returns the number of glyphs in text.
+        Uses SkPaint::TextEncoding to count the glyphs.
+        Returns the same result as textToGlyphs().
+
+        @param text        character storage encoded with SkPaint::TextEncoding
+        @param byteLength  length of character storage in bytes
+        @return            number of glyphs represented by text of length byteLength
+    */
+    int countText(const void* text, size_t byteLength) const;
+
+    /** Returns the advance width of text.
+        The advance is the normal distance to move before drawing additional text.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
+        and text size, text scale x, text skew x, stroke width, and
+        SkPathEffect to scale the metrics and bounds.
+        Returns the bounding box of text if bounds is not nullptr.
+        The bounding box is computed as if the text was drawn at the origin.
+
+        @param text    character codes or glyph indices to be measured
+        @param length  number of bytes of text to measure
+        @param bounds  returns bounding box relative to (0, 0) if not nullptr
+        @return        advance width or height
+    */
+    SkScalar measureText(const void* text, size_t length, SkRect* bounds) const;
+
+    /** Returns the advance width of text.
+        The advance is the normal distance to move before drawing additional text.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
+        and text size to scale the metrics.
+        Does not scale the advance or bounds by fake bold or SkPathEffect.
+
+        @param text    character codes or glyph indices to be measured
+        @param length  number of bytes of text to measure
+        @return        advance width or height
+    */
+    SkScalar measureText(const void* text, size_t length) const {
+        return this->measureText(text, length, nullptr);
+    }
+#endif
+
+    /** Returns the bytes of text that fit within maxWidth.
+        The text fragment fits if its advance width is less than or equal to maxWidth.
+        Measures only while the advance is less than or equal to maxWidth.
+        Returns the advance or the text fragment in measuredWidth if it not nullptr.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
+        and text size to scale the metrics.
+        Does not scale the advance or bounds by fake bold or SkPathEffect.
+
+        @param text           character codes or glyph indices to be measured
+        @param length         number of bytes of text to measure
+        @param maxWidth       advance limit; text is measured while advance is less than maxWidth
+        @param measuredWidth  returns the width of the text less than or equal to maxWidth
+        @return               bytes of text that fit, always less than or equal to length
+    */
+    size_t  breakText(const void* text, size_t length, SkScalar maxWidth,
+                      SkScalar* measuredWidth = nullptr) const;
+
+#ifdef SK_SUPPORT_LEGACY_PAINT_TEXTMEASURE
+    /** Retrieves the advance and bounds for each glyph in text, and returns
+        the glyph count in text.
+        Both widths and bounds may be nullptr.
+        If widths is not nullptr, widths must be an array of glyph count entries.
+        if bounds is not nullptr, bounds must be an array of glyph count entries.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the font metrics,
+        and text size to scale the widths and bounds.
+        Does not scale the advance by fake bold or SkPathEffect.
+        Does include fake bold and SkPathEffect in the bounds.
+
+        @param text        character codes or glyph indices to be measured
+        @param byteLength  number of bytes of text to measure
+        @param widths      returns text advances for each glyph; may be nullptr
+        @param bounds      returns bounds for each glyph relative to (0, 0); may be nullptr
+        @return            glyph count in text
+    */
+    int getTextWidths(const void* text, size_t byteLength, SkScalar widths[],
+                      SkRect bounds[] = nullptr) const;
+
+    /** Returns the geometry as SkPath equivalent to the drawn text.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        All of the glyph paths are stored in path.
+        Uses x, y, to position path.
+
+        @param text    character codes or glyph indices
+        @param length  number of bytes of text
+        @param x       x-axis value of the origin of the text
+        @param y       y-axis value of the origin of the text
+        @param path    geometry of the glyphs
+    */
+    void getTextPath(const void* text, size_t length, SkScalar x, SkScalar y,
+                     SkPath* path) const;
+
+    /** Returns the geometry as SkPath equivalent to the drawn text.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        All of the glyph paths are stored in path.
+        Uses pos array to position path.
+        pos contains a position for each glyph.
+
+        @param text    character codes or glyph indices
+        @param length  number of bytes of text
+        @param pos     positions of each glyph
+        @param path    geometry of the glyphs
+    */
+    void getPosTextPath(const void* text, size_t length,
+                        const SkPoint pos[], SkPath* path) const;
+
+#ifdef SK_SUPPORT_LEGACY_TEXTINTERCEPTS
+public:
+#else
+private:
+#endif
+    /** Returns the number of intervals that intersect bounds.
+        bounds describes a pair of lines parallel to the text advance.
+        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
+        the string.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        Uses x, y to position intervals.
+
+        Pass nullptr for intervals to determine the size of the interval array.
+
+        intervals are cached to improve performance for multiple calls.
+
+        @param text       character codes or glyph indices
+        @param length     number of bytes of text
+        @param x          x-axis value of the origin of the text
+        @param y          y-axis value of the origin of the text
+        @param bounds     lower and upper line parallel to the advance
+        @param intervals  returned intersections; may be nullptr
+        @return           number of intersections; may be zero
+    */
+    int getTextIntercepts(const void* text, size_t length, SkScalar x, SkScalar y,
+                          const SkScalar bounds[2], SkScalar* intervals) const;
+
+    /** Returns the number of intervals that intersect bounds.
+        bounds describes a pair of lines parallel to the text advance.
+        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
+        the string.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        Uses pos array to position intervals.
+
+        Pass nullptr for intervals to determine the size of the interval array.
+
+        intervals are cached to improve performance for multiple calls.
+
+        @param text       character codes or glyph indices
+        @param length     number of bytes of text
+        @param pos        positions of each glyph
+        @param bounds     lower and upper line parallel to the advance
+        @param intervals  returned intersections; may be nullptr
+        @return           number of intersections; may be zero
+    */
+    int getPosTextIntercepts(const void* text, size_t length, const SkPoint pos[],
+                             const SkScalar bounds[2], SkScalar* intervals) const;
+
+    /** Returns the number of intervals that intersect bounds.
+        bounds describes a pair of lines parallel to the text advance.
+        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
+        the string.
+        Uses SkPaint::TextEncoding to decode text, SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        Uses xpos array, constY to position intervals.
+
+        Pass nullptr for intervals to determine the size of the interval array.
+
+        intervals are cached to improve performance for multiple calls.
+
+        @param text       character codes or glyph indices
+        @param length     number of bytes of text
+        @param xpos       positions of each glyph on x-axis
+        @param constY     position of each glyph on y-axis
+        @param bounds     lower and upper line parallel to the advance
+        @param intervals  returned intersections; may be nullptr
+        @return           number of intersections; may be zero
+    */
+    int getPosTextHIntercepts(const void* text, size_t length, const SkScalar xpos[],
+                              SkScalar constY, const SkScalar bounds[2], SkScalar* intervals) const;
+public:
+
+    /** Returns the number of intervals that intersect bounds.
+        bounds describes a pair of lines parallel to the text advance.
+        The return count is zero or a multiple of two, and is at most twice the number of glyphs in
+        the string.
+        Uses SkTypeface to get the glyph paths,
+        and text size, fake bold, and SkPathEffect to scale and modify the glyph paths.
+        Uses run array to position intervals.
+
+        SkPaint::TextEncoding must be set to SkPaint::kGlyphID_TextEncoding.
+
+        Pass nullptr for intervals to determine the size of the interval array.
+
+        intervals are cached to improve performance for multiple calls.
+
+        @param blob       glyphs, positions, and text paint attributes
+        @param bounds     lower and upper line parallel to the advance
+        @param intervals  returned intersections; may be nullptr
+        @return           number of intersections; may be zero
+    */
+    int getTextBlobIntercepts(const SkTextBlob* blob, const SkScalar bounds[2],
+                              SkScalar* intervals) const;
+
+    /** Returns the union of bounds of all glyphs.
+        Returned dimensions are computed by font manager from font data,
+        ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect.
+
+        If text size is large, text scale is one, and text skew is zero,
+        returns the bounds as:
+        { SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }.
+
+        @return  union of bounds of all glyphs
+    */
+    SkRect getFontBounds() const;
+#endif
+
+    /** Returns true if SkPaint prevents all drawing;
+        otherwise, the SkPaint may or may not allow drawing.
+
+        Returns true if, for example, SkBlendMode combined with alpha computes a
+        new alpha of zero.
+
+        @return  true if SkPaint prevents all drawing
+    */
+    bool nothingToDraw() const;
+
+    /**     (to be made private)
+        Returns true if SkPaint does not include elements requiring extensive computation
+        to compute SkBaseDevice bounds of drawn geometry. For instance, SkPaint with SkPathEffect
+        always returns false.
+
+        @return  true if SkPaint allows for fast computation of bounds
+    */
+    bool canComputeFastBounds() const;
+
+    /**     (to be made private)
+        Only call this if canComputeFastBounds() returned true. This takes a
+        raw rectangle (the raw bounds of a shape), and adjusts it for stylistic
+        effects in the paint (e.g. stroking). If needed, it uses the storage
+        parameter. It returns the adjusted bounds that can then be used
+        for SkCanvas::quickReject tests.
+
+        The returned SkRect will either be orig or storage, thus the caller
+        should not rely on storage being set to the result, but should always
+        use the returned value. It is legal for orig and storage to be the same
+        SkRect.
+            For example:
+            if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
+                SkRect storage;
+                if (canvas->quickReject(paint.computeFastBounds(path.getBounds(), &storage))) {
+                    return; // do not draw the path
+                }
+            }
+            // draw the path
+
+        @param orig     geometry modified by SkPaint when drawn
+        @param storage  computed bounds of geometry; may not be nullptr
+        @return         fast computed bounds
+    */
+    const SkRect& computeFastBounds(const SkRect& orig, SkRect* storage) const {
+        // Things like stroking, etc... will do math on the bounds rect, assuming that it's sorted.
+        SkASSERT(orig.isSorted());
+        SkPaint::Style style = this->getStyle();
+        // ultra fast-case: filling with no effects that affect geometry
+        if (kFill_Style == style) {
+            uintptr_t effects = reinterpret_cast<uintptr_t>(this->getLooper());
+            effects |= reinterpret_cast<uintptr_t>(this->getMaskFilter());
+            effects |= reinterpret_cast<uintptr_t>(this->getPathEffect());
+            effects |= reinterpret_cast<uintptr_t>(this->getImageFilter());
+            if (!effects) {
+                return orig;
+            }
+        }
+
+        return this->doComputeFastBounds(orig, storage, style);
+    }
+
+    /**     (to be made private)
+
+        @param orig     geometry modified by SkPaint when drawn
+        @param storage  computed bounds of geometry
+        @return         fast computed bounds
+    */
+    const SkRect& computeFastStrokeBounds(const SkRect& orig,
+                                          SkRect* storage) const {
+        return this->doComputeFastBounds(orig, storage, kStroke_Style);
+    }
+
+    /**     (to be made private)
+        Computes the bounds, overriding the SkPaint SkPaint::Style. This can be used to
+        account for additional width required by stroking orig, without
+        altering SkPaint::Style set to fill.
+
+        @param orig     geometry modified by SkPaint when drawn
+        @param storage  computed bounds of geometry
+        @param style    overrides SkPaint::Style
+        @return         fast computed bounds
+    */
+    const SkRect& doComputeFastBounds(const SkRect& orig, SkRect* storage,
+                                      Style style) const;
+
+private:
+    friend class SkGlyphRun;
+    friend class SkGlyphRunBuilder;
+    SkPaint(const SkPaint&, const SkRunFont&);
+
+    sk_sp<SkTypeface>     fTypeface;
+    sk_sp<SkPathEffect>   fPathEffect;
+    sk_sp<SkShader>       fShader;
+    sk_sp<SkMaskFilter>   fMaskFilter;
+    sk_sp<SkColorFilter>  fColorFilter;
+    sk_sp<SkDrawLooper>   fDrawLooper;
+    sk_sp<SkImageFilter>  fImageFilter;
+
+    SkScalar        fTextSize;
+    SkScalar        fTextScaleX;
+    SkScalar        fTextSkewX;
+    SkColor4f       fColor4f;
+    SkScalar        fWidth;
+    SkScalar        fMiterLimit;
+    uint32_t        fBlendMode; // just need 5-6 bits
+    union {
+        struct {
+            // all of these bitfields should add up to 32
+            unsigned        fFlags : 16;
+            unsigned        fCapType : 2;
+            unsigned        fJoinType : 2;
+            unsigned        fStyle : 2;
+            unsigned        fTextEncoding : 2;  // 3 values
+            unsigned        fHinting : 2;
+            unsigned        fFilterQuality : 2;
+            //unsigned      fFreeBits : 4;
+        } fBitfields;
+        uint32_t fBitfieldsUInt;
+    };
+
+    SkScalar measure_text(SkGlyphCache*, const char* text, size_t length,
+                          int* count, SkRect* bounds) const;
+
+    /*
+     * The luminance color is used to determine which Gamma Canonical color to map to.  This is
+     * really only used by backends which want to cache glyph masks, and need some way to know if
+     * they need to generate new masks based off a given color.
+     */
+    SkColor computeLuminanceColor() const;
+
+    /*  This is the size we use when we ask for a glyph's path. We then
+     *  post-transform it as we draw to match the request.
+     *  This is done to try to re-use cache entries for the path.
+     *
+     *  This value is somewhat arbitrary. In theory, it could be 1, since
+     *  we store paths as floats. However, we get the path from the font
+     *  scaler, and it may represent its paths as fixed-point (or 26.6),
+     *  so we shouldn't ask for something too big (might overflow 16.16)
+     *  or too small (underflow 26.6).
+     *
+     *  This value could track kMaxSizeForGlyphCache, assuming the above
+     *  constraints, but since we ask for unhinted paths, the two values
+     *  need not match per-se.
+     */
+    static constexpr int kCanonicalTextSizeForPaths  = 64;
+
+    static bool TooBigToUseCache(const SkMatrix& ctm, const SkMatrix& textM, SkScalar maxLimit);
+
+    // Set flags/hinting/textSize up to use for drawing text as paths.
+    // Returns scale factor to restore the original textSize, since will will
+    // have change it to kCanonicalTextSizeForPaths.
+    SkScalar setupForAsPaths();
+
+    static SkScalar MaxCacheSize2(SkScalar maxLimit);
+
+    friend class GrTextBlob;
+    friend class GrTextContext;
+    friend class GrGLPathRendering;
+    friend class GrPathRendering;
+    friend class SkAutoGlyphCacheNoGamma;
+    friend class SkCanonicalizePaint;
+    friend class SkCanvas;
+    friend class SkDraw;
+    friend class SkFont;
+    friend class SkGlyphRunListPainter;
+    friend class SkPaintPriv;
+    friend class SkPDFDevice;
+    friend class SkScalerContext;  // for computeLuminanceColor()
+    friend class SkTextBaseIter;
+    friend class SkTextBlobCacheDiffCanvas;
+};
+
+#endif

+ 1779 - 0
skia/include/core/SkPath.h

@@ -0,0 +1,1779 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkPath.h and docs/SkPath_Reference.bmh
+   on 2018-09-13 13:59:55. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkPath_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkPath_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkPath.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkPath_DEFINED
+#define SkPath_DEFINED
+
+#include "SkMatrix.h"
+#include "../private/SkPathRef.h"
+#include "../private/SkTo.h"
+
+#include <initializer_list>
+
+class SkAutoPathBoundsUpdate;
+class SkData;
+class SkRRect;
+class SkWStream;
+
+/** \class SkPath
+    SkPath contain geometry. SkPath may be empty, or contain one or more verbs that
+    outline a figure. SkPath always starts with a move verb to a Cartesian coordinate,
+    and may be followed by additional verbs that add lines or curves.
+    Adding a close verb makes the geometry into a continuous loop, a closed contour.
+    SkPath may contain any number of contours, each beginning with a move verb.
+
+    SkPath contours may contain only a move verb, or may also contain lines,
+    quadratic beziers, conics, and cubic beziers. SkPath contours may be open or
+    closed.
+
+    When used to draw a filled area, SkPath describes whether the fill is inside or
+    outside the geometry. SkPath also describes the winding rule used to fill
+    overlapping contours.
+
+    Internally, SkPath lazily computes metrics likes bounds and convexity. Call
+    SkPath::updateBoundsCache to make SkPath thread safe.
+*/
+class SK_API SkPath {
+public:
+
+    /** \enum SkPath::Direction
+        Direction describes whether contour is clockwise or counterclockwise.
+        When SkPath contains multiple overlapping contours, Direction together with
+        FillType determines whether overlaps are filled or form holes.
+
+        Direction also determines how contour is measured. For instance, dashing
+        measures along SkPath to determine where to start and stop stroke; Direction
+        will change dashed results as it steps clockwise or counterclockwise.
+
+        Closed contours like SkRect, SkRRect, circle, and oval added with
+        kCW_Direction travel clockwise; the same added with kCCW_Direction
+        travel counterclockwise.
+    */
+    enum Direction : int {
+        kCW_Direction,  //!< contour travels clockwise
+        kCCW_Direction, //!< contour travels counterclockwise
+    };
+
+    /** Constructs an empty SkPath. By default, SkPath has no verbs, no SkPoint, and no weights.
+        SkPath::FillType is set to kWinding_FillType.
+
+        @return  empty SkPath
+    */
+    SkPath();
+
+    /** Constructs a copy of an existing path.
+        Copy constructor makes two paths identical by value. Internally, path and
+        the returned result share pointer values. The underlying verb array, SkPoint array
+        and weights are copied when modified.
+
+        Creating a SkPath copy is very efficient and never allocates memory.
+        SkPath are always copied by value from the interface; the underlying shared
+        pointers are not exposed.
+
+        @param path  SkPath to copy by value
+        @return      copy of SkPath
+    */
+    SkPath(const SkPath& path);
+
+    /** Releases ownership of any shared data and deletes data if SkPath is sole owner.
+    */
+    ~SkPath();
+
+    /** Constructs a copy of an existing path.
+        SkPath assignment makes two paths identical by value. Internally, assignment
+        shares pointer values. The underlying verb array, SkPoint array and weights
+        are copied when modified.
+
+        Copying SkPath by assignment is very efficient and never allocates memory.
+        SkPath are always copied by value from the interface; the underlying shared
+        pointers are not exposed.
+
+        @param path  verb array, SkPoint array, weights, and SkPath::FillType to copy
+        @return      SkPath copied by value
+    */
+    SkPath& operator=(const SkPath& path);
+
+    /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
+        are equivalent.
+
+        @param a  SkPath to compare
+        @param b  SkPath to compare
+        @return   true if SkPath pair are equivalent
+    */
+    friend SK_API bool operator==(const SkPath& a, const SkPath& b);
+
+    /** Compares a and b; returns true if SkPath::FillType, verb array, SkPoint array, and weights
+        are not equivalent.
+
+        @param a  SkPath to compare
+        @param b  SkPath to compare
+        @return   true if SkPath pair are not equivalent
+    */
+    friend bool operator!=(const SkPath& a, const SkPath& b) {
+        return !(a == b);
+    }
+
+    /** Returns true if SkPath contain equal verbs and equal weights.
+        If SkPath contain one or more conics, the weights must match.
+
+        conicTo() may add different verbs depending on conic weight, so it is not
+        trivial to interpolate a pair of SkPath containing conics with different
+        conic weight values.
+
+        @param compare  SkPath to compare
+        @return         true if SkPath verb array and weights are equivalent
+    */
+    bool isInterpolatable(const SkPath& compare) const;
+
+    /** Interpolates between SkPath with SkPoint array of equal size.
+        Copy verb array and weights to out, and set out SkPoint array to a weighted
+        average of this SkPoint array and ending SkPoint array, using the formula:
+        (Path Point * weight) + ending Point * (1 - weight).
+
+        weight is most useful when between zero (ending SkPoint array) and
+        one (this Point_Array); will work with values outside of this
+        range.
+
+        interpolate() returns false and leaves out unchanged if SkPoint array is not
+        the same size as ending SkPoint array. Call isInterpolatable() to check SkPath
+        compatibility prior to calling interpolate().
+
+        @param ending  SkPoint array averaged with this SkPoint array
+        @param weight  contribution of this SkPoint array, and
+                       one minus contribution of ending SkPoint array
+        @param out     SkPath replaced by interpolated averages
+        @return        true if SkPath contain same number of SkPoint
+    */
+    bool interpolate(const SkPath& ending, SkScalar weight, SkPath* out) const;
+
+    /** \enum SkPath::FillType
+        FillType selects the rule used to fill SkPath. SkPath set to kWinding_FillType
+        fills if the sum of contour edges is not zero, where clockwise edges add one, and
+        counterclockwise edges subtract one. SkPath set to kEvenOdd_FillType fills if the
+        number of contour edges is odd. Each FillType has an inverse variant that
+        reverses the rule:
+        kInverseWinding_FillType fills where the sum of contour edges is zero;
+        kInverseEvenOdd_FillType fills where the number of contour edges is even.
+    */
+    enum FillType {
+        kWinding_FillType,        //!< is enclosed by a non-zero sum of contour directions
+        kEvenOdd_FillType,        //!< is enclosed by an odd number of contours
+        kInverseWinding_FillType, //!< is enclosed by a zero sum of contour directions
+        kInverseEvenOdd_FillType, //!< is enclosed by an even number of contours
+    };
+
+    /** Returns FillType, the rule used to fill SkPath. FillType of a new SkPath is
+        kWinding_FillType.
+
+        @return  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,
+                 kInverseEvenOdd_FillType
+    */
+    FillType getFillType() const { return (FillType)fFillType; }
+
+    /** Sets FillType, the rule used to fill SkPath. While there is no check
+        that ft is legal, values outside of FillType are not supported.
+
+        @param ft  one of: kWinding_FillType, kEvenOdd_FillType,  kInverseWinding_FillType,
+                   kInverseEvenOdd_FillType
+    */
+    void setFillType(FillType ft) {
+        fFillType = SkToU8(ft);
+    }
+
+    /** Returns if FillType describes area outside SkPath geometry. The inverse fill area
+        extends indefinitely.
+
+        @return  true if FillType is kInverseWinding_FillType or kInverseEvenOdd_FillType
+    */
+    bool isInverseFillType() const { return IsInverseFillType((FillType)fFillType); }
+
+    /** Replaces FillType with its inverse. The inverse of FillType describes the area
+        unmodified by the original FillType.
+    */
+    void toggleInverseFillType() {
+        fFillType ^= 2;
+    }
+
+    /** \enum SkPath::Convexity
+        SkPath is convex if it contains one contour and contour loops no more than
+        360 degrees, and contour angles all have same Direction. Convex SkPath
+        may have better performance and require fewer resources on GPU surface.
+
+        SkPath is concave when either at least one Direction change is clockwise and
+        another is counterclockwise, or the sum of the changes in Direction is not 360
+        degrees.
+
+        Initially SkPath Convexity is kUnknown_Convexity. SkPath Convexity is computed
+        if needed by destination SkSurface.
+    */
+    enum Convexity : uint8_t {
+        kUnknown_Convexity, //!< indicates Convexity has not been determined
+        kConvex_Convexity,  //!< one contour made of a simple geometry without indentations
+        kConcave_Convexity, //!< more than one contour, or a geometry with indentations
+    };
+
+    /** Computes SkPath::Convexity if required, and returns stored value.
+        SkPath::Convexity is computed if stored value is kUnknown_Convexity,
+        or if SkPath has been altered since SkPath::Convexity was computed or set.
+
+        @return  computed or stored SkPath::Convexity
+    */
+    Convexity getConvexity() const {
+        for (Convexity convexity = fConvexity.load(); kUnknown_Convexity != convexity; ) {
+            return convexity;
+        }
+        return this->internalGetConvexity();
+    }
+
+    /** Returns last computed SkPath::Convexity, or kUnknown_Convexity if
+        SkPath has been altered since SkPath::Convexity was computed or set.
+
+        @return  stored SkPath::Convexity
+    */
+    Convexity getConvexityOrUnknown() const { return (Convexity)fConvexity; }
+
+    /** Stores convexity so that it is later returned by getConvexity() or getConvexityOrUnknown().
+        convexity may differ from getConvexity(), although setting an incorrect value may
+        cause incorrect or inefficient drawing.
+
+        If convexity is kUnknown_Convexity: getConvexity() will
+        compute SkPath::Convexity, and getConvexityOrUnknown() will return kUnknown_Convexity.
+
+        If convexity is kConvex_Convexity or kConcave_Convexity, getConvexity()
+        and getConvexityOrUnknown() will return convexity until the path is
+        altered.
+
+        @param convexity  one of: kUnknown_Convexity, kConvex_Convexity, or kConcave_Convexity
+    */
+    void setConvexity(Convexity convexity);
+
+    /** Computes SkPath::Convexity if required, and returns true if value is kConvex_Convexity.
+        If setConvexity() was called with kConvex_Convexity or kConcave_Convexity, and
+        the path has not been altered, SkPath::Convexity is not recomputed.
+
+        @return  true if SkPath::Convexity stored or computed is kConvex_Convexity
+    */
+    bool isConvex() const {
+        return kConvex_Convexity == this->getConvexity();
+    }
+
+    /** Returns true if this path is recognized as an oval or circle.
+
+        bounds receives bounds of oval.
+
+        bounds is unmodified if oval is not found.
+
+        @param bounds  storage for bounding SkRect of oval; may be nullptr
+        @return        true if SkPath is recognized as an oval or circle
+    */
+    bool isOval(SkRect* bounds) const;
+
+    /** Returns true if path is representable as SkRRect.
+        Returns false if path is representable as oval, circle, or SkRect.
+
+        rrect receives bounds of SkRRect.
+
+        rrect is unmodified if SkRRect is not found.
+
+        @param rrect  storage for bounding SkRect of SkRRect; may be nullptr
+        @return       true if SkPath contains only SkRRect
+    */
+    bool isRRect(SkRRect* rrect) const;
+
+    /** Sets SkPath to its initial state.
+        Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
+        Internal storage associated with SkPath is released.
+
+        @return  reference to SkPath
+    */
+    SkPath& reset();
+
+    /** Sets SkPath to its initial state, preserving internal storage.
+        Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.
+        Internal storage associated with SkPath is retained.
+
+        Use rewind() instead of reset() if SkPath storage will be reused and performance
+        is critical.
+
+        @return  reference to SkPath
+    */
+    SkPath& rewind();
+
+    /** Returns if SkPath is empty.
+        Empty SkPath may have FillType but has no SkPoint, SkPath::Verb, or conic weight.
+        SkPath() constructs empty SkPath; reset() and rewind() make SkPath empty.
+
+        @return  true if the path contains no SkPath::Verb array
+    */
+    bool isEmpty() const {
+        SkDEBUGCODE(this->validate();)
+        return 0 == fPathRef->countVerbs();
+    }
+
+    /** Returns if contour is closed.
+        Contour is closed if SkPath SkPath::Verb array was last modified by close(). When stroked,
+        closed contour draws SkPaint::Join instead of SkPaint::Cap at first and last SkPoint.
+
+        @return  true if the last contour ends with a kClose_Verb
+    */
+    bool isLastContourClosed() const;
+
+    /** Returns true for finite SkPoint array values between negative SK_ScalarMax and
+        positive SK_ScalarMax. Returns false for any SkPoint array value of
+        SK_ScalarInfinity, SK_ScalarNegativeInfinity, or SK_ScalarNaN.
+
+        @return  true if all SkPoint values are finite
+    */
+    bool isFinite() const {
+        SkDEBUGCODE(this->validate();)
+        return fPathRef->isFinite();
+    }
+
+    /** Returns true if the path is volatile; it will not be altered or discarded
+        by the caller after it is drawn. SkPath by default have volatile set false, allowing
+        SkSurface to attach a cache of data which speeds repeated drawing. If true, SkSurface
+        may not speed repeated drawing.
+
+        @return  true if caller will alter SkPath after drawing
+    */
+    bool isVolatile() const {
+        return SkToBool(fIsVolatile);
+    }
+
+    /** Specifies whether SkPath is volatile; whether it will be altered or discarded
+        by the caller after it is drawn. SkPath by default have volatile set false, allowing
+        SkBaseDevice to attach a cache of data which speeds repeated drawing.
+
+        Mark temporary paths, discarded or modified after use, as volatile
+        to inform SkBaseDevice that the path need not be cached.
+
+        Mark animating SkPath volatile to improve performance.
+        Mark unchanging SkPath non-volatile to improve repeated rendering.
+
+        raster surface SkPath draws are affected by volatile for some shadows.
+        GPU surface SkPath draws are affected by volatile for some shadows and concave geometries.
+
+        @param isVolatile  true if caller will alter SkPath after drawing
+    */
+    void setIsVolatile(bool isVolatile) {
+        fIsVolatile = isVolatile;
+    }
+
+    /** Tests if line between SkPoint pair is degenerate.
+        Line with no length or that moves a very short distance is degenerate; it is
+        treated as a point.
+
+        exact changes the equality test. If true, returns true only if p1 equals p2.
+        If false, returns true if p1 equals or nearly equals p2.
+
+        @param p1     line start point
+        @param p2     line end point
+        @param exact  if false, allow nearly equals
+        @return       true if line is degenerate; its length is effectively zero
+    */
+    static bool IsLineDegenerate(const SkPoint& p1, const SkPoint& p2, bool exact);
+
+    /** Tests if quad is degenerate.
+        Quad with no length or that moves a very short distance is degenerate; it is
+        treated as a point.
+
+        @param p1     quad start point
+        @param p2     quad control point
+        @param p3     quad end point
+        @param exact  if true, returns true only if p1, p2, and p3 are equal;
+                      if false, returns true if p1, p2, and p3 are equal or nearly equal
+        @return       true if quad is degenerate; its length is effectively zero
+    */
+    static bool IsQuadDegenerate(const SkPoint& p1, const SkPoint& p2,
+                                 const SkPoint& p3, bool exact);
+
+    /** Tests if cubic is degenerate.
+        Cubic with no length or that moves a very short distance is degenerate; it is
+        treated as a point.
+
+        @param p1     cubic start point
+        @param p2     cubic control point 1
+        @param p3     cubic control point 2
+        @param p4     cubic end point
+        @param exact  if true, returns true only if p1, p2, p3, and p4 are equal;
+                      if false, returns true if p1, p2, p3, and p4 are equal or nearly equal
+        @return       true if cubic is degenerate; its length is effectively zero
+    */
+    static bool IsCubicDegenerate(const SkPoint& p1, const SkPoint& p2,
+                                  const SkPoint& p3, const SkPoint& p4, bool exact);
+
+    /** Returns true if SkPath contains only one line;
+        SkPath::Verb array has two entries: kMove_Verb, kLine_Verb.
+        If SkPath contains one line and line is not nullptr, line is set to
+        line start point and line end point.
+        Returns false if SkPath is not one line; line is unaltered.
+
+        @param line  storage for line. May be nullptr
+        @return      true if SkPath contains exactly one line
+    */
+    bool isLine(SkPoint line[2]) const;
+
+    /** Returns the number of points in SkPath.
+        SkPoint count is initially zero.
+
+        @return  SkPath SkPoint array length
+    */
+    int countPoints() const;
+
+    /** Returns SkPoint at index in SkPoint array. Valid range for index is
+        0 to countPoints() - 1.
+        Returns (0, 0) if index is out of range.
+
+        @param index  SkPoint array element selector
+        @return       SkPoint array value or (0, 0)
+    */
+    SkPoint getPoint(int index) const;
+
+    /** Returns number of points in SkPath. Up to max points are copied.
+        points may be nullptr; then, max must be zero.
+        If max is greater than number of points, excess points storage is unaltered.
+
+        @param points  storage for SkPath SkPoint array. May be nullptr
+        @param max     maximum to copy; must be greater than or equal to zero
+        @return        SkPath SkPoint array length
+    */
+    int getPoints(SkPoint points[], int max) const;
+
+    /** Returns the number of verbs: kMove_Verb, kLine_Verb, kQuad_Verb, kConic_Verb,
+        kCubic_Verb, and kClose_Verb; added to SkPath.
+
+        @return  length of verb array
+    */
+    int countVerbs() const;
+
+    /** Returns the number of verbs in the path. Up to max verbs are copied. The
+        verbs are copied as one byte per verb.
+
+        @param verbs  storage for verbs, may be nullptr
+        @param max    maximum number to copy into verbs
+        @return       the actual number of verbs in the path
+    */
+    int getVerbs(uint8_t verbs[], int max) const;
+
+    /** Exchanges the verb array, SkPoint array, weights, and SkPath::FillType with other.
+        Cached state is also exchanged. swap() internally exchanges pointers, so
+        it is lightweight and does not allocate memory.
+
+        swap() usage has largely been replaced by operator=(const SkPath& path).
+        SkPath do not copy their content on assignment until they are written to,
+        making assignment as efficient as swap().
+
+        @param other  SkPath exchanged by value
+    */
+    void swap(SkPath& other);
+
+    /** Returns minimum and maximum axes values of SkPoint array.
+        Returns (0, 0, 0, 0) if SkPath contains no points. Returned bounds width and height may
+        be larger or smaller than area affected when SkPath is drawn.
+
+        SkRect returned includes all SkPoint added to SkPath, including SkPoint associated with
+        kMove_Verb that define empty contours.
+
+        @return  bounds of all SkPoint in SkPoint array
+    */
+    const SkRect& getBounds() const {
+        return fPathRef->getBounds();
+    }
+
+    /** Updates internal bounds so that subsequent calls to getBounds() are instantaneous.
+        Unaltered copies of SkPath may also access cached bounds through getBounds().
+
+        For now, identical to calling getBounds() and ignoring the returned value.
+
+        Call to prepare SkPath subsequently drawn from multiple threads,
+        to avoid a race condition where each draw separately computes the bounds.
+    */
+    void updateBoundsCache() const {
+        // for now, just calling getBounds() is sufficient
+        this->getBounds();
+    }
+
+    /** Returns minimum and maximum axes values of the lines and curves in SkPath.
+        Returns (0, 0, 0, 0) if SkPath contains no points.
+        Returned bounds width and height may be larger or smaller than area affected
+        when SkPath is drawn.
+
+        Includes SkPoint associated with kMove_Verb that define empty
+        contours.
+
+        Behaves identically to getBounds() when SkPath contains
+        only lines. If SkPath contains curves, computed bounds includes
+        the maximum extent of the quad, conic, or cubic; is slower than getBounds();
+        and unlike getBounds(), does not cache the result.
+
+        @return  tight bounds of curves in SkPath
+    */
+    SkRect computeTightBounds() const;
+
+    /** Returns true if rect is contained by SkPath.
+        May return false when rect is contained by SkPath.
+
+        For now, only returns true if SkPath has one contour and is convex.
+        rect may share points and edges with SkPath and be contained.
+        Returns true if rect is empty, that is, it has zero width or height; and
+        the SkPoint or line described by rect is contained by SkPath.
+
+        @param rect  SkRect, line, or SkPoint checked for containment
+        @return      true if rect is contained
+    */
+    bool conservativelyContainsRect(const SkRect& rect) const;
+
+    /** Grows SkPath verb array and SkPoint array to contain extraPtCount additional SkPoint.
+        May improve performance and use less memory by
+        reducing the number and size of allocations when creating SkPath.
+
+        @param extraPtCount  number of additional SkPoint to allocate
+    */
+    void incReserve(int extraPtCount);
+
+    /** Shrinks SkPath verb array and SkPoint array storage to discard unused capacity.
+        May reduce the heap overhead for SkPath known to be fully constructed.
+    */
+    void shrinkToFit();
+
+    /** Adds beginning of contour at SkPoint (x, y).
+
+        @param x  x-axis value of contour start
+        @param y  y-axis value of contour start
+        @return   reference to SkPath
+    */
+    SkPath& moveTo(SkScalar x, SkScalar y);
+
+    /** Adds beginning of contour at SkPoint p.
+
+        @param p  contour start
+        @return   reference to SkPath
+    */
+    SkPath& moveTo(const SkPoint& p) {
+        return this->moveTo(p.fX, p.fY);
+    }
+
+    /** Adds beginning of contour relative to last point.
+        If SkPath is empty, starts contour at (dx, dy).
+        Otherwise, start contour at last point offset by (dx, dy).
+        Function name stands for "relative move to".
+
+        @param dx  offset from last point to contour start on x-axis
+        @param dy  offset from last point to contour start on y-axis
+        @return    reference to SkPath
+    */
+    SkPath& rMoveTo(SkScalar dx, SkScalar dy);
+
+    /** Adds line from last point to (x, y). If SkPath is empty, or last SkPath::Verb is
+        kClose_Verb, last point is set to (0, 0) before adding line.
+
+        lineTo() appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+        lineTo() then appends kLine_Verb to verb array and (x, y) to SkPoint array.
+
+        @param x  end of added line on x-axis
+        @param y  end of added line on y-axis
+        @return   reference to SkPath
+    */
+    SkPath& lineTo(SkScalar x, SkScalar y);
+
+    /** Adds line from last point to SkPoint p. If SkPath is empty, or last SkPath::Verb is
+        kClose_Verb, last point is set to (0, 0) before adding line.
+
+        lineTo() first appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+        lineTo() then appends kLine_Verb to verb array and SkPoint p to SkPoint array.
+
+        @param p  end SkPoint of added line
+        @return   reference to SkPath
+    */
+    SkPath& lineTo(const SkPoint& p) {
+        return this->lineTo(p.fX, p.fY);
+    }
+
+    /** Adds line from last point to vector (dx, dy). If SkPath is empty, or last SkPath::Verb is
+        kClose_Verb, last point is set to (0, 0) before adding line.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+        then appends kLine_Verb to verb array and line end to SkPoint array.
+        Line end is last point plus vector (dx, dy).
+        Function name stands for "relative line to".
+
+        @param dx  offset from last point to line end on x-axis
+        @param dy  offset from last point to line end on y-axis
+        @return    reference to SkPath
+    */
+    SkPath& rLineTo(SkScalar dx, SkScalar dy);
+
+    /** Adds quad from last point towards (x1, y1), to (x2, y2).
+        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+        before adding quad.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+        then appends kQuad_Verb to verb array; and (x1, y1), (x2, y2)
+        to SkPoint array.
+
+        @param x1  control SkPoint of quad on x-axis
+        @param y1  control SkPoint of quad on y-axis
+        @param x2  end SkPoint of quad on x-axis
+        @param y2  end SkPoint of quad on y-axis
+        @return    reference to SkPath
+    */
+    SkPath& quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2);
+
+    /** Adds quad from last point towards SkPoint p1, to SkPoint p2.
+        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+        before adding quad.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+        then appends kQuad_Verb to verb array; and SkPoint p1, p2
+        to SkPoint array.
+
+        @param p1  control SkPoint of added quad
+        @param p2  end SkPoint of added quad
+        @return    reference to SkPath
+    */
+    SkPath& quadTo(const SkPoint& p1, const SkPoint& p2) {
+        return this->quadTo(p1.fX, p1.fY, p2.fX, p2.fY);
+    }
+
+    /** Adds quad from last point towards vector (dx1, dy1), to vector (dx2, dy2).
+        If SkPath is empty, or last SkPath::Verb
+        is kClose_Verb, last point is set to (0, 0) before adding quad.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+        if needed; then appends kQuad_Verb to verb array; and appends quad
+        control and quad end to SkPoint array.
+        Quad control is last point plus vector (dx1, dy1).
+        Quad end is last point plus vector (dx2, dy2).
+        Function name stands for "relative quad to".
+
+        @param dx1  offset from last point to quad control on x-axis
+        @param dy1  offset from last point to quad control on y-axis
+        @param dx2  offset from last point to quad end on x-axis
+        @param dy2  offset from last point to quad end on y-axis
+        @return     reference to SkPath
+    */
+    SkPath& rQuadTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2);
+
+    /** Adds conic from last point towards (x1, y1), to (x2, y2), weighted by w.
+        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+        before adding conic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+
+        If w is finite and not one, appends kConic_Verb to verb array;
+        and (x1, y1), (x2, y2) to SkPoint array; and w to conic weights.
+
+        If w is one, appends kQuad_Verb to verb array, and
+        (x1, y1), (x2, y2) to SkPoint array.
+
+        If w is not finite, appends kLine_Verb twice to verb array, and
+        (x1, y1), (x2, y2) to SkPoint array.
+
+        @param x1  control SkPoint of conic on x-axis
+        @param y1  control SkPoint of conic on y-axis
+        @param x2  end SkPoint of conic on x-axis
+        @param y2  end SkPoint of conic on y-axis
+        @param w   weight of added conic
+        @return    reference to SkPath
+    */
+    SkPath& conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                    SkScalar w);
+
+    /** Adds conic from last point towards SkPoint p1, to SkPoint p2, weighted by w.
+        If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to (0, 0)
+        before adding conic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed.
+
+        If w is finite and not one, appends kConic_Verb to verb array;
+        and SkPoint p1, p2 to SkPoint array; and w to conic weights.
+
+        If w is one, appends kQuad_Verb to verb array, and SkPoint p1, p2
+        to SkPoint array.
+
+        If w is not finite, appends kLine_Verb twice to verb array, and
+        SkPoint p1, p2 to SkPoint array.
+
+        @param p1  control SkPoint of added conic
+        @param p2  end SkPoint of added conic
+        @param w   weight of added conic
+        @return    reference to SkPath
+    */
+    SkPath& conicTo(const SkPoint& p1, const SkPoint& p2, SkScalar w) {
+        return this->conicTo(p1.fX, p1.fY, p2.fX, p2.fY, w);
+    }
+
+    /** Adds conic from last point towards vector (dx1, dy1), to vector (dx2, dy2),
+        weighted by w. If SkPath is empty, or last SkPath::Verb
+        is kClose_Verb, last point is set to (0, 0) before adding conic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+        if needed.
+
+        If w is finite and not one, next appends kConic_Verb to verb array,
+        and w is recorded as conic weight; otherwise, if w is one, appends
+        kQuad_Verb to verb array; or if w is not finite, appends kLine_Verb
+        twice to verb array.
+
+        In all cases appends SkPoint control and end to SkPoint array.
+        control is last point plus vector (dx1, dy1).
+        end is last point plus vector (dx2, dy2).
+
+        Function name stands for "relative conic to".
+
+        @param dx1  offset from last point to conic control on x-axis
+        @param dy1  offset from last point to conic control on y-axis
+        @param dx2  offset from last point to conic end on x-axis
+        @param dy2  offset from last point to conic end on y-axis
+        @param w    weight of added conic
+        @return     reference to SkPath
+    */
+    SkPath& rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                     SkScalar w);
+
+    /** Adds cubic from last point towards (x1, y1), then towards (x2, y2), ending at
+        (x3, y3). If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
+        (0, 0) before adding cubic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+        then appends kCubic_Verb to verb array; and (x1, y1), (x2, y2), (x3, y3)
+        to SkPoint array.
+
+        @param x1  first control SkPoint of cubic on x-axis
+        @param y1  first control SkPoint of cubic on y-axis
+        @param x2  second control SkPoint of cubic on x-axis
+        @param y2  second control SkPoint of cubic on y-axis
+        @param x3  end SkPoint of cubic on x-axis
+        @param y3  end SkPoint of cubic on y-axis
+        @return    reference to SkPath
+    */
+    SkPath& cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
+                    SkScalar x3, SkScalar y3);
+
+    /** Adds cubic from last point towards SkPoint p1, then towards SkPoint p2, ending at
+        SkPoint p3. If SkPath is empty, or last SkPath::Verb is kClose_Verb, last point is set to
+        (0, 0) before adding cubic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array, if needed;
+        then appends kCubic_Verb to verb array; and SkPoint p1, p2, p3
+        to SkPoint array.
+
+        @param p1  first control SkPoint of cubic
+        @param p2  second control SkPoint of cubic
+        @param p3  end SkPoint of cubic
+        @return    reference to SkPath
+    */
+    SkPath& cubicTo(const SkPoint& p1, const SkPoint& p2, const SkPoint& p3) {
+        return this->cubicTo(p1.fX, p1.fY, p2.fX, p2.fY, p3.fX, p3.fY);
+    }
+
+    /** Adds cubic from last point towards vector (dx1, dy1), then towards
+        vector (dx2, dy2), to vector (dx3, dy3).
+        If SkPath is empty, or last SkPath::Verb
+        is kClose_Verb, last point is set to (0, 0) before adding cubic.
+
+        Appends kMove_Verb to verb array and (0, 0) to SkPoint array,
+        if needed; then appends kCubic_Verb to verb array; and appends cubic
+        control and cubic end to SkPoint array.
+        Cubic control is last point plus vector (dx1, dy1).
+        Cubic end is last point plus vector (dx2, dy2).
+        Function name stands for "relative cubic to".
+
+        @param dx1  offset from last point to first cubic control on x-axis
+        @param dy1  offset from last point to first cubic control on y-axis
+        @param dx2  offset from last point to second cubic control on x-axis
+        @param dy2  offset from last point to second cubic control on y-axis
+        @param dx3  offset from last point to cubic end on x-axis
+        @param dy3  offset from last point to cubic end on y-axis
+        @return    reference to SkPath
+    */
+    SkPath& rCubicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
+                     SkScalar dx3, SkScalar dy3);
+
+    /** Appends arc to SkPath. Arc added is part of ellipse
+        bounded by oval, from startAngle through sweepAngle. Both startAngle and
+        sweepAngle are measured in degrees, where zero degrees is aligned with the
+        positive x-axis, and positive sweeps extends arc clockwise.
+
+        arcTo() adds line connecting SkPath last SkPoint to initial arc SkPoint if forceMoveTo
+        is false and SkPath is not empty. Otherwise, added contour begins with first point
+        of arc. Angles greater than -360 and less than 360 are treated modulo 360.
+
+        @param oval         bounds of ellipse containing arc
+        @param startAngle   starting angle of arc in degrees
+        @param sweepAngle   sweep, in degrees. Positive is clockwise; treated modulo 360
+        @param forceMoveTo  true to start a new contour with arc
+        @return             reference to SkPath
+    */
+    SkPath& arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, bool forceMoveTo);
+
+    /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
+        weighted to describe part of circle. Arc is contained by tangent from
+        last SkPath point to (x1, y1), and tangent from (x1, y1) to (x2, y2). Arc
+        is part of circle sized to radius, positioned so it touches both tangent lines.
+
+        If last Path Point does not start Arc, arcTo appends connecting Line to Path.
+        The length of Vector from (x1, y1) to (x2, y2) does not affect Arc.
+
+        Arc sweep is always less than 180 degrees. If radius is zero, or if
+        tangents are nearly parallel, arcTo appends Line from last Path Point to (x1, y1).
+
+        arcTo appends at most one Line and one conic.
+        arcTo implements the functionality of PostScript arct and HTML Canvas arcTo.
+
+        @param x1      x-axis value common to pair of tangents
+        @param y1      y-axis value common to pair of tangents
+        @param x2      x-axis value end of second tangent
+        @param y2      y-axis value end of second tangent
+        @param radius  distance from arc to circle center
+        @return        reference to SkPath
+    */
+    SkPath& arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar radius);
+
+    /** Appends arc to SkPath, after appending line if needed. Arc is implemented by conic
+        weighted to describe part of circle. Arc is contained by tangent from
+        last SkPath point to p1, and tangent from p1 to p2. Arc
+        is part of circle sized to radius, positioned so it touches both tangent lines.
+
+        If last SkPath SkPoint does not start arc, arcTo() appends connecting line to SkPath.
+        The length of vector from p1 to p2 does not affect arc.
+
+        Arc sweep is always less than 180 degrees. If radius is zero, or if
+        tangents are nearly parallel, arcTo() appends line from last SkPath SkPoint to p1.
+
+        arcTo() appends at most one line and one conic.
+        arcTo() implements the functionality of PostScript arct and HTML Canvas arcTo.
+
+        @param p1      SkPoint common to pair of tangents
+        @param p2      end of second tangent
+        @param radius  distance from arc to circle center
+        @return        reference to SkPath
+    */
+    SkPath& arcTo(const SkPoint p1, const SkPoint p2, SkScalar radius) {
+        return this->arcTo(p1.fX, p1.fY, p2.fX, p2.fY, radius);
+    }
+
+    /** \enum SkPath::ArcSize
+        Four oval parts with radii (rx, ry) start at last SkPath SkPoint and ends at (x, y).
+        ArcSize and Direction select one of the four oval parts.
+    */
+    enum ArcSize {
+        kSmall_ArcSize, //!< smaller of arc pair
+        kLarge_ArcSize, //!< larger of arc pair
+    };
+
+    /** Appends arc to SkPath. Arc is implemented by one or more conics weighted to
+        describe part of oval with radii (rx, ry) rotated by xAxisRotate degrees. Arc
+        curves from last SkPath SkPoint to (x, y), choosing one of four possible routes:
+        clockwise or counterclockwise, and smaller or larger.
+
+        Arc sweep is always less than 360 degrees. arcTo() appends line to (x, y) if
+        either radii are zero, or if last SkPath SkPoint equals (x, y). arcTo() scales radii
+        (rx, ry) to fit last SkPath SkPoint and (x, y) if both are greater than zero but
+        too small.
+
+        arcTo() appends up to four conic curves.
+        arcTo() implements the functionality of SVG arc, although SVG sweep-flag value
+        is opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise,
+        while kCW_Direction cast to int is zero.
+
+        @param rx           radius on x-axis before x-axis rotation
+        @param ry           radius on y-axis before x-axis rotation
+        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
+        @param largeArc     chooses smaller or larger arc
+        @param sweep        chooses clockwise or counterclockwise arc
+        @param x            end of arc
+        @param y            end of arc
+        @return             reference to SkPath
+    */
+    SkPath& arcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+                  Direction sweep, SkScalar x, SkScalar y);
+
+    /** Appends arc to SkPath. Arc is implemented by one or more conic weighted to describe
+        part of oval with radii (r.fX, r.fY) rotated by xAxisRotate degrees. Arc curves
+        from last SkPath SkPoint to (xy.fX, xy.fY), choosing one of four possible routes:
+        clockwise or counterclockwise,
+        and smaller or larger.
+
+        Arc sweep is always less than 360 degrees. arcTo() appends line to xy if either
+        radii are zero, or if last SkPath SkPoint equals (xy.fX, xy.fY). arcTo() scales radii r to
+        fit last SkPath SkPoint and xy if both are greater than zero but too small to describe
+        an arc.
+
+        arcTo() appends up to four conic curves.
+        arcTo() implements the functionality of SVG arc, although SVG sweep-flag value is
+        opposite the integer value of sweep; SVG sweep-flag uses 1 for clockwise, while
+        kCW_Direction cast to int is zero.
+
+        @param r            radii on axes before x-axis rotation
+        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
+        @param largeArc     chooses smaller or larger arc
+        @param sweep        chooses clockwise or counterclockwise arc
+        @param xy           end of arc
+        @return             reference to SkPath
+    */
+    SkPath& arcTo(const SkPoint r, SkScalar xAxisRotate, ArcSize largeArc, Direction sweep,
+               const SkPoint xy) {
+        return this->arcTo(r.fX, r.fY, xAxisRotate, largeArc, sweep, xy.fX, xy.fY);
+    }
+
+    /** Appends arc to SkPath, relative to last SkPath SkPoint. Arc is implemented by one or
+        more conic, weighted to describe part of oval with radii (rx, ry) rotated by
+        xAxisRotate degrees. Arc curves from last SkPath SkPoint to relative end SkPoint:
+        (dx, dy), choosing one of four possible routes: clockwise or
+        counterclockwise, and smaller or larger. If SkPath is empty, the start arc SkPoint
+        is (0, 0).
+
+        Arc sweep is always less than 360 degrees. arcTo() appends line to end SkPoint
+        if either radii are zero, or if last SkPath SkPoint equals end SkPoint.
+        arcTo() scales radii (rx, ry) to fit last SkPath SkPoint and end SkPoint if both are
+        greater than zero but too small to describe an arc.
+
+        arcTo() appends up to four conic curves.
+        arcTo() implements the functionality of svg arc, although SVG "sweep-flag" value is
+        opposite the integer value of sweep; SVG "sweep-flag" uses 1 for clockwise, while
+        kCW_Direction cast to int is zero.
+
+        @param rx           radius before x-axis rotation
+        @param ry           radius before x-axis rotation
+        @param xAxisRotate  x-axis rotation in degrees; positive values are clockwise
+        @param largeArc     chooses smaller or larger arc
+        @param sweep        chooses clockwise or counterclockwise arc
+        @param dx           x-axis offset end of arc from last SkPath SkPoint
+        @param dy           y-axis offset end of arc from last SkPath SkPoint
+        @return             reference to SkPath
+    */
+    SkPath& rArcTo(SkScalar rx, SkScalar ry, SkScalar xAxisRotate, ArcSize largeArc,
+                   Direction sweep, SkScalar dx, SkScalar dy);
+
+    /** Appends kClose_Verb to SkPath. A closed contour connects the first and last SkPoint
+        with line, forming a continuous loop. Open and closed contour draw the same
+        with SkPaint::kFill_Style. With SkPaint::kStroke_Style, open contour draws
+        SkPaint::Cap at contour start and end; closed contour draws
+        SkPaint::Join at contour start and end.
+
+        close() has no effect if SkPath is empty or last SkPath SkPath::Verb is kClose_Verb.
+
+        @return  reference to SkPath
+    */
+    SkPath& close();
+
+    /** Returns true if fill is inverted and SkPath with fill represents area outside
+        of its geometric bounds.
+
+        @param fill  one of: kWinding_FillType, kEvenOdd_FillType,
+                     kInverseWinding_FillType, kInverseEvenOdd_FillType
+        @return      true if SkPath fills outside its bounds
+    */
+    static bool IsInverseFillType(FillType fill) {
+        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
+        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
+        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
+        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
+        return (fill & 2) != 0;
+    }
+
+    /** Returns equivalent SkPath::FillType representing SkPath fill inside its bounds.
+        .
+
+        @param fill  one of: kWinding_FillType, kEvenOdd_FillType,
+                     kInverseWinding_FillType, kInverseEvenOdd_FillType
+        @return      fill, or kWinding_FillType or kEvenOdd_FillType if fill is inverted
+    */
+    static FillType ConvertToNonInverseFillType(FillType fill) {
+        static_assert(0 == kWinding_FillType, "fill_type_mismatch");
+        static_assert(1 == kEvenOdd_FillType, "fill_type_mismatch");
+        static_assert(2 == kInverseWinding_FillType, "fill_type_mismatch");
+        static_assert(3 == kInverseEvenOdd_FillType, "fill_type_mismatch");
+        return (FillType)(fill & 1);
+    }
+
+    /** Approximates conic with quad array. Conic is constructed from start SkPoint p0,
+        control SkPoint p1, end SkPoint p2, and weight w.
+        Quad array is stored in pts; this storage is supplied by caller.
+        Maximum quad count is 2 to the pow2.
+        Every third point in array shares last SkPoint of previous quad and first SkPoint of
+        next quad. Maximum pts storage size is given by:
+        (1 + 2 * (1 << pow2)) * sizeof(SkPoint).
+
+        Returns quad count used the approximation, which may be smaller
+        than the number requested.
+
+        conic weight determines the amount of influence conic control point has on the curve.
+        w less than one represents an elliptical section. w greater than one represents
+        a hyperbolic section. w equal to one represents a parabolic section.
+
+        Two quad curves are sufficient to approximate an elliptical conic with a sweep
+        of up to 90 degrees; in this case, set pow2 to one.
+
+        @param p0    conic start SkPoint
+        @param p1    conic control SkPoint
+        @param p2    conic end SkPoint
+        @param w     conic weight
+        @param pts   storage for quad array
+        @param pow2  quad count, as power of two, normally 0 to 5 (1 to 32 quad curves)
+        @return      number of quad curves written to pts
+    */
+    static int ConvertConicToQuads(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
+                                   SkScalar w, SkPoint pts[], int pow2);
+
+    /** Returns true if SkPath is equivalent to SkRect when filled.
+        If false: rect, isClosed, and direction are unchanged.
+        If true: rect, isClosed, and direction are written to if not nullptr.
+
+        rect may be smaller than the SkPath bounds. SkPath bounds may include kMove_Verb points
+        that do not alter the area drawn by the returned rect.
+
+        @param rect       storage for bounds of SkRect; may be nullptr
+        @param isClosed   storage set to true if SkPath is closed; may be nullptr
+        @param direction  storage set to SkRect direction; may be nullptr
+        @return           true if SkPath contains SkRect
+    */
+    bool isRect(SkRect* rect, bool* isClosed = nullptr, Direction* direction = nullptr) const;
+
+    /** Returns true if SkPath is equivalent to nested SkRect pair when filled.
+        If false, rect and dirs are unchanged.
+        If true, rect and dirs are written to if not nullptr:
+        setting rect[0] to outer SkRect, and rect[1] to inner SkRect;
+        setting dirs[0] to SkPath::Direction of outer SkRect, and dirs[1] to SkPath::Direction of
+        inner SkRect.
+
+        @param rect  storage for SkRect pair; may be nullptr
+        @param dirs  storage for SkPath::Direction pair; may be nullptr
+        @return      true if SkPath contains nested SkRect pair
+    */
+    bool isNestedFillRects(SkRect rect[2], Direction dirs[2] = nullptr) const;
+
+    /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb,
+        starting with top-left corner of SkRect; followed by top-right, bottom-right,
+        and bottom-left if dir is kCW_Direction; or followed by bottom-left,
+        bottom-right, and top-right if dir is kCCW_Direction.
+
+        @param rect  SkRect to add as a closed contour
+        @param dir   SkPath::Direction to wind added contour
+        @return      reference to SkPath
+    */
+    SkPath& addRect(const SkRect& rect, Direction dir = kCW_Direction);
+
+    /** Adds SkRect to SkPath, appending kMove_Verb, three kLine_Verb, and kClose_Verb.
+        If dir is kCW_Direction, SkRect corners are added clockwise; if dir is
+        kCCW_Direction, SkRect corners are added counterclockwise.
+        start determines the first corner added.
+
+        @param rect   SkRect to add as a closed contour
+        @param dir    SkPath::Direction to wind added contour
+        @param start  initial corner of SkRect to add
+        @return       reference to SkPath
+    */
+    SkPath& addRect(const SkRect& rect, Direction dir, unsigned start);
+
+    /** Adds SkRect (left, top, right, bottom) to SkPath,
+        appending kMove_Verb, three kLine_Verb, and kClose_Verb,
+        starting with top-left corner of SkRect; followed by top-right, bottom-right,
+        and bottom-left if dir is kCW_Direction; or followed by bottom-left,
+        bottom-right, and top-right if dir is kCCW_Direction.
+
+        @param left    smaller x-axis value of SkRect
+        @param top     smaller y-axis value of SkRect
+        @param right   larger x-axis value of SkRect
+        @param bottom  larger y-axis value of SkRect
+        @param dir     SkPath::Direction to wind added contour
+        @return        reference to SkPath
+    */
+    SkPath& addRect(SkScalar left, SkScalar top, SkScalar right, SkScalar bottom,
+                    Direction dir = kCW_Direction);
+
+    /** Adds oval to path, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
+        and half oval height. Oval begins at (oval.fRight, oval.centerY()) and continues
+        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
+
+        @param oval  bounds of ellipse added
+        @param dir   SkPath::Direction to wind ellipse
+        @return      reference to SkPath
+    */
+    SkPath& addOval(const SkRect& oval, Direction dir = kCW_Direction);
+
+    /** Adds oval to SkPath, appending kMove_Verb, four kConic_Verb, and kClose_Verb.
+        Oval is upright ellipse bounded by SkRect oval with radii equal to half oval width
+        and half oval height. Oval begins at start and continues
+        clockwise if dir is kCW_Direction, counterclockwise if dir is kCCW_Direction.
+
+        @param oval   bounds of ellipse added
+        @param dir    SkPath::Direction to wind ellipse
+        @param start  index of initial point of ellipse
+        @return       reference to SkPath
+    */
+    SkPath& addOval(const SkRect& oval, Direction dir, unsigned start);
+
+    /** Adds circle centered at (x, y) of size radius to SkPath, appending kMove_Verb,
+        four kConic_Verb, and kClose_Verb. Circle begins at: (x + radius, y), continuing
+        clockwise if dir is kCW_Direction, and counterclockwise if dir is kCCW_Direction.
+
+        Has no effect if radius is zero or negative.
+
+        @param x       center of circle
+        @param y       center of circle
+        @param radius  distance from center to edge
+        @param dir     SkPath::Direction to wind circle
+        @return        reference to SkPath
+    */
+    SkPath& addCircle(SkScalar x, SkScalar y, SkScalar radius,
+                      Direction dir = kCW_Direction);
+
+    /** Appends arc to SkPath, as the start of new contour. Arc added is part of ellipse
+        bounded by oval, from startAngle through sweepAngle. Both startAngle and
+        sweepAngle are measured in degrees, where zero degrees is aligned with the
+        positive x-axis, and positive sweeps extends arc clockwise.
+
+        If sweepAngle <= -360, or sweepAngle >= 360; and startAngle modulo 90 is nearly
+        zero, append oval instead of arc. Otherwise, sweepAngle values are treated
+        modulo 360, and arc may or may not draw depending on numeric rounding.
+
+        @param oval        bounds of ellipse containing arc
+        @param startAngle  starting angle of arc in degrees
+        @param sweepAngle  sweep, in degrees. Positive is clockwise; treated modulo 360
+        @return            reference to SkPath
+    */
+    SkPath& addArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle);
+
+    /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
+        equal to rect; each corner is 90 degrees of an ellipse with radii (rx, ry). If
+        dir is kCW_Direction, SkRRect starts at top-left of the lower-left corner and
+        winds clockwise. If dir is kCCW_Direction, SkRRect starts at the bottom-left
+        of the upper-left corner and winds counterclockwise.
+
+        If either rx or ry is too large, rx and ry are scaled uniformly until the
+        corners fit. If rx or ry is less than or equal to zero, addRoundRect() appends
+        SkRect rect to SkPath.
+
+        After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
+
+        @param rect  bounds of SkRRect
+        @param rx    x-axis radius of rounded corners on the SkRRect
+        @param ry    y-axis radius of rounded corners on the SkRRect
+        @param dir   SkPath::Direction to wind SkRRect
+        @return      reference to SkPath
+    */
+    SkPath& addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
+                         Direction dir = kCW_Direction);
+
+    /** Appends SkRRect to SkPath, creating a new closed contour. SkRRect has bounds
+        equal to rect; each corner is 90 degrees of an ellipse with radii from the
+        array.
+
+        @param rect   bounds of SkRRect
+        @param radii  array of 8 SkScalar values, a radius pair for each corner
+        @param dir    SkPath::Direction to wind SkRRect
+        @return       reference to SkPath
+    */
+    SkPath& addRoundRect(const SkRect& rect, const SkScalar radii[],
+                         Direction dir = kCW_Direction);
+
+    /** Adds rrect to SkPath, creating a new closed contour. If
+        dir is kCW_Direction, rrect starts at top-left of the lower-left corner and
+        winds clockwise. If dir is kCCW_Direction, rrect starts at the bottom-left
+        of the upper-left corner and winds counterclockwise.
+
+        After appending, SkPath may be empty, or may contain: SkRect, oval, or SkRRect.
+
+        @param rrect  bounds and radii of rounded rectangle
+        @param dir    SkPath::Direction to wind SkRRect
+        @return       reference to SkPath
+    */
+    SkPath& addRRect(const SkRRect& rrect, Direction dir = kCW_Direction);
+
+    /** Adds rrect to SkPath, creating a new closed contour. If dir is kCW_Direction, rrect
+        winds clockwise; if dir is kCCW_Direction, rrect winds counterclockwise.
+        start determines the first point of rrect to add.
+
+        @param rrect  bounds and radii of rounded rectangle
+        @param dir    SkPath::Direction to wind SkRRect
+        @param start  index of initial point of SkRRect
+        @return       reference to SkPath
+    */
+    SkPath& addRRect(const SkRRect& rrect, Direction dir, unsigned start);
+
+    /** Adds contour created from line array, adding (count - 1) line segments.
+        Contour added starts at pts[0], then adds a line for every additional SkPoint
+        in pts array. If close is true, appends kClose_Verb to SkPath, connecting
+        pts[count - 1] and pts[0].
+
+        If count is zero, append kMove_Verb to path.
+        Has no effect if count is less than one.
+
+        @param pts    array of line sharing end and start SkPoint
+        @param count  length of SkPoint array
+        @param close  true to add line connecting contour end and start
+        @return       reference to SkPath
+    */
+    SkPath& addPoly(const SkPoint pts[], int count, bool close);
+
+    /** Adds contour created from list. Contour added starts at list[0], then adds a line
+        for every additional SkPoint in list. If close is true, appends kClose_Verb to SkPath,
+        connecting last and first SkPoint in list.
+
+        If list is empty, append kMove_Verb to path.
+
+        @param list   array of SkPoint
+        @param close  true to add line connecting contour end and start
+        @return       reference to SkPath
+    */
+    SkPath& addPoly(const std::initializer_list<SkPoint>& list, bool close) {
+        return this->addPoly(list.begin(), SkToInt(list.size()), close);
+    }
+
+    /** \enum SkPath::AddPathMode
+        AddPathMode chooses how addPath() appends. Adding one SkPath to another can extend
+        the last contour or start a new contour.
+    */
+    enum AddPathMode {
+        kAppend_AddPathMode, //!< appended to destination unaltered
+        kExtend_AddPathMode, //!< add line if prior contour is not closed
+    };
+
+    /** Appends src to SkPath, offset by (dx, dy).
+
+        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+        added unaltered. If mode is kExtend_AddPathMode, add line before appending
+        verbs, SkPoint, and conic weights.
+
+        @param src   SkPath verbs, SkPoint, and conic weights to add
+        @param dx    offset added to src SkPoint array x-axis coordinates
+        @param dy    offset added to src SkPoint array y-axis coordinates
+        @param mode  kAppend_AddPathMode or kExtend_AddPathMode
+        @return      reference to SkPath
+    */
+    SkPath& addPath(const SkPath& src, SkScalar dx, SkScalar dy,
+                    AddPathMode mode = kAppend_AddPathMode);
+
+    /** Appends src to SkPath.
+
+        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+        added unaltered. If mode is kExtend_AddPathMode, add line before appending
+        verbs, SkPoint, and conic weights.
+
+        @param src   SkPath verbs, SkPoint, and conic weights to add
+        @param mode  kAppend_AddPathMode or kExtend_AddPathMode
+        @return      reference to SkPath
+    */
+    SkPath& addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
+        SkMatrix m;
+        m.reset();
+        return this->addPath(src, m, mode);
+    }
+
+    /** Appends src to SkPath, transformed by matrix. Transformed curves may have different
+        verbs, SkPoint, and conic weights.
+
+        If mode is kAppend_AddPathMode, src verb array, SkPoint array, and conic weights are
+        added unaltered. If mode is kExtend_AddPathMode, add line before appending
+        verbs, SkPoint, and conic weights.
+
+        @param src     SkPath verbs, SkPoint, and conic weights to add
+        @param matrix  transform applied to src
+        @param mode    kAppend_AddPathMode or kExtend_AddPathMode
+        @return        reference to SkPath
+    */
+    SkPath& addPath(const SkPath& src, const SkMatrix& matrix,
+                    AddPathMode mode = kAppend_AddPathMode);
+
+    /** Appends src to SkPath, from back to front.
+        Reversed src always appends a new contour to SkPath.
+
+        @param src  SkPath verbs, SkPoint, and conic weights to add
+        @return     reference to SkPath
+    */
+    SkPath& reverseAddPath(const SkPath& src);
+
+    /** Offsets SkPoint array by (dx, dy). Offset SkPath replaces dst.
+        If dst is nullptr, SkPath is replaced by offset data.
+
+        @param dx   offset added to SkPoint array x-axis coordinates
+        @param dy   offset added to SkPoint array y-axis coordinates
+        @param dst  overwritten, translated copy of SkPath; may be nullptr
+    */
+    void offset(SkScalar dx, SkScalar dy, SkPath* dst) const;
+
+    /** Offsets SkPoint array by (dx, dy). SkPath is replaced by offset data.
+
+        @param dx  offset added to SkPoint array x-axis coordinates
+        @param dy  offset added to SkPoint array y-axis coordinates
+    */
+    void offset(SkScalar dx, SkScalar dy) {
+        this->offset(dx, dy, this);
+    }
+
+    /** Transforms verb array, SkPoint array, and weight by matrix.
+        transform may change verbs and increase their number.
+        Transformed SkPath replaces dst; if dst is nullptr, original data
+        is replaced.
+
+        @param matrix  SkMatrix to apply to SkPath
+        @param dst     overwritten, transformed copy of SkPath; may be nullptr
+    */
+    void transform(const SkMatrix& matrix, SkPath* dst) const;
+
+    /** Transforms verb array, SkPoint array, and weight by matrix.
+        transform may change verbs and increase their number.
+        SkPath is replaced by transformed data.
+
+        @param matrix  SkMatrix to apply to SkPath
+    */
+    void transform(const SkMatrix& matrix) {
+        this->transform(matrix, this);
+    }
+
+    /** Returns last point on SkPath in lastPt. Returns false if SkPoint array is empty,
+        storing (0, 0) if lastPt is not nullptr.
+
+        @param lastPt  storage for final SkPoint in SkPoint array; may be nullptr
+        @return        true if SkPoint array contains one or more SkPoint
+    */
+    bool getLastPt(SkPoint* lastPt) const;
+
+    /** Sets last point to (x, y). If SkPoint array is empty, append kMove_Verb to
+        verb array and append (x, y) to SkPoint array.
+
+        @param x  set x-axis value of last point
+        @param y  set y-axis value of last point
+    */
+    void setLastPt(SkScalar x, SkScalar y);
+
+    /** Sets the last point on the path. If SkPoint array is empty, append kMove_Verb to
+        verb array and append p to SkPoint array.
+
+        @param p  set value of last point
+    */
+    void setLastPt(const SkPoint& p) {
+        this->setLastPt(p.fX, p.fY);
+    }
+
+    /** \enum SkPath::SegmentMask
+        SegmentMask constants correspond to each drawing Verb type in SkPath; for
+        instance, if SkPath only contains lines, only the kLine_SegmentMask bit is set.
+    */
+    enum SegmentMask {
+        kLine_SegmentMask  = 1 << 0, //!< contains one or more lines
+        kQuad_SegmentMask  = 1 << 1, //!< contains one or more quads
+        kConic_SegmentMask = 1 << 2, //!< contains one or more conics
+        kCubic_SegmentMask = 1 << 3, //!< contains one or more cubics
+    };
+
+    /** Returns a mask, where each set bit corresponds to a SegmentMask constant
+        if SkPath contains one or more verbs of that type.
+        Returns zero if SkPath contains no lines, or curves: quads, conics, or cubics.
+
+        getSegmentMasks() returns a cached result; it is very fast.
+
+        @return  SegmentMask bits or zero
+    */
+    uint32_t getSegmentMasks() const { return fPathRef->getSegmentMasks(); }
+
+    /** \enum SkPath::Verb
+        Verb instructs SkPath how to interpret one or more SkPoint and optional conic weight;
+        manage contour, and terminate SkPath.
+    */
+    enum Verb {
+        kMove_Verb,  //!< starts new contour at next SkPoint
+        kLine_Verb,  //!< adds line from last point to next SkPoint
+        kQuad_Verb,  //!< adds quad from last point
+        kConic_Verb, //!< adds conic from last point
+        kCubic_Verb, //!< adds cubic from last point
+        kClose_Verb, //!< closes contour
+        kDone_Verb,  //!< terminates SkPath
+    };
+
+    /** \class SkPath::Iter
+        Iterates through verb array, and associated SkPoint array and conic weight.
+        Provides options to treat open contours as closed, and to ignore
+        degenerate data.
+    */
+    class SK_API Iter {
+    public:
+
+        /** Initializes SkPath::Iter with an empty SkPath. next() on SkPath::Iter returns
+            kDone_Verb.
+            Call setPath to initialize SkPath::Iter at a later time.
+
+            @return  SkPath::Iter of empty SkPath
+        */
+        Iter();
+
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+            open contour. path is not altered.
+
+            @param path        SkPath to iterate
+            @param forceClose  true if open contours generate kClose_Verb
+            @return            SkPath::Iter of path
+        */
+        Iter(const SkPath& path, bool forceClose);
+
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path. If forceClose is true, SkPath::Iter will add kLine_Verb and kClose_Verb after each
+            open contour. path is not altered.
+
+            @param path        SkPath to iterate
+            @param forceClose  true if open contours generate kClose_Verb
+        */
+        void setPath(const SkPath& path, bool forceClose);
+
+        /** Returns next SkPath::Verb in verb array, and advances SkPath::Iter.
+            When verb array is exhausted, returns kDone_Verb.
+
+            Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
+
+            If doConsumeDegenerates is true, skip consecutive kMove_Verb entries, returning
+            only the last in the series; and skip very small lines, quads, and conics; and
+            skip kClose_Verb following kMove_Verb.
+            if doConsumeDegenerates is true and exact is true, only skip lines, quads, and
+            conics with zero lengths.
+
+            @param pts                   storage for SkPoint data describing returned SkPath::Verb
+            @param doConsumeDegenerates  if true, skip degenerate verbs
+            @param exact                 skip zero length curves
+            @return                      next SkPath::Verb from verb array
+        */
+        Verb next(SkPoint pts[4], bool doConsumeDegenerates = true, bool exact = false) {
+            if (doConsumeDegenerates) {
+                this->consumeDegenerateSegments(exact);
+            }
+            return this->doNext(pts);
+        }
+
+        /** Returns conic weight if next() returned kConic_Verb.
+
+            If next() has not been called, or next() did not return kConic_Verb,
+            result is undefined.
+
+            @return  conic weight for conic SkPoint returned by next()
+        */
+        SkScalar conicWeight() const { return *fConicWeights; }
+
+        /** Returns true if last kLine_Verb returned by next() was generated
+            by kClose_Verb. When true, the end point returned by next() is
+            also the start point of contour.
+
+            If next() has not been called, or next() did not return kLine_Verb,
+            result is undefined.
+
+            @return  true if last kLine_Verb was generated by kClose_Verb
+        */
+        bool isCloseLine() const { return SkToBool(fCloseLine); }
+
+        /** Returns true if subsequent calls to next() return kClose_Verb before returning
+            kMove_Verb. if true, contour SkPath::Iter is processing may end with kClose_Verb, or
+            SkPath::Iter may have been initialized with force close set to true.
+
+            @return  true if contour is closed
+        */
+        bool isClosedContour() const;
+
+    private:
+        const SkPoint*  fPts;
+        const uint8_t*  fVerbs;
+        const uint8_t*  fVerbStop;
+        const SkScalar* fConicWeights;
+        SkPoint         fMoveTo;
+        SkPoint         fLastPt;
+        bool            fForceClose;
+        bool            fNeedClose;
+        bool            fCloseLine;
+        enum SegmentState : uint8_t {
+            /** The current contour is empty. Starting processing or have just closed a contour. */
+            kEmptyContour_SegmentState,
+            /** Have seen a move, but nothing else. */
+            kAfterMove_SegmentState,
+            /** Have seen a primitive but not yet closed the path. Also the initial state. */
+            kAfterPrimitive_SegmentState
+        };
+        SegmentState    fSegmentState;
+
+        inline const SkPoint& cons_moveTo();
+        Verb autoClose(SkPoint pts[2]);
+        void consumeDegenerateSegments(bool exact);
+        Verb doNext(SkPoint pts[4]);
+
+    };
+
+    /** \class SkPath::RawIter
+        Iterates through verb array, and associated SkPoint array and conic weight.
+        verb array, SkPoint array, and conic weight are returned unaltered.
+    */
+    class SK_API RawIter {
+    public:
+
+        /** Initializes RawIter with an empty SkPath. next() on RawIter returns kDone_Verb.
+            Call setPath to initialize SkPath::Iter at a later time.
+
+            @return  RawIter of empty SkPath
+        */
+        RawIter() {}
+
+        /** Sets RawIter to return elements of verb array, SkPoint array, and conic weight in path.
+
+            @param path  SkPath to iterate
+            @return      RawIter of path
+        */
+        RawIter(const SkPath& path) {
+            setPath(path);
+        }
+
+        /** Sets SkPath::Iter to return elements of verb array, SkPoint array, and conic weight in
+            path.
+
+            @param path  SkPath to iterate
+        */
+        void setPath(const SkPath& path) {
+            fRawIter.setPathRef(*path.fPathRef.get());
+        }
+
+        /** Returns next SkPath::Verb in verb array, and advances RawIter.
+            When verb array is exhausted, returns kDone_Verb.
+            Zero to four SkPoint are stored in pts, depending on the returned SkPath::Verb.
+
+            @param pts  storage for SkPoint data describing returned SkPath::Verb
+            @return     next SkPath::Verb from verb array
+        */
+        Verb next(SkPoint pts[4]) {
+            return (Verb) fRawIter.next(pts);
+        }
+
+        /** Returns next SkPath::Verb, but does not advance RawIter.
+
+            @return  next SkPath::Verb from verb array
+        */
+        Verb peek() const {
+            return (Verb) fRawIter.peek();
+        }
+
+        /** Returns conic weight if next() returned kConic_Verb.
+
+            If next() has not been called, or next() did not return kConic_Verb,
+            result is undefined.
+
+            @return  conic weight for conic SkPoint returned by next()
+        */
+        SkScalar conicWeight() const {
+            return fRawIter.conicWeight();
+        }
+
+    private:
+        SkPathRef::Iter fRawIter;
+        friend class SkPath;
+
+    };
+
+    /** Returns true if the point (x, y) is contained by SkPath, taking into
+        account FillType.
+
+        @param x  x-axis value of containment test
+        @param y  y-axis value of containment test
+        @return   true if SkPoint is in SkPath
+    */
+    bool contains(SkScalar x, SkScalar y) const;
+
+    /** Writes text representation of SkPath to stream. If stream is nullptr, writes to
+        standard output. Set forceClose to true to get edges used to fill SkPath.
+        Set dumpAsHex true to generate exact binary representations
+        of floating point numbers used in SkPoint array and conic weights.
+
+        @param stream      writable SkWStream receiving SkPath text representation; may be nullptr
+        @param forceClose  true if missing kClose_Verb is output
+        @param dumpAsHex   true if SkScalar values are written as hexadecimal
+    */
+    void dump(SkWStream* stream, bool forceClose, bool dumpAsHex) const;
+
+    /** Writes text representation of SkPath to standard output. The representation may be
+        directly compiled as C++ code. Floating point values are written
+        with limited precision; it may not be possible to reconstruct original SkPath
+        from output.
+    */
+    void dump() const;
+
+    /** Writes text representation of SkPath to standard output. The representation may be
+        directly compiled as C++ code. Floating point values are written
+        in hexadecimal to preserve their exact bit pattern. The output reconstructs the
+        original SkPath.
+
+        Use instead of dump() when submitting
+    */
+    void dumpHex() const;
+
+    /** Writes SkPath to buffer, returning the number of bytes written.
+        Pass nullptr to obtain the storage size.
+
+        Writes SkPath::FillType, verb array, SkPoint array, conic weight, and
+        additionally writes computed information like SkPath::Convexity and bounds.
+
+        Use only be used in concert with readFromMemory();
+        the format used for SkPath in memory is not guaranteed.
+
+        @param buffer  storage for SkPath; may be nullptr
+        @return        size of storage required for SkPath; always a multiple of 4
+    */
+    size_t writeToMemory(void* buffer) const;
+
+    /** Writes SkPath to buffer, returning the buffer written to, wrapped in SkData.
+
+        serialize() writes SkPath::FillType, verb array, SkPoint array, conic weight, and
+        additionally writes computed information like SkPath::Convexity and bounds.
+
+        serialize() should only be used in concert with readFromMemory().
+        The format used for SkPath in memory is not guaranteed.
+
+        @return  SkPath data wrapped in SkData buffer
+    */
+    sk_sp<SkData> serialize() const;
+
+    /** Initializes SkPath from buffer of size length. Returns zero if the buffer is
+        data is inconsistent, or the length is too small.
+
+        Reads SkPath::FillType, verb array, SkPoint array, conic weight, and
+        additionally reads computed information like SkPath::Convexity and bounds.
+
+        Used only in concert with writeToMemory();
+        the format used for SkPath in memory is not guaranteed.
+
+        @param buffer  storage for SkPath
+        @param length  buffer size in bytes; must be multiple of 4
+        @return        number of bytes read, or zero on failure
+    */
+    size_t readFromMemory(const void* buffer, size_t length);
+
+    /** (See Skia bug 1762.)
+        Returns a non-zero, globally unique value. A different value is returned
+        if verb array, SkPoint array, or conic weight changes.
+
+        Setting SkPath::FillType does not change generation identifier.
+
+        Each time the path is modified, a different generation identifier will be returned.
+        SkPath::FillType does affect generation identifier on Android framework.
+
+        @return  non-zero, globally unique value
+    */
+    uint32_t getGenerationID() const;
+
+#ifdef SK_SUPPORT_DIRECT_PATHREF_VALIDATION
+    /** Returns if SkPath data is consistent. Corrupt SkPath data is detected if
+        internal values are out of range or internal storage does not match
+        array dimensions.
+
+        @return  true if SkPath data is consistent
+    */
+    bool isValid() const { return this->isValidImpl() && fPathRef->isValid(); }
+#else
+    /** Deprecated.
+     */
+    bool isValid() const { return this->isValidImpl(); }
+    /** Deprecated.
+     */
+    bool pathRefIsValid() const { return fPathRef->isValid(); }
+#endif
+
+private:
+    sk_sp<SkPathRef>                                     fPathRef;
+    int                                                  fLastMoveToIndex;
+    mutable SkAtomic<Convexity, sk_memory_order_relaxed> fConvexity;       // SkPath::Convexity
+   mutable SkAtomic<uint8_t, sk_memory_order_relaxed> fFirstDirection; // SkPathPriv::FirstDirection
+    uint8_t                                              fFillType    : 2;
+    uint8_t                                              fIsVolatile  : 1;
+    uint8_t                                              fIsBadForDAA : 1;
+
+    /** Resets all fields other than fPathRef to their initial 'empty' values.
+     *  Assumes the caller has already emptied fPathRef.
+     *  On Android increments fGenerationID without reseting it.
+     */
+    void resetFields();
+
+    /** Sets all fields other than fPathRef to the values in 'that'.
+     *  Assumes the caller has already set fPathRef.
+     *  Doesn't change fGenerationID or fSourcePath on Android.
+     */
+    void copyFields(const SkPath& that);
+
+    size_t writeToMemoryAsRRect(void* buffer) const;
+    size_t readAsRRect(const void*, size_t);
+    size_t readFromMemory_LE3(const void*, size_t);
+    size_t readFromMemory_EQ4(const void*, size_t);
+
+    friend class Iter;
+    friend class SkPathPriv;
+    friend class SkPathStroker;
+
+    /*  Append, in reverse order, the first contour of path, ignoring path's
+        last point. If no moveTo() call has been made for this contour, the
+        first point is automatically set to (0,0).
+    */
+    SkPath& reversePathTo(const SkPath&);
+
+    // called before we add points for lineTo, quadTo, cubicTo, checking to see
+    // if we need to inject a leading moveTo first
+    //
+    //  SkPath path; path.lineTo(...);   <--- need a leading moveTo(0, 0)
+    // SkPath path; ... path.close(); path.lineTo(...) <-- need a moveTo(previous moveTo)
+    //
+    inline void injectMoveToIfNeeded();
+
+    inline bool hasOnlyMoveTos() const;
+
+    Convexity internalGetConvexity() const;
+
+    /** Asserts if SkPath data is inconsistent.
+        Debugging check intended for internal use only.
+     */
+    SkDEBUGCODE(void validate() const { SkASSERT(this->isValidImpl()); } )
+    bool isValidImpl() const;
+    SkDEBUGCODE(void validateRef() const { fPathRef->validate(); } )
+
+    bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
+                       bool* isClosed, Direction* direction, SkRect* rect) const;
+
+    // called by stroker to see if all points (in the last contour) are equal and worthy of a cap
+    bool isZeroLengthSincePoint(int startPtIndex) const;
+
+    /** Returns if the path can return a bound at no cost (true) or will have to
+        perform some computation (false).
+     */
+    bool hasComputedBounds() const {
+        SkDEBUGCODE(this->validate();)
+        return fPathRef->hasComputedBounds();
+    }
+
+
+    // 'rect' needs to be sorted
+    void setBounds(const SkRect& rect) {
+        SkPathRef::Editor ed(&fPathRef);
+
+        ed.setBounds(rect);
+    }
+
+    void setPt(int index, SkScalar x, SkScalar y);
+
+    friend class SkAutoPathBoundsUpdate;
+    friend class SkAutoDisableOvalCheck;
+    friend class SkAutoDisableDirectionCheck;
+    friend class SkPathWriter;
+    friend class SkOpBuilder;
+    friend class SkBench_AddPathTest; // perf test reversePathTo
+    friend class PathTest_Private; // unit test reversePathTo
+    friend class ForceIsRRect_Private; // unit test isRRect
+    friend class FuzzPath; // for legacy access to validateRef
+};
+
+#endif

+ 187 - 0
skia/include/core/SkPathEffect.h

@@ -0,0 +1,187 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathEffect_DEFINED
+#define SkPathEffect_DEFINED
+
+#include "SkFlattenable.h"
+#include "SkPath.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+
+class SkPath;
+class SkStrokeRec;
+
+/** \class SkPathEffect
+
+    SkPathEffect is the base class for objects in the SkPaint that affect
+    the geometry of a drawing primitive before it is transformed by the
+    canvas' matrix and drawn.
+
+    Dashing is implemented as a subclass of SkPathEffect.
+*/
+class SK_API SkPathEffect : public SkFlattenable {
+public:
+    /**
+     *  Returns a patheffect that apples each effect (first and second) to the original path,
+     *  and returns a path with the sum of these.
+     *
+     *  result = first(path) + second(path)
+     *
+     */
+    static sk_sp<SkPathEffect> MakeSum(sk_sp<SkPathEffect> first, sk_sp<SkPathEffect> second);
+
+    /**
+     *  Returns a patheffect that applies the inner effect to the path, and then applies the
+     *  outer effect to the result of the inner's.
+     *
+     *  result = outer(inner(path))
+     */
+    static sk_sp<SkPathEffect> MakeCompose(sk_sp<SkPathEffect> outer, sk_sp<SkPathEffect> inner);
+
+    /**
+     *  Given a src path (input) and a stroke-rec (input and output), apply
+     *  this effect to the src path, returning the new path in dst, and return
+     *  true. If this effect cannot be applied, return false and ignore dst
+     *  and stroke-rec.
+     *
+     *  The stroke-rec specifies the initial request for stroking (if any).
+     *  The effect can treat this as input only, or it can choose to change
+     *  the rec as well. For example, the effect can decide to change the
+     *  stroke's width or join, or the effect can change the rec from stroke
+     *  to fill (or fill to stroke) in addition to returning a new (dst) path.
+     *
+     *  If this method returns true, the caller will apply (as needed) the
+     *  resulting stroke-rec to dst and then draw.
+     */
+    bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, const SkRect* cullR) const;
+
+    /**
+     *  Compute a conservative bounds for its effect, given the src bounds.
+     *  The baseline implementation just assigns src to dst.
+     */
+    void computeFastBounds(SkRect* dst, const SkRect& src) const;
+
+    /** \class PointData
+
+        PointData aggregates all the information needed to draw the point
+        primitives returned by an 'asPoints' call.
+    */
+    class PointData {
+    public:
+        PointData()
+            : fFlags(0)
+            , fPoints(nullptr)
+            , fNumPoints(0) {
+            fSize.set(SK_Scalar1, SK_Scalar1);
+            // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets
+            // the kUseClip flag
+        }
+        ~PointData() {
+            delete [] fPoints;
+        }
+
+        // TODO: consider using passed-in flags to limit the work asPoints does.
+        // For example, a kNoPath flag could indicate don't bother generating
+        // stamped solutions.
+
+        // Currently none of these flags are supported.
+        enum PointFlags {
+            kCircles_PointFlag            = 0x01,   // draw points as circles (instead of rects)
+            kUsePath_PointFlag            = 0x02,   // draw points as stamps of the returned path
+            kUseClip_PointFlag            = 0x04,   // apply 'fClipRect' before drawing the points
+        };
+
+        uint32_t           fFlags;      // flags that impact the drawing of the points
+        SkPoint*           fPoints;     // the center point of each generated point
+        int                fNumPoints;  // number of points in fPoints
+        SkVector           fSize;       // the size to draw the points
+        SkRect             fClipRect;   // clip required to draw the points (if kUseClip is set)
+        SkPath             fPath;       // 'stamp' to be used at each point (if kUsePath is set)
+
+        SkPath             fFirst;      // If not empty, contains geometry for first point
+        SkPath             fLast;       // If not empty, contains geometry for last point
+    };
+
+    /**
+     *  Does applying this path effect to 'src' yield a set of points? If so,
+     *  optionally return the points in 'results'.
+     */
+    bool asPoints(PointData* results, const SkPath& src,
+                          const SkStrokeRec&, const SkMatrix&,
+                          const SkRect* cullR) const;
+
+    /**
+     *  If the PathEffect can be represented as a dash pattern, asADash will return kDash_DashType
+     *  and None otherwise. If a non NULL info is passed in, the various DashInfo will be filled
+     *  in if the PathEffect can be a dash pattern. If passed in info has an fCount equal or
+     *  greater to that of the effect, it will memcpy the values of the dash intervals into the
+     *  info. Thus the general approach will be call asADash once with default info to get DashType
+     *  and fCount. If effect can be represented as a dash pattern, allocate space for the intervals
+     *  in info, then call asADash again with the same info and the intervals will get copied in.
+     */
+
+    enum DashType {
+        kNone_DashType, //!< ignores the info parameter
+        kDash_DashType, //!< fills in all of the info parameter
+    };
+
+    struct DashInfo {
+        DashInfo() : fIntervals(nullptr), fCount(0), fPhase(0) {}
+        DashInfo(SkScalar* intervals, int32_t count, SkScalar phase)
+            : fIntervals(intervals), fCount(count), fPhase(phase) {}
+
+        SkScalar*   fIntervals;         //!< Length of on/off intervals for dashed lines
+                                        //   Even values represent ons, and odds offs
+        int32_t     fCount;             //!< Number of intervals in the dash. Should be even number
+        SkScalar    fPhase;             //!< Offset into the dashed interval pattern
+                                        //   mod the sum of all intervals
+    };
+
+    DashType asADash(DashInfo* info) const;
+
+    static void RegisterFlattenables();
+
+    static SkFlattenable::Type GetFlattenableType() {
+        return kSkPathEffect_Type;
+    }
+
+    SkFlattenable::Type getFlattenableType() const override {
+        return kSkPathEffect_Type;
+    }
+
+    static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,
+                                          const SkDeserialProcs* procs = nullptr) {
+        return sk_sp<SkPathEffect>(static_cast<SkPathEffect*>(
+                                  SkFlattenable::Deserialize(
+                                  kSkPathEffect_Type, data, size, procs).release()));
+    }
+
+protected:
+    SkPathEffect() {}
+
+    virtual bool onFilterPath(SkPath*, const SkPath&, SkStrokeRec*, const SkRect*) const = 0;
+    virtual SkRect onComputeFastBounds(const SkRect& src) const {
+        return src;
+    }
+    virtual bool onAsPoints(PointData*, const SkPath&, const SkStrokeRec&, const SkMatrix&,
+                            const SkRect*) const {
+        return false;
+    }
+    virtual DashType onAsADash(DashInfo*) const {
+        return kNone_DashType;
+    }
+
+private:
+    // illegal
+    SkPathEffect(const SkPathEffect&);
+    SkPathEffect& operator=(const SkPathEffect&);
+
+    typedef SkFlattenable INHERITED;
+};
+
+#endif

+ 125 - 0
skia/include/core/SkPathMeasure.h

@@ -0,0 +1,125 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPathMeasure_DEFINED
+#define SkPathMeasure_DEFINED
+
+#include "../private/SkTDArray.h"
+#include "SkPath.h"
+
+struct SkConic;
+
+class SK_API SkPathMeasure : SkNoncopyable {
+public:
+    SkPathMeasure();
+    /** Initialize the pathmeasure with the specified path. The path must remain valid
+        for the lifetime of the measure object, or until setPath() is called with
+        a different path (or null), since the measure object keeps a pointer to the
+        path object (does not copy its data).
+
+        resScale controls the precision of the measure. values > 1 increase the
+        precision (and possible slow down the computation).
+    */
+    SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
+    ~SkPathMeasure();
+
+    /** Reset the pathmeasure with the specified path. The path must remain valid
+        for the lifetime of the measure object, or until setPath() is called with
+        a different path (or null), since the measure object keeps a pointer to the
+        path object (does not copy its data).
+    */
+    void setPath(const SkPath*, bool forceClosed);
+
+    /** Return the total length of the current contour, or 0 if no path
+        is associated (e.g. resetPath(null))
+    */
+    SkScalar getLength();
+
+    /** Pins distance to 0 <= distance <= getLength(), and then computes
+        the corresponding position and tangent.
+        Returns false if there is no path, or a zero-length path was specified, in which case
+        position and tangent are unchanged.
+    */
+    bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
+                                         SkVector* tangent);
+
+    enum MatrixFlags {
+        kGetPosition_MatrixFlag     = 0x01,
+        kGetTangent_MatrixFlag      = 0x02,
+        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
+    };
+
+    /** Pins distance to 0 <= distance <= getLength(), and then computes
+        the corresponding matrix (by calling getPosTan).
+        Returns false if there is no path, or a zero-length path was specified, in which case
+        matrix is unchanged.
+    */
+    bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
+                                  MatrixFlags flags = kGetPosAndTan_MatrixFlag);
+
+    /** Given a start and stop distance, return in dst the intervening segment(s).
+        If the segment is zero-length, return false, else return true.
+        startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
+        then return false (and leave dst untouched).
+        Begin the segment with a moveTo if startWithMoveTo is true
+    */
+    bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo);
+
+    /** Return true if the current contour is closed()
+    */
+    bool isClosed();
+
+    /** Move to the next contour in the path. Return true if one exists, or false if
+        we're done with the path.
+    */
+    bool nextContour();
+
+#ifdef SK_DEBUG
+    void    dump();
+#endif
+
+private:
+    SkPath::Iter    fIter;
+    SkPath          fPath;
+    SkScalar        fTolerance;
+    SkScalar        fLength;            // relative to the current contour
+    unsigned        fFirstPtIndex;      // relative to the current contour
+    bool            fIsClosed;          // relative to the current contour
+    bool            fForceClosed;
+#if defined(IS_FUZZING_WITH_LIBFUZZER)
+    int             fSubdivisionsMax;
+#endif
+    struct Segment {
+        SkScalar    fDistance;  // total distance up to this point
+        unsigned    fPtIndex; // index into the fPts array
+        unsigned    fTValue : 30;
+        unsigned    fType : 2;  // actually the enum SkSegType
+                                // See SkPathMeasurePriv.h
+
+        SkScalar getScalarT() const;
+    };
+    SkTDArray<Segment>  fSegments;
+    SkTDArray<SkPoint>  fPts; // Points used to define the segments
+
+    static const Segment* NextSegment(const Segment*);
+
+    void     buildSegments();
+    SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance,
+                                int mint, int maxt, unsigned ptIndex);
+    SkScalar compute_conic_segs(const SkConic&, SkScalar distance,
+                                int mint, const SkPoint& minPt,
+                                int maxt, const SkPoint& maxPt, unsigned ptIndex);
+    SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance,
+                                int mint, int maxt, unsigned ptIndex);
+    const Segment* distanceToSegment(SkScalar distance, SkScalar* t);
+    bool quad_too_curvy(const SkPoint pts[3]);
+    bool conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTPt,const SkPoint& lastPt);
+    bool cheap_dist_exceeds_limit(const SkPoint& pt, SkScalar x, SkScalar y);
+    bool cubic_too_curvy(const SkPoint pts[4]);
+};
+
+#endif

+ 284 - 0
skia/include/core/SkPicture.h

@@ -0,0 +1,284 @@
+/*
+ * Copyright 2007 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkPicture.h and docs/SkPicture_Reference.bmh
+   on 2018-08-10 12:59:44. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkPicture_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkPicture_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkPicture.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkPicture_DEFINED
+#define SkPicture_DEFINED
+
+#include "SkRefCnt.h"
+#include "SkRect.h"
+#include "SkTypes.h"
+
+class SkCanvas;
+class SkData;
+struct SkDeserialProcs;
+class SkImage;
+struct SkSerialProcs;
+class SkStream;
+class SkWStream;
+
+/** \class SkPicture
+    SkPicture records drawing commands made to SkCanvas. The command stream may be
+    played in whole or in part at a later time.
+
+    SkPicture is an abstract class. SkPicture may be generated by SkPictureRecorder
+    or SkDrawable, or from SkPicture previously saved to SkData or SkStream.
+
+    SkPicture may contain any SkCanvas drawing command, as well as one or more
+    SkCanvas matrix or SkCanvas clip. SkPicture has a cull SkRect, which is used as
+    a bounding box hint. To limit SkPicture bounds, use SkCanvas clip when
+    recording or drawing SkPicture.
+*/
+class SK_API SkPicture : public SkRefCnt {
+public:
+
+    /** Recreates SkPicture that was serialized into a stream. Returns constructed SkPicture
+        if successful; otherwise, returns nullptr. Fails if data does not permit
+        constructing valid SkPicture.
+
+        procs->fPictureProc permits supplying a custom function to decode SkPicture.
+        If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+        is called with a pointer to data, data byte length, and user context.
+
+        @param stream  container for serial data
+        @param procs   custom serial data decoders; may be nullptr
+        @return        SkPicture constructed from stream data
+    */
+    static sk_sp<SkPicture> MakeFromStream(SkStream* stream,
+                                           const SkDeserialProcs* procs = nullptr);
+
+    /** Recreates SkPicture that was serialized into data. Returns constructed SkPicture
+        if successful; otherwise, returns nullptr. Fails if data does not permit
+        constructing valid SkPicture.
+
+        procs->fPictureProc permits supplying a custom function to decode SkPicture.
+        If procs->fPictureProc is nullptr, default decoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+        is called with a pointer to data, data byte length, and user context.
+
+        @param data   container for serial data
+        @param procs  custom serial data decoders; may be nullptr
+        @return       SkPicture constructed from data
+    */
+    static sk_sp<SkPicture> MakeFromData(const SkData* data,
+                                         const SkDeserialProcs* procs = nullptr);
+
+    /**
+
+        @param data   pointer to serial data
+        @param size   size of data
+        @param procs  custom serial data decoders; may be nullptr
+        @return       SkPicture constructed from data
+    */
+    static sk_sp<SkPicture> MakeFromData(const void* data, size_t size,
+                                         const SkDeserialProcs* procs = nullptr);
+
+    /** \class SkPicture::AbortCallback
+        AbortCallback is an abstract class. An implementation of AbortCallback may
+        passed as a parameter to SkPicture::playback, to stop it before all drawing
+        commands have been processed.
+
+        If AbortCallback::abort returns true, SkPicture::playback is interrupted.
+    */
+    class SK_API AbortCallback {
+    public:
+
+        /** Has no effect.
+
+            @return  abstract class cannot be instantiated
+        */
+        AbortCallback() {}
+
+        /** Has no effect.
+        */
+        virtual ~AbortCallback() {}
+
+        /** Stops SkPicture playback when some condition is met. A subclass of
+            AbortCallback provides an override for abort() that can stop SkPicture::playback.
+
+            The part of SkPicture drawn when aborted is undefined. SkPicture instantiations are
+            free to stop drawing at different points during playback.
+
+            If the abort happens inside one or more calls to SkCanvas::save(), stack
+            of SkCanvas matrix and SkCanvas clip values is restored to its state before
+            SkPicture::playback was called.
+
+            @return  true to stop playback
+        */
+        virtual bool abort() = 0;
+    };
+
+    /** Replays the drawing commands on the specified canvas. In the case that the
+        commands are recorded, each command in the SkPicture is sent separately to canvas.
+
+        To add a single command to draw SkPicture to recording canvas, call
+        SkCanvas::drawPicture instead.
+
+        @param canvas    receiver of drawing commands
+        @param callback  allows interruption of playback
+    */
+    virtual void playback(SkCanvas* canvas, AbortCallback* callback = nullptr) const = 0;
+
+    /** Returns cull SkRect for this picture, passed in when SkPicture was created.
+        Returned SkRect does not specify clipping SkRect for SkPicture; cull is hint
+        of SkPicture bounds.
+
+        SkPicture is free to discard recorded drawing commands that fall outside
+        cull.
+
+        @return  bounds passed when SkPicture was created
+    */
+    virtual SkRect cullRect() const = 0;
+
+    /** Returns a non-zero value unique among SkPicture in Skia process.
+
+        @return  identifier for SkPicture
+    */
+    uint32_t uniqueID() const;
+
+    /** Returns storage containing SkData describing SkPicture, using optional custom
+        encoders.
+
+        procs->fPictureProc permits supplying a custom function to encode SkPicture.
+        If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+        is called with a pointer to SkPicture and user context.
+
+        @param procs  custom serial data encoders; may be nullptr
+        @return       storage containing serialized SkPicture
+    */
+    sk_sp<SkData> serialize(const SkSerialProcs* procs = nullptr) const;
+
+    /** Writes picture to stream, using optional custom encoders.
+
+        procs->fPictureProc permits supplying a custom function to encode SkPicture.
+        If procs->fPictureProc is nullptr, default encoding is used. procs->fPictureCtx
+        may be used to provide user context to procs->fPictureProc; procs->fPictureProc
+        is called with a pointer to SkPicture and user context.
+
+        @param stream  writable serial data stream
+        @param procs   custom serial data encoders; may be nullptr
+    */
+    void serialize(SkWStream* stream, const SkSerialProcs* procs = nullptr) const;
+
+    /** Returns a placeholder SkPicture. Result does not draw, and contains only
+        cull SkRect, a hint of its bounds. Result is immutable; it cannot be changed
+        later. Result identifier is unique.
+
+        Returned placeholder can be intercepted during playback to insert other
+        commands into SkCanvas draw stream.
+
+        @param cull  placeholder dimensions
+        @return      placeholder with unique identifier
+    */
+    static sk_sp<SkPicture> MakePlaceholder(SkRect cull);
+
+    /** Returns the approximate number of operations in SkPicture. Returned value
+        may be greater or less than the number of SkCanvas calls
+        recorded: some calls may be recorded as more than one operation, other
+        calls may be optimized away.
+
+        @return  approximate operation count
+    */
+    virtual int approximateOpCount() const = 0;
+
+    /** Returns the approximate byte size of SkPicture. Does not include large objects
+        referenced by SkPicture.
+
+        @return  approximate size
+    */
+    virtual size_t approximateBytesUsed() const = 0;
+
+private:
+    // Subclass whitelist.
+    SkPicture();
+    friend class SkBigPicture;
+    friend class SkEmptyPicture;
+    friend class SkPicturePriv;
+    template <typename> friend class SkMiniPicture;
+
+    void serialize(SkWStream*, const SkSerialProcs*, class SkRefCntSet* typefaces) const;
+    static sk_sp<SkPicture> MakeFromStream(SkStream*, const SkDeserialProcs*,
+                                           class SkTypefacePlayback*);
+    friend class SkPictureData;
+
+    /** Return true if the SkStream/Buffer represents a serialized picture, and
+     fills out SkPictInfo. After this function returns, the data source is not
+     rewound so it will have to be manually reset before passing to
+     MakeFromStream or MakeFromBuffer. Note, MakeFromStream and
+     MakeFromBuffer perform this check internally so these entry points are
+     intended for stand alone tools.
+     If false is returned, SkPictInfo is unmodified.
+     */
+    static bool StreamIsSKP(SkStream*, struct SkPictInfo*);
+    static bool BufferIsSKP(class SkReadBuffer*, struct SkPictInfo*);
+    friend bool SkPicture_StreamIsSKP(SkStream*, struct SkPictInfo*);
+
+    // Returns NULL if this is not an SkBigPicture.
+    virtual const class SkBigPicture* asSkBigPicture() const { return nullptr; }
+
+    friend struct SkPathCounter;
+
+    // V35: Store SkRect (rather then width & height) in header
+    // V36: Remove (obsolete) alphatype from SkColorTable
+    // V37: Added shadow only option to SkDropShadowImageFilter (last version to record CLEAR)
+    // V38: Added PictureResolution option to SkPictureImageFilter
+    // V39: Added FilterLevel option to SkPictureImageFilter
+    // V40: Remove UniqueID serialization from SkImageFilter.
+    // V41: Added serialization of SkBitmapSource's filterQuality parameter
+    // V42: Added a bool to SkPictureShader serialization to indicate did-we-serialize-a-picture?
+    // V43: Added DRAW_IMAGE and DRAW_IMAGE_RECT opt codes to serialized data
+    // V44: Move annotations from paint to drawAnnotation
+    // V45: Add invNormRotation to SkLightingShader.
+    // V46: Add drawTextRSXform
+    // V47: Add occluder rect to SkBlurMaskFilter
+    // V48: Read and write extended SkTextBlobs.
+    // V49: Gradients serialized as SkColor4f + SkColorSpace
+    // V50: SkXfermode -> SkBlendMode
+    // V51: more SkXfermode -> SkBlendMode
+    // V52: Remove SkTextBlob::fRunCount
+    // V53: SaveLayerRec clip mask
+    // V54: ComposeShader can use a Mode or a Lerp
+    // V55: Drop blendmode[] from MergeImageFilter
+    // V56: Add TileMode in SkBlurImageFilter.
+    // V57: Sweep tiling info.
+    // V58: No more 2pt conical flipping.
+    // V59: No more LocalSpace option on PictureImageFilter
+    // V60: Remove flags in picture header
+    // V61: Change SkDrawPictureRec to take two colors rather than two alphas
+    // V62: Don't negate size of custom encoded images (don't write origin x,y either)
+    // V63: Store image bounds (including origin) instead of just width/height to support subsets
+    // V64: Remove occluder feature from blur maskFilter
+
+    // Only SKPs within the min/current picture version range (inclusive) can be read.
+    static const uint32_t     MIN_PICTURE_VERSION = 56;     // august 2017
+    static const uint32_t CURRENT_PICTURE_VERSION = 65;
+
+    static_assert(MIN_PICTURE_VERSION <= 62, "Remove kFontAxes_bad from SkFontDescriptor.cpp");
+
+    static bool IsValidPictInfo(const struct SkPictInfo& info);
+    static sk_sp<SkPicture> Forwardport(const struct SkPictInfo&,
+                                        const class SkPictureData*,
+                                        class SkReadBuffer* buffer);
+
+    struct SkPictInfo createHeader() const;
+    class SkPictureData* backport() const;
+
+    mutable uint32_t fUniqueID;
+};
+
+#endif

+ 125 - 0
skia/include/core/SkPictureRecorder.h

@@ -0,0 +1,125 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPictureRecorder_DEFINED
+#define SkPictureRecorder_DEFINED
+
+#include "../private/SkNoncopyable.h"
+#include "SkBBHFactory.h"
+#include "SkPicture.h"
+#include "SkRefCnt.h"
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+namespace android {
+    class Picture;
+};
+#endif
+
+class GrContext;
+class SkCanvas;
+class SkDrawable;
+class SkMiniRecorder;
+class SkPictureRecord;
+class SkRecord;
+class SkRecorder;
+
+class SK_API SkPictureRecorder : SkNoncopyable {
+public:
+    SkPictureRecorder();
+    ~SkPictureRecorder();
+
+    enum RecordFlags {
+        // If you call drawPicture() or drawDrawable() on the recording canvas, this flag forces
+        // that object to playback its contents immediately rather than reffing the object.
+        kPlaybackDrawPicture_RecordFlag     = 1 << 0,
+    };
+
+    enum FinishFlags {
+    };
+
+    /** Returns the canvas that records the drawing commands.
+        @param bounds the cull rect used when recording this picture. Any drawing the falls outside
+                      of this rect is undefined, and may be drawn or it may not.
+        @param bbhFactory factory to create desired acceleration structure
+        @param recordFlags optional flags that control recording.
+        @return the canvas.
+    */
+    SkCanvas* beginRecording(const SkRect& bounds,
+                             SkBBHFactory* bbhFactory = nullptr,
+                             uint32_t recordFlags = 0);
+
+    SkCanvas* beginRecording(SkScalar width, SkScalar height,
+                             SkBBHFactory* bbhFactory = nullptr,
+                             uint32_t recordFlags = 0) {
+        return this->beginRecording(SkRect::MakeWH(width, height), bbhFactory, recordFlags);
+    }
+
+    /** Returns the recording canvas if one is active, or NULL if recording is
+        not active. This does not alter the refcnt on the canvas (if present).
+    */
+    SkCanvas* getRecordingCanvas();
+
+    /**
+     *  Signal that the caller is done recording. This invalidates the canvas returned by
+     *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
+     *  must call unref() when they are done using it.
+     *
+     *  The returned picture is immutable. If during recording drawables were added to the canvas,
+     *  these will have been "drawn" into a recording canvas, so that this resulting picture will
+     *  reflect their current state, but will not contain a live reference to the drawables
+     *  themselves.
+     */
+    sk_sp<SkPicture> finishRecordingAsPicture(uint32_t endFlags = 0);
+
+    /**
+     *  Signal that the caller is done recording, and update the cull rect to use for bounding
+     *  box hierarchy (BBH) generation. The behavior is the same as calling
+     *  finishRecordingAsPicture(), except that this method updates the cull rect initially passed
+     *  into beginRecording.
+     *  @param cullRect the new culling rectangle to use as the overall bound for BBH generation
+     *                  and subsequent culling operations.
+     *  @return the picture containing the recorded content.
+     */
+    sk_sp<SkPicture> finishRecordingAsPictureWithCull(const SkRect& cullRect,
+                                                      uint32_t endFlags = 0);
+
+    /**
+     *  Signal that the caller is done recording. This invalidates the canvas returned by
+     *  beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
+     *  must call unref() when they are done using it.
+     *
+     *  Unlike finishRecordingAsPicture(), which returns an immutable picture, the returned drawable
+     *  may contain live references to other drawables (if they were added to the recording canvas)
+     *  and therefore this drawable will reflect the current state of those nested drawables anytime
+     *  it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
+     */
+    sk_sp<SkDrawable> finishRecordingAsDrawable(uint32_t endFlags = 0);
+
+private:
+    void reset();
+
+    /** Replay the current (partially recorded) operation stream into
+        canvas. This call doesn't close the current recording.
+    */
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+    friend class android::Picture;
+#endif
+    friend class SkPictureRecorderReplayTester; // for unit testing
+    void partialReplay(SkCanvas* canvas) const;
+
+    bool                        fActivelyRecording;
+    uint32_t                    fFlags;
+    SkRect                      fCullRect;
+    sk_sp<SkBBoxHierarchy>      fBBH;
+    std::unique_ptr<SkRecorder> fRecorder;
+    sk_sp<SkRecord>             fRecord;
+    std::unique_ptr<SkMiniRecorder> fMiniRecorder;
+
+    typedef SkNoncopyable INHERITED;
+};
+
+#endif

+ 129 - 0
skia/include/core/SkPixelRef.h

@@ -0,0 +1,129 @@
+/*
+ * Copyright 2008 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPixelRef_DEFINED
+#define SkPixelRef_DEFINED
+
+#include "../private/SkMutex.h"
+#include "../private/SkTDArray.h"
+#include "SkBitmap.h"
+#include "SkFilterQuality.h"
+#include "SkImageInfo.h"
+#include "SkPixmap.h"
+#include "SkRefCnt.h"
+#include "SkSize.h"
+#include "SkString.h"
+
+#include <atomic>
+
+struct SkIRect;
+
+class GrTexture;
+class SkDiscardableMemory;
+
+/** \class SkPixelRef
+
+    This class is the smart container for pixel memory, and is used with SkBitmap.
+    This class can be shared/accessed between multiple threads.
+*/
+class SK_API SkPixelRef : public SkRefCnt {
+public:
+    SkPixelRef(int width, int height, void* addr, size_t rowBytes);
+    ~SkPixelRef() override;
+
+    int width() const { return fWidth; }
+    int height() const { return fHeight; }
+    void* pixels() const { return fPixels; }
+    size_t rowBytes() const { return fRowBytes; }
+
+    /** Returns a non-zero, unique value corresponding to the pixels in this
+        pixelref. Each time the pixels are changed (and notifyPixelsChanged is
+        called), a different generation ID will be returned.
+    */
+    uint32_t getGenerationID() const;
+
+    /**
+     *  Call this if you have changed the contents of the pixels. This will in-
+     *  turn cause a different generation ID value to be returned from
+     *  getGenerationID().
+     */
+    void notifyPixelsChanged();
+
+    /** Returns true if this pixelref is marked as immutable, meaning that the
+        contents of its pixels will not change for the lifetime of the pixelref.
+    */
+    bool isImmutable() const { return fMutability != kMutable; }
+
+    /** Marks this pixelref is immutable, meaning that the contents of its
+        pixels will not change for the lifetime of the pixelref. This state can
+        be set on a pixelref, but it cannot be cleared once it is set.
+    */
+    void setImmutable();
+
+    // Register a listener that may be called the next time our generation ID changes.
+    //
+    // We'll only call the listener if we're confident that we are the only SkPixelRef with this
+    // generation ID.  If our generation ID changes and we decide not to call the listener, we'll
+    // never call it: you must add a new listener for each generation ID change.  We also won't call
+    // the listener when we're certain no one knows what our generation ID is.
+    //
+    // This can be used to invalidate caches keyed by SkPixelRef generation ID.
+    struct GenIDChangeListener {
+        virtual ~GenIDChangeListener() {}
+        virtual void onChange() = 0;
+    };
+
+    // Takes ownership of listener.  Threadsafe.
+    void addGenIDChangeListener(GenIDChangeListener* listener);
+
+    // Call when this pixelref is part of the key to a resourcecache entry. This allows the cache
+    // to know automatically those entries can be purged when this pixelref is changed or deleted.
+    void notifyAddedToCache() {
+        fAddedToCache.store(true);
+    }
+
+    virtual SkDiscardableMemory* diagnostic_only_getDiscardable() const { return nullptr; }
+
+protected:
+    void android_only_reset(int width, int height, size_t rowBytes);
+
+private:
+    int                 fWidth;
+    int                 fHeight;
+    void*               fPixels;
+    size_t              fRowBytes;
+
+    // Bottom bit indicates the Gen ID is unique.
+    bool genIDIsUnique() const { return SkToBool(fTaggedGenID.load() & 1); }
+    mutable std::atomic<uint32_t> fTaggedGenID;
+
+    SkMutex                         fGenIDChangeListenersMutex;
+    SkTDArray<GenIDChangeListener*> fGenIDChangeListeners;  // pointers are owned
+
+    // Set true by caches when they cache content that's derived from the current pixels.
+    std::atomic<bool> fAddedToCache;
+
+    enum Mutability {
+        kMutable,               // PixelRefs begin mutable.
+        kTemporarilyImmutable,  // Considered immutable, but can revert to mutable.
+        kImmutable,             // Once set to this state, it never leaves.
+    } fMutability : 8;          // easily fits inside a byte
+
+    void needsNewGenID();
+    void callGenIDChangeListeners();
+
+    void setTemporarilyImmutable();
+    void restoreMutability();
+    friend class SkSurface_Raster;   // For the two methods above.
+
+    void setImmutableWithID(uint32_t genID);
+    friend void SkBitmapCache_setImmutableWithID(SkPixelRef*, uint32_t);
+
+    typedef SkRefCnt INHERITED;
+};
+
+#endif

+ 706 - 0
skia/include/core/SkPixmap.h

@@ -0,0 +1,706 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Generated by tools/bookmaker from include/core/SkPixmap.h and docs/SkPixmap_Reference.bmh
+   on 2018-06-08 11:48:28. Additional documentation and examples can be found at:
+   https://skia.org/user/api/SkPixmap_Reference
+
+   You may edit either file directly. Structural changes to public interfaces require
+   editing both files. After editing docs/SkPixmap_Reference.bmh, run:
+       bookmaker -b docs -i include/core/SkPixmap.h -p
+   to create an updated version of this file.
+ */
+
+#ifndef SkPixmap_DEFINED
+#define SkPixmap_DEFINED
+
+#include "SkColor.h"
+#include "SkFilterQuality.h"
+#include "SkImageInfo.h"
+
+class SkData;
+struct SkMask;
+
+/** \class SkPixmap
+    SkPixmap provides a utility to pair SkImageInfo with pixels and row bytes.
+    SkPixmap is a low level class which provides convenience functions to access
+    raster destinations. SkCanvas can not draw SkPixmap, nor does SkPixmap provide
+    a direct drawing destination.
+
+    Use SkBitmap to draw pixels referenced by SkPixmap; use SkSurface to draw into
+    pixels referenced by SkPixmap.
+
+    SkPixmap does not try to manage the lifetime of the pixel memory. Use SkPixelRef
+    to manage pixel memory; SkPixelRef is safe across threads.
+*/
+class SK_API SkPixmap {
+public:
+
+    /** Creates an empty SkPixmap without pixels, with kUnknown_SkColorType, with
+        kUnknown_SkAlphaType, and with a width and height of zero. Use
+        reset() to associate pixels, SkColorType, SkAlphaType, width, and height
+        after SkPixmap has been created.
+
+        @return  empty SkPixmap
+    */
+    SkPixmap()
+        : fPixels(nullptr), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0))
+    {}
+
+    /** Creates SkPixmap from info width, height, SkAlphaType, and SkColorType.
+        addr points to pixels, or nullptr. rowBytes should be info.width() times
+        info.bytesPerPixel(), or larger.
+
+        No parameter checking is performed; it is up to the caller to ensure that
+        addr and rowBytes agree with info.
+
+        The memory lifetime of pixels is managed by the caller. When SkPixmap goes
+        out of scope, addr is unaffected.
+
+        SkPixmap may be later modified by reset() to change its size, pixel type, or
+        storage.
+
+        @param info      width, height, SkAlphaType, SkColorType of SkImageInfo
+        @param addr      pointer to pixels allocated by caller; may be nullptr
+        @param rowBytes  size of one row of addr; width times pixel size, or larger
+        @return          initialized SkPixmap
+    */
+    SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes)
+        : fPixels(addr), fRowBytes(rowBytes), fInfo(info)
+    {}
+
+    /** Sets width, height, row bytes to zero; pixel address to nullptr; SkColorType to
+        kUnknown_SkColorType; and SkAlphaType to kUnknown_SkAlphaType.
+
+        The prior pixels are unaffected; it is up to the caller to release pixels
+        memory if desired.
+    */
+    void reset();
+
+    /** Sets width, height, SkAlphaType, and SkColorType from info.
+        Sets pixel address from addr, which may be nullptr.
+        Sets row bytes from rowBytes, which should be info.width() times
+        info.bytesPerPixel(), or larger.
+
+        Does not check addr. Asserts if built with SK_DEBUG defined and if rowBytes is
+        too small to hold one row of pixels.
+
+        The memory lifetime pixels are managed by the caller. When SkPixmap goes
+        out of scope, addr is unaffected.
+
+        @param info      width, height, SkAlphaType, SkColorType of SkImageInfo
+        @param addr      pointer to pixels allocated by caller; may be nullptr
+        @param rowBytes  size of one row of addr; width times pixel size, or larger
+    */
+    void reset(const SkImageInfo& info, const void* addr, size_t rowBytes);
+
+    /** Changes SkColorSpace in SkImageInfo; preserves width, height, SkAlphaType, and
+        SkColorType in SkImage, and leaves pixel address and row bytes unchanged.
+        SkColorSpace reference count is incremented.
+
+        @param colorSpace  SkColorSpace moved to SkImageInfo
+    */
+    void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
+    /** Deprecated.
+    */
+    bool SK_WARN_UNUSED_RESULT reset(const SkMask& mask);
+
+    /** Sets subset width, height, pixel address to intersection of SkPixmap with area,
+        if intersection is not empty; and return true. Otherwise, leave subset unchanged
+        and return false.
+
+        Failing to read the return value generates a compile time warning.
+
+        @param subset  storage for width, height, pixel address of intersection
+        @param area    bounds to intersect with SkPixmap
+        @return        true if intersection of SkPixmap and area is not empty
+    */
+    bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const;
+
+    /** Returns width, height, SkAlphaType, SkColorType, and SkColorSpace.
+
+        @return  reference to SkImageInfo
+    */
+    const SkImageInfo& info() const { return fInfo; }
+
+    /** Returns row bytes, the interval from one pixel row to the next. Row bytes
+        is at least as large as: width() * info().bytesPerPixel().
+
+        Returns zero if colorType() is kUnknown_SkColorType.
+        It is up to the SkBitmap creator to ensure that row bytes is a useful value.
+
+        @return  byte length of pixel row
+    */
+    size_t rowBytes() const { return fRowBytes; }
+
+    /** Returns pixel address, the base address corresponding to the pixel origin.
+
+        It is up to the SkPixmap creator to ensure that pixel address is a useful value.
+
+        @return  pixel address
+    */
+    const void* addr() const { return fPixels; }
+
+    /** Returns pixel count in each pixel row. Should be equal or less than:
+        rowBytes() / info().bytesPerPixel().
+
+        @return  pixel width in SkImageInfo
+    */
+    int width() const { return fInfo.width(); }
+
+    /** Returns pixel row count.
+
+        @return  pixel height in SkImageInfo
+    */
+    int height() const { return fInfo.height(); }
+
+    /** Returns SkColorType, one of:
+        kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
+        kARGB_4444_SkColorType, kRGBA_8888_SkColorType, kRGB_888x_SkColorType,
+        kBGRA_8888_SkColorType, kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
+        kGray_8_SkColorType, kRGBA_F16_SkColorType.
+
+        @return  SkColorType in SkImageInfo
+    */
+    SkColorType colorType() const { return fInfo.colorType(); }
+
+    /** Returns SkAlphaType, one of:
+        kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType,
+        kUnpremul_SkAlphaType.
+
+        @return  SkAlphaType in SkImageInfo
+    */
+    SkAlphaType alphaType() const { return fInfo.alphaType(); }
+
+    /** Returns SkColorSpace, the range of colors, associated with SkImageInfo. The
+        reference count of SkColorSpace is unchanged. The returned SkColorSpace is
+        immutable.
+
+        @return  SkColorSpace in SkImageInfo, or nullptr
+    */
+    SkColorSpace* colorSpace() const { return fInfo.colorSpace(); }
+
+    /** Returns true if SkAlphaType is kOpaque_SkAlphaType.
+        Does not check if SkColorType allows alpha, or if any pixel value has
+        transparency.
+
+        @return  true if SkImageInfo has opaque SkAlphaType
+    */
+    bool isOpaque() const { return fInfo.isOpaque(); }
+
+    /** Returns SkIRect { 0, 0, width(), height() }.
+
+        @return  integral rectangle from origin to width() and height()
+    */
+    SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); }
+
+    /** Returns number of pixels that fit on row. Should be greater than or equal to
+        width().
+
+        @return  maximum pixels per row
+    */
+    int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); }
+
+    /** Returns bit shift converting row bytes to row pixels.
+        Returns zero for kUnknown_SkColorType.
+
+        @return  one of: 0, 1, 2, 3; left shift to convert pixels to bytes
+    */
+    int shiftPerPixel() const { return fInfo.shiftPerPixel(); }
+
+    /** Returns minimum memory required for pixel storage.
+        Does not include unused memory on last row when rowBytesAsPixels() exceeds width().
+        Returns zero if result does not fit in size_t.
+        Returns zero if height() or width() is 0.
+        Returns height() times rowBytes() if colorType() is kUnknown_SkColorType.
+
+        @return  size in bytes of image buffer
+    */
+    size_t computeByteSize() const { return fInfo.computeByteSize(fRowBytes); }
+
+    /** Returns true if all pixels are opaque. SkColorType determines how pixels
+        are encoded, and whether pixel describes alpha. Returns true for SkColorType
+        without alpha in each pixel; for other SkColorType, returns true if all
+        pixels have alpha values equivalent to 1.0 or greater.
+
+        For SkColorType kRGB_565_SkColorType or kGray_8_SkColorType: always
+        returns true. For SkColorType kAlpha_8_SkColorType, kBGRA_8888_SkColorType,
+        kRGBA_8888_SkColorType: returns true if all pixel alpha values are 255.
+        For SkColorType kARGB_4444_SkColorType: returns true if all pixel alpha values are 15.
+        For kRGBA_F16_SkColorType: returns true if all pixel alpha values are 1.0 or
+        greater.
+
+        Returns false for kUnknown_SkColorType.
+
+        @return  true if all pixels have opaque values or SkColorType is opaque
+    */
+    bool computeIsOpaque() const;
+
+    /** Returns pixel at (x, y) as unpremultiplied color.
+        Returns black with alpha if SkColorType is kAlpha_8_SkColorType.
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined; and returns undefined values or may crash if
+        SK_RELEASE is defined. Fails if SkColorType is kUnknown_SkColorType or
+        pixel address is nullptr.
+
+        SkColorSpace in SkImageInfo is ignored. Some color precision may be lost in the
+        conversion to unpremultiplied color; original pixel data may have additional
+        precision.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   pixel converted to unpremultiplied color
+    */
+    SkColor getColor(int x, int y) const;
+
+    /** Look up the pixel at (x,y) and return its alpha component, normalized to [0..1].
+        This is roughly equivalent to SkGetColorA(getColor()), but can be more efficent
+        (and more precise if the pixels store more than 8 bits per component).
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   alpha converted to normalized float
+     */
+    float getAlphaf(int x, int y) const;
+
+    /** Returns readable pixel address at (x, y). Returns nullptr if SkPixelRef is nullptr.
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined. Returns nullptr if SkColorType is kUnknown_SkColorType.
+
+        Performs a lookup of pixel size; for better performance, call
+        one of: addr8, addr16, addr32, addr64, or addrF16().
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable generic pointer to pixel
+    */
+    const void* addr(int x, int y) const {
+        return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes);
+    }
+
+    /** Returns readable base pixel address. Result is addressable as unsigned 8-bit bytes.
+        Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
+        kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+        One byte corresponds to one pixel.
+
+        @return  readable unsigned 8-bit pointer to pixels
+    */
+    const uint8_t* addr8() const {
+        SkASSERT(1 == fInfo.bytesPerPixel());
+        return reinterpret_cast<const uint8_t*>(fPixels);
+    }
+
+    /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
+        Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
+        kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+        One word corresponds to one pixel.
+
+        @return  readable unsigned 16-bit pointer to pixels
+    */
+    const uint16_t* addr16() const {
+        SkASSERT(2 == fInfo.bytesPerPixel());
+        return reinterpret_cast<const uint16_t*>(fPixels);
+    }
+
+    /** Returns readable base pixel address. Result is addressable as unsigned 32-bit words.
+        Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
+        kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
+
+        One word corresponds to one pixel.
+
+        @return  readable unsigned 32-bit pointer to pixels
+    */
+    const uint32_t* addr32() const {
+        SkASSERT(4 == fInfo.bytesPerPixel());
+        return reinterpret_cast<const uint32_t*>(fPixels);
+    }
+
+    /** Returns readable base pixel address. Result is addressable as unsigned 64-bit words.
+        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+        with SK_DEBUG defined.
+
+        One word corresponds to one pixel.
+
+        @return  readable unsigned 64-bit pointer to pixels
+    */
+    const uint64_t* addr64() const {
+        SkASSERT(8 == fInfo.bytesPerPixel());
+        return reinterpret_cast<const uint64_t*>(fPixels);
+    }
+
+    /** Returns readable base pixel address. Result is addressable as unsigned 16-bit words.
+        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+        with SK_DEBUG defined.
+
+        Each word represents one color component encoded as a half float.
+        Four words correspond to one pixel.
+
+        @return  readable unsigned 16-bit pointer to first component of pixels
+    */
+    const uint16_t* addrF16() const {
+        SkASSERT(8 == fInfo.bytesPerPixel());
+        SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
+        return reinterpret_cast<const uint16_t*>(fPixels);
+    }
+
+    /** Returns readable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined.
+
+        Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType or
+        kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable unsigned 8-bit pointer to pixel at (x, y)
+    */
+    const uint8_t* addr8(int x, int y) const {
+        SkASSERT((unsigned)x < (unsigned)fInfo.width());
+        SkASSERT((unsigned)y < (unsigned)fInfo.height());
+        return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0));
+    }
+
+    /** Returns readable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined.
+
+        Will trigger an assert() if SkColorType is not kRGB_565_SkColorType or
+        kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable unsigned 16-bit pointer to pixel at (x, y)
+    */
+    const uint16_t* addr16(int x, int y) const {
+        SkASSERT((unsigned)x < (unsigned)fInfo.width());
+        SkASSERT((unsigned)y < (unsigned)fInfo.height());
+        return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1));
+    }
+
+    /** Returns readable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined.
+
+        Will trigger an assert() if SkColorType is not kRGBA_8888_SkColorType or
+        kBGRA_8888_SkColorType, and is built with SK_DEBUG defined.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable unsigned 32-bit pointer to pixel at (x, y)
+    */
+    const uint32_t* addr32(int x, int y) const {
+        SkASSERT((unsigned)x < (unsigned)fInfo.width());
+        SkASSERT((unsigned)y < (unsigned)fInfo.height());
+        return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2));
+    }
+
+    /** Returns readable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined.
+
+        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+        with SK_DEBUG defined.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable unsigned 64-bit pointer to pixel at (x, y)
+    */
+    const uint64_t* addr64(int x, int y) const {
+        SkASSERT((unsigned)x < (unsigned)fInfo.width());
+        SkASSERT((unsigned)y < (unsigned)fInfo.height());
+        return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3));
+    }
+
+    /** Returns readable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined.
+
+        Will trigger an assert() if SkColorType is not kRGBA_F16_SkColorType and is built
+        with SK_DEBUG defined.
+
+        Each unsigned 16-bit word represents one color component encoded as a half float.
+        Four words correspond to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   readable unsigned 16-bit pointer to pixel component at (x, y)
+    */
+    const uint16_t* addrF16(int x, int y) const {
+        SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType());
+        return reinterpret_cast<const uint16_t*>(this->addr64(x, y));
+    }
+
+    /** Returns writable base pixel address.
+
+        @return  writable generic base pointer to pixels
+    */
+    void* writable_addr() const { return const_cast<void*>(fPixels); }
+
+    /** Returns writable pixel address at (x, y).
+
+        Input is not validated: out of bounds values of x or y trigger an assert() if
+        built with SK_DEBUG defined. Returns zero if SkColorType is kUnknown_SkColorType.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable generic pointer to pixel
+    */
+    void* writable_addr(int x, int y) const {
+        return const_cast<void*>(this->addr(x, y));
+    }
+
+    /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+        8-bit bytes. Will trigger an assert() if SkColorType is not kAlpha_8_SkColorType
+        or kGray_8_SkColorType, and is built with SK_DEBUG defined.
+
+        One byte corresponds to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable unsigned 8-bit pointer to pixels
+    */
+    uint8_t* writable_addr8(int x, int y) const {
+        return const_cast<uint8_t*>(this->addr8(x, y));
+    }
+
+    /** Returns writable_addr pixel address at (x, y). Result is addressable as unsigned
+        16-bit words. Will trigger an assert() if SkColorType is not kRGB_565_SkColorType
+        or kARGB_4444_SkColorType, and is built with SK_DEBUG defined.
+
+        One word corresponds to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable unsigned 16-bit pointer to pixel
+    */
+    uint16_t* writable_addr16(int x, int y) const {
+        return const_cast<uint16_t*>(this->addr16(x, y));
+    }
+
+    /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+        32-bit words. Will trigger an assert() if SkColorType is not
+        kRGBA_8888_SkColorType or kBGRA_8888_SkColorType, and is built with SK_DEBUG
+        defined.
+
+        One word corresponds to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable unsigned 32-bit pointer to pixel
+    */
+    uint32_t* writable_addr32(int x, int y) const {
+        return const_cast<uint32_t*>(this->addr32(x, y));
+    }
+
+    /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+        64-bit words. Will trigger an assert() if SkColorType is not
+        kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
+
+        One word corresponds to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable unsigned 64-bit pointer to pixel
+    */
+    uint64_t* writable_addr64(int x, int y) const {
+        return const_cast<uint64_t*>(this->addr64(x, y));
+    }
+
+    /** Returns writable pixel address at (x, y). Result is addressable as unsigned
+        16-bit words. Will trigger an assert() if SkColorType is not
+        kRGBA_F16_SkColorType and is built with SK_DEBUG defined.
+
+        Each word represents one color component encoded as a half float.
+        Four words correspond to one pixel.
+
+        @param x  column index, zero or greater, and less than width()
+        @param y  row index, zero or greater, and less than height()
+        @return   writable unsigned 16-bit pointer to first component of pixel
+    */
+    uint16_t* writable_addrF16(int x, int y) const {
+        return reinterpret_cast<uint16_t*>(writable_addr64(x, y));
+    }
+
+    /** Copies a SkRect of pixels to dstPixels. Copy starts at (0, 0), and does not
+        exceed SkPixmap (width(), height()).
+
+        dstInfo specifies width, height, SkColorType, SkAlphaType, and
+        SkColorSpace of destination. dstRowBytes specifics the gap from one destination
+        row to the next. Returns true if pixels are copied. Returns false if
+        dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
+
+        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+        If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+        If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+        match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        Returns false if SkPixmap width() or height() is zero or negative.
+
+        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
+        @param dstPixels    destination pixel storage
+        @param dstRowBytes  destination row length
+        @return             true if pixels are copied to dstPixels
+    */
+    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const {
+        return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0);
+    }
+
+    /** Copies a SkRect of pixels to dstPixels. Copy starts at (srcX, srcY), and does not
+        exceed SkPixmap (width(), height()).
+
+        dstInfo specifies width, height, SkColorType, SkAlphaType, and
+        SkColorSpace of destination. dstRowBytes specifics the gap from one destination
+        row to the next. Returns true if pixels are copied. Returns false if
+        dstInfo address equals nullptr, or dstRowBytes is less than dstInfo.minRowBytes().
+
+        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dstInfo.colorType() must match.
+        If SkPixmap colorType() is kGray_8_SkColorType, dstInfo.colorSpace() must match.
+        If SkPixmap alphaType() is kOpaque_SkAlphaType, dstInfo.alphaType() must
+        match. If SkPixmap colorSpace() is nullptr, dstInfo.colorSpace() must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false if SkPixmap width() or height() is zero or negative. Returns false if:
+        abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
+
+        @param dstInfo      destination width, height, SkColorType, SkAlphaType, SkColorSpace
+        @param dstPixels    destination pixel storage
+        @param dstRowBytes  destination row length
+        @param srcX         column index whose absolute value is less than width()
+        @param srcY         row index whose absolute value is less than height()
+        @return             true if pixels are copied to dstPixels
+    */
+    bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,
+                    int srcY) const;
+
+    /** Copies a SkRect of pixels to dst. Copy starts at (srcX, srcY), and does not
+        exceed SkPixmap (width(), height()). dst specifies width, height, SkColorType,
+        SkAlphaType, and SkColorSpace of destination.  Returns true if pixels are copied.
+        Returns false if dst address equals nullptr, or dst.rowBytes() is less than
+        dst SkImageInfo::minRowBytes.
+
+        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst.info().colorType must match.
+        If SkPixmap colorType() is kGray_8_SkColorType, dst.info().colorSpace must match.
+        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst.info().alphaType must
+        match. If SkPixmap colorSpace() is nullptr, dst.info().colorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        srcX and srcY may be negative to copy only top or left of source. Returns
+        false SkPixmap width() or height() is zero or negative. Returns false if:
+        abs(srcX) >= Pixmap width(), or if abs(srcY) >= Pixmap height().
+
+        @param dst   SkImageInfo and pixel address to write to
+        @param srcX  column index whose absolute value is less than width()
+        @param srcY  row index whose absolute value is less than height()
+        @return      true if pixels are copied to dst
+    */
+    bool readPixels(const SkPixmap& dst, int srcX, int srcY) const {
+        return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
+    }
+
+    /** Copies pixels inside bounds() to dst. dst specifies width, height, SkColorType,
+        SkAlphaType, and SkColorSpace of destination.  Returns true if pixels are copied.
+        Returns false if dst address equals nullptr, or dst.rowBytes() is less than
+        dst SkImageInfo::minRowBytes.
+
+        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+        If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+        match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        Returns false if SkPixmap width() or height() is zero or negative.
+
+        @param dst  SkImageInfo and pixel address to write to
+        @return     true if pixels are copied to dst
+    */
+    bool readPixels(const SkPixmap& dst) const {
+        return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0);
+    }
+
+    /** Copies SkBitmap to dst, scaling pixels to fit dst.width() and dst.height(), and
+        converting pixels to match dst.colorType() and dst.alphaType(). Returns true if
+        pixels are copied. Returns false if dst address is nullptr, or dst.rowBytes() is
+        less than dst SkImageInfo::minRowBytes.
+
+        Pixels are copied only if pixel conversion is possible. If SkPixmap colorType() is
+        kGray_8_SkColorType, or kAlpha_8_SkColorType; dst SkColorType must match.
+        If SkPixmap colorType() is kGray_8_SkColorType, dst SkColorSpace must match.
+        If SkPixmap alphaType() is kOpaque_SkAlphaType, dst SkAlphaType must
+        match. If SkPixmap colorSpace() is nullptr, dst SkColorSpace must match. Returns
+        false if pixel conversion is not possible.
+
+        Returns false if SkBitmap width() or height() is zero or negative.
+
+        Scales the image, with filterQuality, to match dst.width() and dst.height().
+        filterQuality kNone_SkFilterQuality is fastest, typically implemented with
+        nearest neighbor filter. kLow_SkFilterQuality is typically implemented with
+        bilerp filter. kMedium_SkFilterQuality is typically implemented with
+        bilerp filter, and mip-map filter when size is reduced.
+        kHigh_SkFilterQuality is slowest, typically implemented with bicubic filter.
+
+        @param dst            SkImageInfo and pixel address to write to
+        @param filterQuality  one of: kNone_SkFilterQuality, kLow_SkFilterQuality,
+                              kMedium_SkFilterQuality, kHigh_SkFilterQuality
+        @return               true if pixels are scaled to fit dst
+    */
+    bool scalePixels(const SkPixmap& dst, SkFilterQuality filterQuality) const;
+
+    /** Writes color to pixels bounded by subset; returns true on success.
+        Returns false if colorType() is kUnknown_SkColorType, or if subset does
+        not intersect bounds().
+
+        @param color   unpremultiplied color to write
+        @param subset  bounding integer SkRect of written pixels
+        @return        true if pixels are changed
+    */
+    bool erase(SkColor color, const SkIRect& subset) const;
+
+    /** Writes color to pixels inside bounds(); returns true on success.
+        Returns false if colorType() is kUnknown_SkColorType, or if bounds()
+        is empty.
+
+        @param color  unpremultiplied color to write
+        @return       true if pixels are changed
+    */
+    bool erase(SkColor color) const { return this->erase(color, this->bounds()); }
+
+    /** Writes color to pixels bounded by subset; returns true on success.
+        if subset is nullptr, writes colors pixels inside bounds(). Returns false if
+        colorType() is kUnknown_SkColorType, if subset is not nullptr and does
+        not intersect bounds(), or if subset is nullptr and bounds() is empty.
+
+        @param color   unpremultiplied color to write
+        @param subset  bounding integer SkRect of pixels to write; may be nullptr
+        @return        true if pixels are changed
+    */
+    bool erase(const SkColor4f& color, const SkIRect* subset = nullptr) const;
+
+private:
+    const void*     fPixels;
+    size_t          fRowBytes;
+    SkImageInfo     fInfo;
+
+    friend class SkPixmapPriv;
+};
+
+#endif

+ 45 - 0
skia/include/core/SkPngChunkReader.h

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkPngChunkReader_DEFINED
+#define SkPngChunkReader_DEFINED
+
+#include "SkTypes.h"
+#include "SkRefCnt.h"
+
+/**
+ *  SkPngChunkReader
+ *
+ *  Base class for optional callbacks to retrieve meta/chunk data out of a PNG
+ *  encoded image as it is being decoded.
+ *  Used by SkCodec.
+ */
+class SkPngChunkReader : public SkRefCnt {
+public:
+    /**
+     *  This will be called by the decoder when it sees an unknown chunk.
+     *
+     *  Use by SkCodec:
+     *  Depending on the location of the unknown chunks, this callback may be
+     *  called by
+     *      - the factory (NewFromStream/NewFromData)
+     *      - getPixels
+     *      - startScanlineDecode
+     *      - the first call to getScanlines/skipScanlines
+     *  The callback may be called from a different thread (e.g. if the SkCodec
+     *  is passed to another thread), and it may be called multiple times, if
+     *  the SkCodec is used multiple times.
+     *
+     *  @param tag Name for this type of chunk.
+     *  @param data Data to be interpreted by the subclass.
+     *  @param length Number of bytes of data in the chunk.
+     *  @return true to continue decoding, or false to indicate an error, which
+     *      will cause the decoder to not return the image.
+     */
+    virtual bool readChunk(const char tag[], const void* data, size_t length) = 0;
+};
+#endif // SkPngChunkReader_DEFINED

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.