DisplayListPlayerSkia.cpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  1. /*
  2. * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <core/SkBitmap.h>
  7. #include <core/SkBlurTypes.h>
  8. #include <core/SkCanvas.h>
  9. #include <core/SkColorFilter.h>
  10. #include <core/SkFont.h>
  11. #include <core/SkFontMgr.h>
  12. #include <core/SkMaskFilter.h>
  13. #include <core/SkPath.h>
  14. #include <core/SkPathBuilder.h>
  15. #include <core/SkPathEffect.h>
  16. #include <core/SkRRect.h>
  17. #include <core/SkSurface.h>
  18. #include <effects/SkDashPathEffect.h>
  19. #include <effects/SkGradientShader.h>
  20. #include <effects/SkImageFilters.h>
  21. #include <effects/SkRuntimeEffect.h>
  22. #include <gpu/GrDirectContext.h>
  23. #include <gpu/ganesh/SkSurfaceGanesh.h>
  24. #include <pathops/SkPathOps.h>
  25. #include <LibGfx/Font/ScaledFont.h>
  26. #include <LibGfx/PathSkia.h>
  27. #include <LibWeb/CSS/ComputedValues.h>
  28. #include <LibWeb/Painting/DisplayListPlayerSkia.h>
  29. #include <LibWeb/Painting/ShadowPainting.h>
  30. #ifdef USE_VULKAN
  31. # include <gpu/ganesh/vk/GrVkDirectContext.h>
  32. # include <gpu/vk/VulkanBackendContext.h>
  33. # include <gpu/vk/VulkanExtensions.h>
  34. #endif
  35. #ifdef AK_OS_MACOS
  36. # include <gpu/GrBackendSurface.h>
  37. # include <gpu/ganesh/mtl/GrMtlBackendContext.h>
  38. # include <gpu/ganesh/mtl/GrMtlBackendSurface.h>
  39. # include <gpu/ganesh/mtl/GrMtlDirectContext.h>
  40. #endif
  41. namespace Web::Painting {
  42. class DisplayListPlayerSkia::SkiaSurface {
  43. public:
  44. SkCanvas& canvas() const { return *m_surface->getCanvas(); }
  45. SkiaSurface(sk_sp<SkSurface> surface)
  46. : m_surface(move(surface))
  47. {
  48. }
  49. void read_into_bitmap(Gfx::Bitmap& bitmap)
  50. {
  51. auto image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
  52. SkPixmap pixmap(image_info, bitmap.begin(), bitmap.pitch());
  53. m_surface->readPixels(pixmap, 0, 0);
  54. }
  55. sk_sp<SkSurface> make_surface(int width, int height)
  56. {
  57. return m_surface->makeSurface(width, height);
  58. }
  59. private:
  60. sk_sp<SkSurface> m_surface;
  61. };
  62. #ifdef USE_VULKAN
  63. class SkiaVulkanBackendContext final : public SkiaBackendContext {
  64. AK_MAKE_NONCOPYABLE(SkiaVulkanBackendContext);
  65. AK_MAKE_NONMOVABLE(SkiaVulkanBackendContext);
  66. public:
  67. SkiaVulkanBackendContext(sk_sp<GrDirectContext> context, NonnullOwnPtr<skgpu::VulkanExtensions> extensions)
  68. : m_context(move(context))
  69. , m_extensions(move(extensions))
  70. {
  71. }
  72. ~SkiaVulkanBackendContext() override {};
  73. void flush_and_submit() override
  74. {
  75. m_context->flush();
  76. m_context->submit(GrSyncCpu::kYes);
  77. }
  78. sk_sp<SkSurface> create_surface(int width, int height)
  79. {
  80. auto image_info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
  81. return SkSurfaces::RenderTarget(m_context.get(), skgpu::Budgeted::kYes, image_info);
  82. }
  83. skgpu::VulkanExtensions const* extensions() const { return m_extensions.ptr(); }
  84. private:
  85. sk_sp<GrDirectContext> m_context;
  86. NonnullOwnPtr<skgpu::VulkanExtensions> m_extensions;
  87. };
  88. OwnPtr<SkiaBackendContext> DisplayListPlayerSkia::create_vulkan_context(Core::VulkanContext& vulkan_context)
  89. {
  90. skgpu::VulkanBackendContext backend_context;
  91. backend_context.fInstance = vulkan_context.instance;
  92. backend_context.fDevice = vulkan_context.logical_device;
  93. backend_context.fQueue = vulkan_context.graphics_queue;
  94. backend_context.fPhysicalDevice = vulkan_context.physical_device;
  95. backend_context.fMaxAPIVersion = vulkan_context.api_version;
  96. backend_context.fGetProc = [](char const* proc_name, VkInstance instance, VkDevice device) {
  97. if (device != VK_NULL_HANDLE) {
  98. return vkGetDeviceProcAddr(device, proc_name);
  99. }
  100. return vkGetInstanceProcAddr(instance, proc_name);
  101. };
  102. auto extensions = make<skgpu::VulkanExtensions>();
  103. backend_context.fVkExtensions = extensions.ptr();
  104. sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeVulkan(backend_context);
  105. VERIFY(ctx);
  106. return make<SkiaVulkanBackendContext>(ctx, move(extensions));
  107. }
  108. DisplayListPlayerSkia::DisplayListPlayerSkia(SkiaBackendContext& context, Gfx::Bitmap& bitmap)
  109. {
  110. VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRA8888);
  111. auto surface = static_cast<SkiaVulkanBackendContext&>(context).create_surface(bitmap.width(), bitmap.height());
  112. m_surface = make<SkiaSurface>(surface);
  113. m_flush_context = [&bitmap, &surface = m_surface, &context] {
  114. context.flush_and_submit();
  115. surface->read_into_bitmap(bitmap);
  116. };
  117. }
  118. #endif
  119. #ifdef AK_OS_MACOS
  120. class SkiaMetalBackendContext final : public SkiaBackendContext {
  121. AK_MAKE_NONCOPYABLE(SkiaMetalBackendContext);
  122. AK_MAKE_NONMOVABLE(SkiaMetalBackendContext);
  123. public:
  124. SkiaMetalBackendContext(sk_sp<GrDirectContext> context)
  125. : m_context(move(context))
  126. {
  127. }
  128. ~SkiaMetalBackendContext() override {};
  129. sk_sp<SkSurface> wrap_metal_texture(Core::MetalTexture& metal_texture)
  130. {
  131. GrMtlTextureInfo mtl_info;
  132. mtl_info.fTexture = sk_ret_cfp(metal_texture.texture());
  133. auto backend_render_target = GrBackendRenderTargets::MakeMtl(metal_texture.width(), metal_texture.height(), mtl_info);
  134. return SkSurfaces::WrapBackendRenderTarget(m_context.get(), backend_render_target, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr, nullptr);
  135. }
  136. void flush_and_submit() override
  137. {
  138. m_context->flush();
  139. m_context->submit(GrSyncCpu::kYes);
  140. }
  141. private:
  142. sk_sp<GrDirectContext> m_context;
  143. };
  144. OwnPtr<SkiaBackendContext> DisplayListPlayerSkia::create_metal_context(Core::MetalContext const& metal_context)
  145. {
  146. GrMtlBackendContext backend_context;
  147. backend_context.fDevice.retain((GrMTLHandle)metal_context.device());
  148. backend_context.fQueue.retain((GrMTLHandle)metal_context.queue());
  149. sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeMetal(backend_context);
  150. return make<SkiaMetalBackendContext>(ctx);
  151. }
  152. DisplayListPlayerSkia::DisplayListPlayerSkia(SkiaBackendContext& context, Core::MetalTexture& metal_texture)
  153. {
  154. auto image_info = SkImageInfo::Make(metal_texture.width(), metal_texture.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
  155. VERIFY(is<SkiaMetalBackendContext>(context));
  156. auto surface = static_cast<SkiaMetalBackendContext&>(context).wrap_metal_texture(metal_texture);
  157. if (!surface) {
  158. dbgln("Failed to create Skia surface from Metal texture");
  159. VERIFY_NOT_REACHED();
  160. }
  161. m_surface = make<SkiaSurface>(surface);
  162. m_flush_context = [&context] mutable {
  163. context.flush_and_submit();
  164. };
  165. }
  166. #endif
  167. DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::Bitmap& bitmap)
  168. {
  169. VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRA8888);
  170. auto image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
  171. auto surface = SkSurfaces::WrapPixels(image_info, bitmap.begin(), bitmap.pitch());
  172. VERIFY(surface);
  173. m_surface = make<SkiaSurface>(surface);
  174. }
  175. DisplayListPlayerSkia::~DisplayListPlayerSkia()
  176. {
  177. if (m_flush_context)
  178. m_flush_context();
  179. }
  180. static SkPoint to_skia_point(auto const& point)
  181. {
  182. return SkPoint::Make(point.x(), point.y());
  183. }
  184. static SkRect to_skia_rect(auto const& rect)
  185. {
  186. return SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
  187. }
  188. static SkColor to_skia_color(Gfx::Color const& color)
  189. {
  190. return SkColorSetARGB(color.alpha(), color.red(), color.green(), color.blue());
  191. }
  192. static SkColor4f to_skia_color4f(Gfx::Color const& color)
  193. {
  194. return {
  195. .fR = color.red() / 255.0f,
  196. .fG = color.green() / 255.0f,
  197. .fB = color.blue() / 255.0f,
  198. .fA = color.alpha() / 255.0f,
  199. };
  200. }
  201. static sk_sp<SkImageFilter> to_skia_image_filter(CSS::ResolvedFilter::FilterFunction const& function)
  202. {
  203. // See: https://drafts.fxtf.org/filter-effects-1/#supported-filter-functions
  204. return function.visit(
  205. [&](CSS::ResolvedFilter::Blur const& blur_filter) {
  206. return SkImageFilters::Blur(blur_filter.radius, blur_filter.radius, nullptr);
  207. },
  208. [&](CSS::ResolvedFilter::Color const& color) {
  209. auto amount = clamp(color.amount, 0.0f, 1.0f);
  210. // Matrices are taken from https://drafts.fxtf.org/filter-effects-1/#FilterPrimitiveRepresentation
  211. sk_sp<SkColorFilter> color_filter;
  212. switch (color.type) {
  213. case CSS::FilterOperation::Color::Type::Grayscale: {
  214. float matrix[20] = {
  215. 0.2126f + 0.7874f * (1 - amount), 0.7152f - 0.7152f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
  216. 0.2126f - 0.2126f * (1 - amount), 0.7152f + 0.2848f * (1 - amount), 0.0722f - 0.0722f * (1 - amount), 0, 0,
  217. 0.2126f - 0.2126f * (1 - amount), 0.7152f - 0.7152f * (1 - amount), 0.0722f + 0.9278f * (1 - amount), 0, 0,
  218. 0, 0, 0, 1, 0
  219. };
  220. color_filter = SkColorFilters::Matrix(matrix);
  221. break;
  222. }
  223. case CSS::FilterOperation::Color::Type::Brightness: {
  224. float matrix[20] = {
  225. amount, 0, 0, 0, 0,
  226. 0, amount, 0, 0, 0,
  227. 0, 0, amount, 0, 0,
  228. 0, 0, 0, 1, 0
  229. };
  230. color_filter = SkColorFilters::Matrix(matrix);
  231. break;
  232. }
  233. case CSS::FilterOperation::Color::Type::Contrast: {
  234. float intercept = -(0.5f * amount) + 0.5f;
  235. float matrix[20] = {
  236. amount, 0, 0, 0, intercept,
  237. 0, amount, 0, 0, intercept,
  238. 0, 0, amount, 0, intercept,
  239. 0, 0, 0, 1, 0
  240. };
  241. color_filter = SkColorFilters::Matrix(matrix);
  242. break;
  243. }
  244. case CSS::FilterOperation::Color::Type::Invert: {
  245. float matrix[20] = {
  246. 1 - 2 * amount, 0, 0, 0, amount,
  247. 0, 1 - 2 * amount, 0, 0, amount,
  248. 0, 0, 1 - 2 * amount, 0, amount,
  249. 0, 0, 0, 1, 0
  250. };
  251. color_filter = SkColorFilters::Matrix(matrix);
  252. break;
  253. }
  254. case CSS::FilterOperation::Color::Type::Opacity: {
  255. float matrix[20] = {
  256. 1, 0, 0, 0, 0,
  257. 0, 1, 0, 0, 0,
  258. 0, 0, 1, 0, 0,
  259. 0, 0, 0, amount, 0
  260. };
  261. color_filter = SkColorFilters::Matrix(matrix);
  262. break;
  263. }
  264. case CSS::FilterOperation::Color::Type::Sepia: {
  265. float matrix[20] = {
  266. 0.393f + 0.607f * (1 - amount), 0.769f - 0.769f * (1 - amount), 0.189f - 0.189f * (1 - amount), 0, 0,
  267. 0.349f - 0.349f * (1 - amount), 0.686f + 0.314f * (1 - amount), 0.168f - 0.168f * (1 - amount), 0, 0,
  268. 0.272f - 0.272f * (1 - amount), 0.534f - 0.534f * (1 - amount), 0.131f + 0.869f * (1 - amount), 0, 0,
  269. 0, 0, 0, 1, 0
  270. };
  271. color_filter = SkColorFilters::Matrix(matrix);
  272. break;
  273. }
  274. case CSS::FilterOperation::Color::Type::Saturate: {
  275. float matrix[20] = {
  276. 0.213f + 0.787f * amount, 0.715f - 0.715f * amount, 0.072f - 0.072f * amount, 0, 0,
  277. 0.213f - 0.213f * amount, 0.715f + 0.285f * amount, 0.072f - 0.072f * amount, 0, 0,
  278. 0.213f - 0.213f * amount, 0.715f - 0.715f * amount, 0.072f + 0.928f * amount, 0, 0,
  279. 0, 0, 0, 1, 0
  280. };
  281. color_filter = SkColorFilters::Matrix(matrix);
  282. break;
  283. }
  284. default:
  285. VERIFY_NOT_REACHED();
  286. }
  287. return SkImageFilters::ColorFilter(color_filter, nullptr);
  288. },
  289. [&](CSS::ResolvedFilter::HueRotate const& hue_rotate) {
  290. float radians = AK::to_radians(hue_rotate.angle_degrees);
  291. auto cosA = cos(radians);
  292. auto sinA = sin(radians);
  293. auto a00 = 0.213f + cosA * 0.787f - sinA * 0.213f;
  294. auto a01 = 0.715f - cosA * 0.715f - sinA * 0.715f;
  295. auto a02 = 0.072f - cosA * 0.072f + sinA * 0.928f;
  296. auto a10 = 0.213f - cosA * 0.213f + sinA * 0.143f;
  297. auto a11 = 0.715f + cosA * 0.285f + sinA * 0.140f;
  298. auto a12 = 0.072f - cosA * 0.072f - sinA * 0.283f;
  299. auto a20 = 0.213f - cosA * 0.213f - sinA * 0.787f;
  300. auto a21 = 0.715f - cosA * 0.715f + sinA * 0.715f;
  301. auto a22 = 0.072f + cosA * 0.928f + sinA * 0.072f;
  302. float matrix[20] = {
  303. a00, a01, a02, 0, 0,
  304. a10, a11, a12, 0, 0,
  305. a20, a21, a22, 0, 0,
  306. 0, 0, 0, 1, 0
  307. };
  308. auto color_filter = SkColorFilters::Matrix(matrix);
  309. return SkImageFilters::ColorFilter(color_filter, nullptr);
  310. },
  311. [&](CSS::ResolvedFilter::DropShadow const&) {
  312. dbgln("TODO: Implement drop-shadow() filter function!");
  313. return sk_sp<SkImageFilter> {};
  314. });
  315. }
  316. static SkPath to_skia_path(Gfx::Path const& path)
  317. {
  318. return static_cast<Gfx::PathImplSkia const&>(path.impl()).sk_path();
  319. }
  320. static SkPathFillType to_skia_path_fill_type(Gfx::WindingRule winding_rule)
  321. {
  322. switch (winding_rule) {
  323. case Gfx::WindingRule::Nonzero:
  324. return SkPathFillType::kWinding;
  325. case Gfx::WindingRule::EvenOdd:
  326. return SkPathFillType::kEvenOdd;
  327. }
  328. VERIFY_NOT_REACHED();
  329. }
  330. static SkRRect to_skia_rrect(auto const& rect, CornerRadii const& corner_radii)
  331. {
  332. SkRRect rrect;
  333. SkVector radii[4];
  334. radii[0].set(corner_radii.top_left.horizontal_radius, corner_radii.top_left.vertical_radius);
  335. radii[1].set(corner_radii.top_right.horizontal_radius, corner_radii.top_right.vertical_radius);
  336. radii[2].set(corner_radii.bottom_right.horizontal_radius, corner_radii.bottom_right.vertical_radius);
  337. radii[3].set(corner_radii.bottom_left.horizontal_radius, corner_radii.bottom_left.vertical_radius);
  338. rrect.setRectRadii(to_skia_rect(rect), radii);
  339. return rrect;
  340. }
  341. static SkColorType to_skia_color_type(Gfx::BitmapFormat format)
  342. {
  343. switch (format) {
  344. case Gfx::BitmapFormat::Invalid:
  345. return kUnknown_SkColorType;
  346. case Gfx::BitmapFormat::BGRA8888:
  347. case Gfx::BitmapFormat::BGRx8888:
  348. return kBGRA_8888_SkColorType;
  349. case Gfx::BitmapFormat::RGBA8888:
  350. return kRGBA_8888_SkColorType;
  351. default:
  352. return kUnknown_SkColorType;
  353. }
  354. }
  355. static SkBitmap to_skia_bitmap(Gfx::Bitmap const& bitmap)
  356. {
  357. SkColorType color_type = to_skia_color_type(bitmap.format());
  358. SkAlphaType alpha_type = bitmap.alpha_type() == Gfx::AlphaType::Premultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
  359. SkImageInfo image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), color_type, alpha_type);
  360. SkBitmap sk_bitmap;
  361. sk_bitmap.setInfo(image_info);
  362. if (!sk_bitmap.installPixels(image_info, const_cast<Gfx::ARGB32*>(bitmap.begin()), bitmap.width() * 4)) {
  363. VERIFY_NOT_REACHED();
  364. }
  365. sk_bitmap.setImmutable();
  366. return sk_bitmap;
  367. }
  368. static SkMatrix to_skia_matrix(Gfx::AffineTransform const& affine_transform)
  369. {
  370. SkScalar affine[6];
  371. affine[0] = affine_transform.a();
  372. affine[1] = affine_transform.b();
  373. affine[2] = affine_transform.c();
  374. affine[3] = affine_transform.d();
  375. affine[4] = affine_transform.e();
  376. affine[5] = affine_transform.f();
  377. SkMatrix matrix;
  378. matrix.setAffine(affine);
  379. return matrix;
  380. }
  381. static SkSamplingOptions to_skia_sampling_options(Gfx::ScalingMode scaling_mode)
  382. {
  383. switch (scaling_mode) {
  384. case Gfx::ScalingMode::NearestNeighbor:
  385. case Gfx::ScalingMode::SmoothPixels:
  386. return SkSamplingOptions(SkFilterMode::kNearest);
  387. case Gfx::ScalingMode::BilinearBlend:
  388. return SkSamplingOptions(SkFilterMode::kLinear);
  389. case Gfx::ScalingMode::BoxSampling:
  390. return SkSamplingOptions(SkCubicResampler::Mitchell());
  391. default:
  392. VERIFY_NOT_REACHED();
  393. }
  394. }
  395. DisplayListPlayerSkia::SkiaSurface& DisplayListPlayerSkia::surface() const
  396. {
  397. return static_cast<SkiaSurface&>(*m_surface);
  398. }
  399. void DisplayListPlayerSkia::draw_glyph_run(DrawGlyphRun const& command)
  400. {
  401. auto const& gfx_font = static_cast<Gfx::ScaledFont const&>(command.glyph_run->font());
  402. auto sk_font = gfx_font.skia_font(command.scale);
  403. auto glyph_count = command.glyph_run->glyphs().size();
  404. Vector<SkGlyphID> glyphs;
  405. glyphs.ensure_capacity(glyph_count);
  406. Vector<SkPoint> positions;
  407. positions.ensure_capacity(glyph_count);
  408. auto font_ascent = gfx_font.pixel_metrics().ascent;
  409. for (auto const& glyph : command.glyph_run->glyphs()) {
  410. auto transformed_glyph = glyph;
  411. transformed_glyph.position.set_y(glyph.position.y() + font_ascent);
  412. transformed_glyph.position = transformed_glyph.position.scaled(command.scale);
  413. auto const& point = transformed_glyph.position;
  414. glyphs.append(transformed_glyph.glyph_id);
  415. positions.append(to_skia_point(point));
  416. }
  417. SkPaint paint;
  418. paint.setColor(to_skia_color(command.color));
  419. surface().canvas().drawGlyphs(glyphs.size(), glyphs.data(), positions.data(), to_skia_point(command.translation), sk_font, paint);
  420. }
  421. void DisplayListPlayerSkia::fill_rect(FillRect const& command)
  422. {
  423. auto const& rect = command.rect;
  424. auto& canvas = surface().canvas();
  425. SkPaint paint;
  426. paint.setColor(to_skia_color(command.color));
  427. canvas.drawRect(to_skia_rect(rect), paint);
  428. }
  429. void DisplayListPlayerSkia::draw_scaled_bitmap(DrawScaledBitmap const& command)
  430. {
  431. auto src_rect = to_skia_rect(command.src_rect);
  432. auto dst_rect = to_skia_rect(command.dst_rect);
  433. auto bitmap = to_skia_bitmap(command.bitmap);
  434. auto image = SkImages::RasterFromBitmap(bitmap);
  435. auto& canvas = surface().canvas();
  436. SkPaint paint;
  437. canvas.drawImageRect(image, src_rect, dst_rect, to_skia_sampling_options(command.scaling_mode), &paint, SkCanvas::kStrict_SrcRectConstraint);
  438. }
  439. void DisplayListPlayerSkia::draw_scaled_immutable_bitmap(DrawScaledImmutableBitmap const& command)
  440. {
  441. auto src_rect = to_skia_rect(command.src_rect);
  442. auto dst_rect = to_skia_rect(command.dst_rect);
  443. auto bitmap = to_skia_bitmap(command.bitmap->bitmap());
  444. auto image = SkImages::RasterFromBitmap(bitmap);
  445. auto& canvas = surface().canvas();
  446. SkPaint paint;
  447. canvas.drawImageRect(image, src_rect, dst_rect, to_skia_sampling_options(command.scaling_mode), &paint, SkCanvas::kStrict_SrcRectConstraint);
  448. }
  449. void DisplayListPlayerSkia::draw_repeated_immutable_bitmap(DrawRepeatedImmutableBitmap const& command)
  450. {
  451. auto bitmap = to_skia_bitmap(command.bitmap->bitmap());
  452. auto image = SkImages::RasterFromBitmap(bitmap);
  453. SkMatrix matrix;
  454. auto dst_rect = command.dst_rect.to_type<float>();
  455. auto src_size = command.bitmap->size().to_type<float>();
  456. matrix.setScale(dst_rect.width() / src_size.width(), dst_rect.height() / src_size.height());
  457. matrix.postTranslate(dst_rect.x(), dst_rect.y());
  458. auto sampling_options = to_skia_sampling_options(command.scaling_mode);
  459. auto tile_mode_x = command.repeat.x ? SkTileMode::kRepeat : SkTileMode::kDecal;
  460. auto tile_mode_y = command.repeat.y ? SkTileMode::kRepeat : SkTileMode::kDecal;
  461. auto shader = image->makeShader(tile_mode_x, tile_mode_y, sampling_options, matrix);
  462. SkPaint paint;
  463. paint.setShader(shader);
  464. auto& canvas = surface().canvas();
  465. canvas.drawPaint(paint);
  466. }
  467. void DisplayListPlayerSkia::add_clip_rect(AddClipRect const& command)
  468. {
  469. auto& canvas = surface().canvas();
  470. auto const& rect = command.rect;
  471. canvas.clipRect(to_skia_rect(rect));
  472. }
  473. void DisplayListPlayerSkia::save(Save const&)
  474. {
  475. auto& canvas = surface().canvas();
  476. canvas.save();
  477. }
  478. void DisplayListPlayerSkia::restore(Restore const&)
  479. {
  480. auto& canvas = surface().canvas();
  481. canvas.restore();
  482. }
  483. void DisplayListPlayerSkia::translate(Translate const& command)
  484. {
  485. auto& canvas = surface().canvas();
  486. canvas.translate(command.delta.x(), command.delta.y());
  487. }
  488. void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& command)
  489. {
  490. auto& canvas = surface().canvas();
  491. auto affine_transform = Gfx::extract_2d_affine_transform(command.transform.matrix);
  492. auto new_transform = Gfx::AffineTransform {}
  493. .translate(command.transform.origin)
  494. .multiply(affine_transform)
  495. .translate(-command.transform.origin);
  496. auto matrix = to_skia_matrix(new_transform);
  497. if (!command.filter.is_none()) {
  498. sk_sp<SkImageFilter> image_filter;
  499. auto append_filter = [&image_filter](auto new_filter) {
  500. if (image_filter)
  501. image_filter = SkImageFilters::Compose(new_filter, image_filter);
  502. else
  503. image_filter = new_filter;
  504. };
  505. // Apply filters in order
  506. for (auto const& filter_function : command.filter.filters)
  507. append_filter(to_skia_image_filter(filter_function));
  508. // We apply opacity as a color filter here so we only need to save and restore a single layer.
  509. if (command.opacity < 1) {
  510. append_filter(to_skia_image_filter(CSS::ResolvedFilter::FilterFunction {
  511. CSS::ResolvedFilter::Color {
  512. CSS::FilterOperation::Color::Type::Opacity,
  513. command.opacity,
  514. },
  515. }));
  516. }
  517. SkPaint paint;
  518. paint.setImageFilter(image_filter);
  519. canvas.saveLayer(nullptr, &paint);
  520. } else if (command.opacity < 1) {
  521. auto source_paintable_rect = to_skia_rect(command.source_paintable_rect);
  522. SkRect dest;
  523. matrix.mapRect(&dest, source_paintable_rect);
  524. canvas.saveLayerAlphaf(&dest, command.opacity);
  525. } else {
  526. canvas.save();
  527. }
  528. if (command.clip_path.has_value())
  529. canvas.clipPath(to_skia_path(command.clip_path.value()), true);
  530. canvas.concat(matrix);
  531. }
  532. void DisplayListPlayerSkia::pop_stacking_context(PopStackingContext const&)
  533. {
  534. surface().canvas().restore();
  535. }
  536. static ColorStopList replace_transition_hints_with_normal_color_stops(ColorStopList const& color_stop_list)
  537. {
  538. ColorStopList stops_with_replaced_transition_hints;
  539. auto const& first_color_stop = color_stop_list.first();
  540. // First color stop in the list should never have transition hint value
  541. VERIFY(!first_color_stop.transition_hint.has_value());
  542. stops_with_replaced_transition_hints.empend(first_color_stop.color, first_color_stop.position);
  543. // This loop replaces transition hints with five regular points, calculated using the
  544. // formula defined in the spec. After rendering using linear interpolation, this will
  545. // produce a result close enough to that obtained if the color of each point were calculated
  546. // using the non-linear formula from the spec.
  547. for (size_t i = 1; i < color_stop_list.size(); i++) {
  548. auto const& color_stop = color_stop_list[i];
  549. if (!color_stop.transition_hint.has_value()) {
  550. stops_with_replaced_transition_hints.empend(color_stop.color, color_stop.position);
  551. continue;
  552. }
  553. auto const& previous_color_stop = color_stop_list[i - 1];
  554. auto const& next_color_stop = color_stop_list[i];
  555. auto distance_between_stops = next_color_stop.position - previous_color_stop.position;
  556. auto transition_hint = color_stop.transition_hint.value();
  557. Array<float, 5> const transition_hint_relative_sampling_positions = {
  558. transition_hint * 0.33f,
  559. transition_hint * 0.66f,
  560. transition_hint,
  561. transition_hint + (1 - transition_hint) * 0.33f,
  562. transition_hint + (1 - transition_hint) * 0.66f,
  563. };
  564. for (auto const& transition_hint_relative_sampling_position : transition_hint_relative_sampling_positions) {
  565. auto position = previous_color_stop.position + transition_hint_relative_sampling_position * distance_between_stops;
  566. auto value = color_stop_step(previous_color_stop, next_color_stop, position);
  567. auto color = previous_color_stop.color.interpolate(next_color_stop.color, value);
  568. stops_with_replaced_transition_hints.empend(color, position);
  569. }
  570. stops_with_replaced_transition_hints.empend(color_stop.color, color_stop.position);
  571. }
  572. return stops_with_replaced_transition_hints;
  573. }
  574. static ColorStopList expand_repeat_length(ColorStopList const& color_stop_list, float repeat_length)
  575. {
  576. // https://drafts.csswg.org/css-images/#repeating-gradients
  577. // When rendered, however, the color-stops are repeated infinitely in both directions, with their
  578. // positions shifted by multiples of the difference between the last specified color-stop’s position
  579. // and the first specified color-stop’s position. For example, repeating-linear-gradient(red 10px, blue 50px)
  580. // is equivalent to linear-gradient(..., red -30px, blue 10px, red 10px, blue 50px, red 50px, blue 90px, ...).
  581. auto first_stop_position = color_stop_list.first().position;
  582. int const negative_repeat_count = AK::ceil(first_stop_position / repeat_length);
  583. int const positive_repeat_count = AK::ceil((1.0f - first_stop_position) / repeat_length);
  584. ColorStopList color_stop_list_with_expanded_repeat = color_stop_list;
  585. auto get_color_between_stops = [](float position, auto const& current_stop, auto const& previous_stop) {
  586. auto distance_between_stops = current_stop.position - previous_stop.position;
  587. auto percentage = (position - previous_stop.position) / distance_between_stops;
  588. return previous_stop.color.interpolate(current_stop.color, percentage);
  589. };
  590. for (auto repeat_count = 1; repeat_count <= negative_repeat_count; repeat_count++) {
  591. for (auto stop : color_stop_list.in_reverse()) {
  592. stop.position += repeat_length * static_cast<float>(-repeat_count);
  593. if (stop.position < 0) {
  594. stop.color = get_color_between_stops(0.0f, stop, color_stop_list_with_expanded_repeat.first());
  595. color_stop_list_with_expanded_repeat.prepend(stop);
  596. break;
  597. }
  598. color_stop_list_with_expanded_repeat.prepend(stop);
  599. }
  600. }
  601. for (auto repeat_count = 0; repeat_count < positive_repeat_count; repeat_count++) {
  602. for (auto stop : color_stop_list) {
  603. stop.position += repeat_length * static_cast<float>(repeat_count);
  604. if (stop.position > 1) {
  605. stop.color = get_color_between_stops(1.0f, stop, color_stop_list_with_expanded_repeat.last());
  606. color_stop_list_with_expanded_repeat.append(stop);
  607. break;
  608. }
  609. color_stop_list_with_expanded_repeat.append(stop);
  610. }
  611. }
  612. return color_stop_list_with_expanded_repeat;
  613. }
  614. void DisplayListPlayerSkia::paint_linear_gradient(PaintLinearGradient const& command)
  615. {
  616. auto const& linear_gradient_data = command.linear_gradient_data;
  617. auto color_stop_list = linear_gradient_data.color_stops.list;
  618. auto const& repeat_length = linear_gradient_data.color_stops.repeat_length;
  619. VERIFY(!color_stop_list.is_empty());
  620. if (repeat_length.has_value())
  621. color_stop_list = expand_repeat_length(color_stop_list, *repeat_length);
  622. auto stops_with_replaced_transition_hints = replace_transition_hints_with_normal_color_stops(color_stop_list);
  623. Vector<SkColor4f> colors;
  624. Vector<SkScalar> positions;
  625. for (size_t stop_index = 0; stop_index < stops_with_replaced_transition_hints.size(); stop_index++) {
  626. auto const& stop = stops_with_replaced_transition_hints[stop_index];
  627. if (stop_index > 0 && stop == stops_with_replaced_transition_hints[stop_index - 1])
  628. continue;
  629. colors.append(to_skia_color4f(stop.color));
  630. positions.append(stop.position);
  631. }
  632. auto const& rect = command.gradient_rect;
  633. auto length = calculate_gradient_length<int>(rect.size(), linear_gradient_data.gradient_angle);
  634. auto bottom = rect.center().translated(0, -length / 2);
  635. auto top = rect.center().translated(0, length / 2);
  636. Array<SkPoint, 2> points;
  637. points[0] = to_skia_point(top);
  638. points[1] = to_skia_point(bottom);
  639. auto center = to_skia_rect(rect).center();
  640. SkMatrix matrix;
  641. matrix.setRotate(linear_gradient_data.gradient_angle, center.x(), center.y());
  642. auto color_space = SkColorSpace::MakeSRGB();
  643. SkGradientShader::Interpolation interpolation = {};
  644. interpolation.fColorSpace = SkGradientShader::Interpolation::ColorSpace::kSRGB;
  645. interpolation.fInPremul = SkGradientShader::Interpolation::InPremul::kYes;
  646. auto shader = SkGradientShader::MakeLinear(points.data(), colors.data(), color_space, positions.data(), positions.size(), SkTileMode::kClamp, interpolation, &matrix);
  647. SkPaint paint;
  648. paint.setShader(shader);
  649. surface().canvas().drawRect(to_skia_rect(rect), paint);
  650. }
  651. static void add_spread_distance_to_border_radius(int& border_radius, int spread_distance)
  652. {
  653. if (border_radius == 0 || spread_distance == 0)
  654. return;
  655. // https://drafts.csswg.org/css-backgrounds/#shadow-shape
  656. // To preserve the box’s shape when spread is applied, the corner radii of the shadow are also increased (decreased,
  657. // for inner shadows) from the border-box (padding-box) radii by adding (subtracting) the spread distance (and flooring
  658. // at zero). However, in order to create a sharper corner when the border radius is small (and thus ensure continuity
  659. // between round and sharp corners), when the border radius is less than the spread distance (or in the case of an inner
  660. // shadow, less than the absolute value of a negative spread distance), the spread distance is first multiplied by the
  661. // proportion 1 + (r-1)^3, where r is the ratio of the border radius to the spread distance, in calculating the corner
  662. // radii of the spread shadow shape.
  663. if (border_radius > AK::abs(spread_distance)) {
  664. border_radius += spread_distance;
  665. } else {
  666. auto r = (float)border_radius / AK::abs(spread_distance);
  667. border_radius += spread_distance * (1 + AK::pow(r - 1, 3.0f));
  668. }
  669. }
  670. void DisplayListPlayerSkia::paint_outer_box_shadow(PaintOuterBoxShadow const& command)
  671. {
  672. auto const& outer_box_shadow_params = command.box_shadow_params;
  673. auto const& color = outer_box_shadow_params.color;
  674. auto const& spread_distance = outer_box_shadow_params.spread_distance;
  675. auto const& blur_radius = outer_box_shadow_params.blur_radius;
  676. auto content_rrect = to_skia_rrect(outer_box_shadow_params.device_content_rect, outer_box_shadow_params.corner_radii);
  677. auto shadow_rect = outer_box_shadow_params.device_content_rect;
  678. shadow_rect.inflate(spread_distance, spread_distance, spread_distance, spread_distance);
  679. auto offset_x = outer_box_shadow_params.offset_x;
  680. auto offset_y = outer_box_shadow_params.offset_y;
  681. shadow_rect.translate_by(offset_x, offset_y);
  682. auto add_spread_distance_to_corner_radius = [&](auto& corner_radius) {
  683. add_spread_distance_to_border_radius(corner_radius.horizontal_radius, spread_distance);
  684. add_spread_distance_to_border_radius(corner_radius.vertical_radius, spread_distance);
  685. };
  686. auto corner_radii = outer_box_shadow_params.corner_radii;
  687. add_spread_distance_to_corner_radius(corner_radii.top_left);
  688. add_spread_distance_to_corner_radius(corner_radii.top_right);
  689. add_spread_distance_to_corner_radius(corner_radii.bottom_right);
  690. add_spread_distance_to_corner_radius(corner_radii.bottom_left);
  691. auto& canvas = surface().canvas();
  692. canvas.save();
  693. canvas.clipRRect(content_rrect, SkClipOp::kDifference, true);
  694. SkPaint paint;
  695. paint.setAntiAlias(true);
  696. paint.setColor(to_skia_color(color));
  697. paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, blur_radius / 2));
  698. auto shadow_rounded_rect = to_skia_rrect(shadow_rect, corner_radii);
  699. canvas.drawRRect(shadow_rounded_rect, paint);
  700. canvas.restore();
  701. }
  702. void DisplayListPlayerSkia::paint_inner_box_shadow(PaintInnerBoxShadow const& command)
  703. {
  704. auto const& outer_box_shadow_params = command.box_shadow_params;
  705. auto color = outer_box_shadow_params.color;
  706. auto device_content_rect = outer_box_shadow_params.device_content_rect;
  707. auto offset_x = outer_box_shadow_params.offset_x;
  708. auto offset_y = outer_box_shadow_params.offset_y;
  709. auto blur_radius = outer_box_shadow_params.blur_radius;
  710. auto spread_distance = outer_box_shadow_params.spread_distance;
  711. auto const& corner_radii = outer_box_shadow_params.corner_radii;
  712. auto outer_shadow_rect = device_content_rect.translated({ offset_x, offset_y });
  713. auto inner_shadow_rect = outer_shadow_rect.inflated(-spread_distance, -spread_distance, -spread_distance, -spread_distance);
  714. outer_shadow_rect.inflate(
  715. blur_radius + offset_y,
  716. blur_radius + abs(offset_x),
  717. blur_radius + abs(offset_y),
  718. blur_radius + offset_x);
  719. auto inner_rect_corner_radii = corner_radii;
  720. auto add_spread_distance_to_corner_radius = [&](auto& corner_radius) {
  721. add_spread_distance_to_border_radius(corner_radius.horizontal_radius, -spread_distance);
  722. add_spread_distance_to_border_radius(corner_radius.vertical_radius, -spread_distance);
  723. };
  724. add_spread_distance_to_corner_radius(inner_rect_corner_radii.top_left);
  725. add_spread_distance_to_corner_radius(inner_rect_corner_radii.top_right);
  726. add_spread_distance_to_corner_radius(inner_rect_corner_radii.bottom_right);
  727. add_spread_distance_to_corner_radius(inner_rect_corner_radii.bottom_left);
  728. auto outer_rect = to_skia_rrect(outer_shadow_rect, corner_radii);
  729. auto inner_rect = to_skia_rrect(inner_shadow_rect, inner_rect_corner_radii);
  730. SkPath outer_path;
  731. outer_path.addRRect(outer_rect);
  732. SkPath inner_path;
  733. inner_path.addRRect(inner_rect);
  734. SkPath result_path;
  735. if (!Op(outer_path, inner_path, SkPathOp::kDifference_SkPathOp, &result_path)) {
  736. VERIFY_NOT_REACHED();
  737. }
  738. auto& canvas = surface().canvas();
  739. SkPaint path_paint;
  740. path_paint.setAntiAlias(true);
  741. path_paint.setColor(to_skia_color(color));
  742. path_paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, blur_radius / 2));
  743. canvas.save();
  744. canvas.clipRRect(to_skia_rrect(device_content_rect, corner_radii), true);
  745. canvas.drawPath(result_path, path_paint);
  746. canvas.restore();
  747. }
  748. void DisplayListPlayerSkia::paint_text_shadow(PaintTextShadow const& command)
  749. {
  750. auto& canvas = surface().canvas();
  751. auto blur_image_filter = SkImageFilters::Blur(command.blur_radius / 2, command.blur_radius / 2, nullptr);
  752. SkPaint blur_paint;
  753. blur_paint.setImageFilter(blur_image_filter);
  754. canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, &blur_paint, nullptr, 0));
  755. draw_glyph_run({
  756. .glyph_run = command.glyph_run,
  757. .color = command.color,
  758. .rect = command.text_rect,
  759. .translation = command.draw_location.to_type<float>() + command.text_rect.location().to_type<float>(),
  760. .scale = command.glyph_run_scale,
  761. });
  762. canvas.restore();
  763. }
  764. void DisplayListPlayerSkia::fill_rect_with_rounded_corners(FillRectWithRoundedCorners const& command)
  765. {
  766. auto const& rect = command.rect;
  767. auto& canvas = surface().canvas();
  768. SkPaint paint;
  769. paint.setColor(to_skia_color(command.color));
  770. paint.setAntiAlias(true);
  771. auto rounded_rect = to_skia_rrect(rect, command.corner_radii);
  772. canvas.drawRRect(rounded_rect, paint);
  773. }
  774. void DisplayListPlayerSkia::fill_path_using_color(FillPathUsingColor const& command)
  775. {
  776. auto& canvas = surface().canvas();
  777. SkPaint paint;
  778. paint.setAntiAlias(true);
  779. paint.setColor(to_skia_color(command.color));
  780. auto path = to_skia_path(command.path);
  781. path.setFillType(to_skia_path_fill_type(command.winding_rule));
  782. path.offset(command.aa_translation.x(), command.aa_translation.y());
  783. canvas.drawPath(path, paint);
  784. }
  785. static SkTileMode to_skia_tile_mode(SVGLinearGradientPaintStyle::SpreadMethod spread_method)
  786. {
  787. switch (spread_method) {
  788. case SVGLinearGradientPaintStyle::SpreadMethod::Pad:
  789. return SkTileMode::kClamp;
  790. case SVGLinearGradientPaintStyle::SpreadMethod::Reflect:
  791. return SkTileMode::kMirror;
  792. case SVGLinearGradientPaintStyle::SpreadMethod::Repeat:
  793. return SkTileMode::kRepeat;
  794. default:
  795. VERIFY_NOT_REACHED();
  796. }
  797. }
  798. static SkPaint paint_style_to_skia_paint(Painting::SVGGradientPaintStyle const& paint_style, Gfx::FloatRect bounding_rect)
  799. {
  800. SkPaint paint;
  801. auto const& color_stops = paint_style.color_stops();
  802. Vector<SkColor> colors;
  803. colors.ensure_capacity(color_stops.size());
  804. Vector<SkScalar> positions;
  805. positions.ensure_capacity(color_stops.size());
  806. for (auto const& color_stop : color_stops) {
  807. colors.append(to_skia_color(color_stop.color));
  808. positions.append(color_stop.position);
  809. }
  810. if (is<SVGLinearGradientPaintStyle>(paint_style)) {
  811. auto const& linear_gradient_paint_style = static_cast<SVGLinearGradientPaintStyle const&>(paint_style);
  812. SkMatrix matrix;
  813. auto scale = linear_gradient_paint_style.scale();
  814. auto start_point = linear_gradient_paint_style.start_point().scaled(scale);
  815. auto end_point = linear_gradient_paint_style.end_point().scaled(scale);
  816. start_point.translate_by(bounding_rect.location());
  817. end_point.translate_by(bounding_rect.location());
  818. Array<SkPoint, 2> points;
  819. points[0] = to_skia_point(start_point);
  820. points[1] = to_skia_point(end_point);
  821. auto shader = SkGradientShader::MakeLinear(points.data(), colors.data(), positions.data(), color_stops.size(), to_skia_tile_mode(paint_style.spread_method()), 0, &matrix);
  822. paint.setShader(shader);
  823. } else if (is<SVGRadialGradientPaintStyle>(paint_style)) {
  824. auto const& radial_gradient_paint_style = static_cast<SVGRadialGradientPaintStyle const&>(paint_style);
  825. SkMatrix matrix;
  826. auto scale = radial_gradient_paint_style.scale();
  827. auto start_center = radial_gradient_paint_style.start_center().scaled(scale);
  828. auto end_center = radial_gradient_paint_style.end_center().scaled(scale);
  829. auto start_radius = radial_gradient_paint_style.start_radius() * scale;
  830. auto end_radius = radial_gradient_paint_style.end_radius() * scale;
  831. start_center.translate_by(bounding_rect.location());
  832. end_center.translate_by(bounding_rect.location());
  833. auto start_sk_point = to_skia_point(start_center);
  834. auto end_sk_point = to_skia_point(end_center);
  835. auto shader = SkGradientShader::MakeTwoPointConical(start_sk_point, start_radius, end_sk_point, end_radius, colors.data(), positions.data(), color_stops.size(), to_skia_tile_mode(paint_style.spread_method()), 0, &matrix);
  836. paint.setShader(shader);
  837. }
  838. return paint;
  839. }
  840. void DisplayListPlayerSkia::fill_path_using_paint_style(FillPathUsingPaintStyle const& command)
  841. {
  842. auto path = to_skia_path(command.path);
  843. path.offset(command.aa_translation.x(), command.aa_translation.y());
  844. path.setFillType(to_skia_path_fill_type(command.winding_rule));
  845. auto paint = paint_style_to_skia_paint(*command.paint_style, command.bounding_rect().to_type<float>());
  846. paint.setAntiAlias(true);
  847. paint.setAlphaf(command.opacity);
  848. surface().canvas().drawPath(path, paint);
  849. }
  850. void DisplayListPlayerSkia::stroke_path_using_color(StrokePathUsingColor const& command)
  851. {
  852. // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
  853. if (!command.thickness)
  854. return;
  855. auto& canvas = surface().canvas();
  856. SkPaint paint;
  857. paint.setAntiAlias(true);
  858. paint.setStyle(SkPaint::kStroke_Style);
  859. paint.setStrokeWidth(command.thickness);
  860. paint.setColor(to_skia_color(command.color));
  861. auto path = to_skia_path(command.path);
  862. path.offset(command.aa_translation.x(), command.aa_translation.y());
  863. canvas.drawPath(path, paint);
  864. }
  865. void DisplayListPlayerSkia::stroke_path_using_paint_style(StrokePathUsingPaintStyle const& command)
  866. {
  867. // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
  868. if (!command.thickness)
  869. return;
  870. auto path = to_skia_path(command.path);
  871. path.offset(command.aa_translation.x(), command.aa_translation.y());
  872. auto paint = paint_style_to_skia_paint(*command.paint_style, command.bounding_rect().to_type<float>());
  873. paint.setAntiAlias(true);
  874. paint.setAlphaf(command.opacity);
  875. paint.setStyle(SkPaint::Style::kStroke_Style);
  876. paint.setStrokeWidth(command.thickness);
  877. surface().canvas().drawPath(path, paint);
  878. }
  879. void DisplayListPlayerSkia::draw_ellipse(DrawEllipse const& command)
  880. {
  881. // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
  882. if (!command.thickness)
  883. return;
  884. auto const& rect = command.rect;
  885. auto& canvas = surface().canvas();
  886. SkPaint paint;
  887. paint.setAntiAlias(true);
  888. paint.setStyle(SkPaint::kStroke_Style);
  889. paint.setStrokeWidth(command.thickness);
  890. paint.setColor(to_skia_color(command.color));
  891. canvas.drawOval(to_skia_rect(rect), paint);
  892. }
  893. void DisplayListPlayerSkia::fill_ellipse(FillEllipse const& command)
  894. {
  895. auto const& rect = command.rect;
  896. auto& canvas = surface().canvas();
  897. SkPaint paint;
  898. paint.setAntiAlias(true);
  899. paint.setColor(to_skia_color(command.color));
  900. canvas.drawOval(to_skia_rect(rect), paint);
  901. }
  902. void DisplayListPlayerSkia::draw_line(DrawLine const& command)
  903. {
  904. // Skia treats zero thickness as a special case and will draw a hairline, while we want to draw nothing.
  905. if (!command.thickness)
  906. return;
  907. auto from = to_skia_point(command.from);
  908. auto to = to_skia_point(command.to);
  909. auto& canvas = surface().canvas();
  910. SkPaint paint;
  911. paint.setAntiAlias(true);
  912. paint.setStrokeWidth(command.thickness);
  913. paint.setColor(to_skia_color(command.color));
  914. switch (command.style) {
  915. case Gfx::LineStyle::Solid:
  916. break;
  917. case Gfx::LineStyle::Dotted: {
  918. auto length = command.to.distance_from(command.from);
  919. auto dot_count = floor(length / (static_cast<float>(command.thickness) * 2));
  920. auto interval = length / dot_count;
  921. SkScalar intervals[] = { 0, interval };
  922. paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
  923. paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
  924. // NOTE: As Skia doesn't render a dot exactly at the end of a line, we need
  925. // to extend it by less then an interval.
  926. auto direction = to - from;
  927. direction.normalize();
  928. to += direction * (interval / 2.0f);
  929. break;
  930. }
  931. case Gfx::LineStyle::Dashed: {
  932. auto length = command.to.distance_from(command.from) + command.thickness;
  933. auto dash_count = floor(length / static_cast<float>(command.thickness) / 4) * 2 + 1;
  934. auto interval = length / dash_count;
  935. SkScalar intervals[] = { interval, interval };
  936. paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 0));
  937. auto direction = to - from;
  938. direction.normalize();
  939. from -= direction * (command.thickness / 2.0f);
  940. to += direction * (command.thickness / 2.0f);
  941. break;
  942. }
  943. }
  944. canvas.drawLine(from, to, paint);
  945. }
  946. void DisplayListPlayerSkia::apply_backdrop_filter(ApplyBackdropFilter const& command)
  947. {
  948. auto& canvas = surface().canvas();
  949. auto rect = to_skia_rect(command.backdrop_region);
  950. canvas.save();
  951. canvas.clipRect(rect);
  952. ScopeGuard guard = [&] { canvas.restore(); };
  953. for (auto const& filter_function : command.backdrop_filter.filters) {
  954. auto image_filter = to_skia_image_filter(filter_function);
  955. canvas.saveLayer(SkCanvas::SaveLayerRec(nullptr, nullptr, image_filter.get(), 0));
  956. canvas.restore();
  957. }
  958. }
  959. void DisplayListPlayerSkia::draw_rect(DrawRect const& command)
  960. {
  961. auto const& rect = command.rect;
  962. auto& canvas = surface().canvas();
  963. SkPaint paint;
  964. paint.setAntiAlias(true);
  965. paint.setStyle(SkPaint::kStroke_Style);
  966. paint.setStrokeWidth(1);
  967. paint.setColor(to_skia_color(command.color));
  968. canvas.drawRect(to_skia_rect(rect), paint);
  969. }
  970. void DisplayListPlayerSkia::paint_radial_gradient(PaintRadialGradient const& command)
  971. {
  972. auto const& radial_gradient_data = command.radial_gradient_data;
  973. auto color_stop_list = radial_gradient_data.color_stops.list;
  974. VERIFY(!color_stop_list.is_empty());
  975. auto const& repeat_length = radial_gradient_data.color_stops.repeat_length;
  976. if (repeat_length.has_value())
  977. color_stop_list = expand_repeat_length(color_stop_list, repeat_length.value());
  978. auto stops_with_replaced_transition_hints = replace_transition_hints_with_normal_color_stops(color_stop_list);
  979. Vector<SkColor4f> colors;
  980. Vector<SkScalar> positions;
  981. for (size_t stop_index = 0; stop_index < stops_with_replaced_transition_hints.size(); stop_index++) {
  982. auto const& stop = stops_with_replaced_transition_hints[stop_index];
  983. if (stop_index > 0 && stop == stops_with_replaced_transition_hints[stop_index - 1])
  984. continue;
  985. colors.append(to_skia_color4f(stop.color));
  986. positions.append(stop.position);
  987. }
  988. auto const& rect = command.rect;
  989. auto center = to_skia_point(command.center.translated(command.rect.location()));
  990. auto const size = command.size.to_type<float>();
  991. SkMatrix matrix;
  992. // Skia does not support specifying of horizontal and vertical radius's separately,
  993. // so instead we apply scale matrix
  994. matrix.setScale(size.width() / size.height(), 1.0f, center.x(), center.y());
  995. SkTileMode tile_mode = SkTileMode::kClamp;
  996. if (repeat_length.has_value())
  997. tile_mode = SkTileMode::kRepeat;
  998. auto color_space = SkColorSpace::MakeSRGB();
  999. SkGradientShader::Interpolation interpolation = {};
  1000. interpolation.fColorSpace = SkGradientShader::Interpolation::ColorSpace::kSRGB;
  1001. interpolation.fInPremul = SkGradientShader::Interpolation::InPremul::kYes;
  1002. auto shader = SkGradientShader::MakeRadial(center, size.height(), colors.data(), color_space, positions.data(), positions.size(), tile_mode, interpolation, &matrix);
  1003. SkPaint paint;
  1004. paint.setAntiAlias(true);
  1005. paint.setShader(shader);
  1006. surface().canvas().drawRect(to_skia_rect(rect), paint);
  1007. }
  1008. void DisplayListPlayerSkia::paint_conic_gradient(PaintConicGradient const& command)
  1009. {
  1010. auto const& conic_gradient_data = command.conic_gradient_data;
  1011. auto color_stop_list = conic_gradient_data.color_stops.list;
  1012. auto const& repeat_length = conic_gradient_data.color_stops.repeat_length;
  1013. if (repeat_length.has_value())
  1014. color_stop_list = expand_repeat_length(color_stop_list, repeat_length.value());
  1015. VERIFY(!color_stop_list.is_empty());
  1016. auto stops_with_replaced_transition_hints = replace_transition_hints_with_normal_color_stops(color_stop_list);
  1017. Vector<SkColor4f> colors;
  1018. Vector<SkScalar> positions;
  1019. for (size_t stop_index = 0; stop_index < stops_with_replaced_transition_hints.size(); stop_index++) {
  1020. auto const& stop = stops_with_replaced_transition_hints[stop_index];
  1021. if (stop_index > 0 && stop == stops_with_replaced_transition_hints[stop_index - 1])
  1022. continue;
  1023. colors.append(to_skia_color4f(stop.color));
  1024. positions.append(stop.position);
  1025. }
  1026. auto const& rect = command.rect;
  1027. auto center = command.position.translated(rect.location()).to_type<float>();
  1028. SkMatrix matrix;
  1029. matrix.setRotate(-90 + conic_gradient_data.start_angle, center.x(), center.y());
  1030. auto color_space = SkColorSpace::MakeSRGB();
  1031. SkGradientShader::Interpolation interpolation = {};
  1032. interpolation.fColorSpace = SkGradientShader::Interpolation::ColorSpace::kSRGB;
  1033. interpolation.fInPremul = SkGradientShader::Interpolation::InPremul::kYes;
  1034. auto shader = SkGradientShader::MakeSweep(center.x(), center.y(), colors.data(), color_space, positions.data(), positions.size(), SkTileMode::kRepeat, 0, 360, interpolation, &matrix);
  1035. SkPaint paint;
  1036. paint.setAntiAlias(true);
  1037. paint.setShader(shader);
  1038. surface().canvas().drawRect(to_skia_rect(rect), paint);
  1039. }
  1040. void DisplayListPlayerSkia::draw_triangle_wave(DrawTriangleWave const&)
  1041. {
  1042. }
  1043. void DisplayListPlayerSkia::add_rounded_rect_clip(AddRoundedRectClip const& command)
  1044. {
  1045. auto rounded_rect = to_skia_rrect(command.border_rect, command.corner_radii);
  1046. auto& canvas = surface().canvas();
  1047. auto clip_op = command.corner_clip == CornerClip::Inside ? SkClipOp::kDifference : SkClipOp::kIntersect;
  1048. canvas.clipRRect(rounded_rect, clip_op, true);
  1049. }
  1050. void DisplayListPlayerSkia::add_mask(AddMask const& command)
  1051. {
  1052. auto const& rect = command.rect;
  1053. if (rect.is_empty())
  1054. return;
  1055. auto mask_surface = m_surface->make_surface(rect.width(), rect.height());
  1056. auto previous_surface = move(m_surface);
  1057. m_surface = make<SkiaSurface>(mask_surface);
  1058. execute(*command.display_list);
  1059. m_surface = move(previous_surface);
  1060. SkMatrix mask_matrix;
  1061. mask_matrix.setTranslate(rect.x(), rect.y());
  1062. auto image = mask_surface->makeImageSnapshot();
  1063. auto shader = image->makeShader(SkSamplingOptions(), mask_matrix);
  1064. surface().canvas().save();
  1065. surface().canvas().clipShader(shader);
  1066. }
  1067. void DisplayListPlayerSkia::paint_nested_display_list(PaintNestedDisplayList const& command)
  1068. {
  1069. auto& canvas = surface().canvas();
  1070. canvas.translate(command.rect.x(), command.rect.y());
  1071. execute(*command.display_list);
  1072. }
  1073. void DisplayListPlayerSkia::paint_scrollbar(PaintScrollBar const& command)
  1074. {
  1075. auto rect = to_skia_rect(command.rect);
  1076. auto radius = rect.width() / 2;
  1077. auto rrect = SkRRect::MakeRectXY(rect, radius, radius);
  1078. auto& canvas = surface().canvas();
  1079. auto fill_color = Color(Color::NamedColor::DarkGray).with_alpha(128);
  1080. SkPaint fill_paint;
  1081. fill_paint.setColor(to_skia_color(fill_color));
  1082. canvas.drawRRect(rrect, fill_paint);
  1083. auto stroke_color = Color(Color::NamedColor::LightGray).with_alpha(128);
  1084. SkPaint stroke_paint;
  1085. stroke_paint.setStroke(true);
  1086. stroke_paint.setStrokeWidth(1);
  1087. stroke_paint.setColor(to_skia_color(stroke_color));
  1088. canvas.drawRRect(rrect, stroke_paint);
  1089. }
  1090. void DisplayListPlayerSkia::apply_opacity(ApplyOpacity const& command)
  1091. {
  1092. auto& canvas = surface().canvas();
  1093. SkPaint paint;
  1094. paint.setAlphaf(command.opacity);
  1095. canvas.saveLayer(nullptr, &paint);
  1096. }
  1097. void DisplayListPlayerSkia::apply_transform(ApplyTransform const& command)
  1098. {
  1099. auto affine_transform = Gfx::extract_2d_affine_transform(command.matrix);
  1100. auto new_transform = Gfx::AffineTransform {}
  1101. .translate(command.origin)
  1102. .multiply(affine_transform)
  1103. .translate(-command.origin);
  1104. auto matrix = to_skia_matrix(new_transform);
  1105. surface().canvas().concat(matrix);
  1106. }
  1107. void DisplayListPlayerSkia::apply_mask_bitmap(ApplyMaskBitmap const& command)
  1108. {
  1109. auto& canvas = surface().canvas();
  1110. auto sk_bitmap = to_skia_bitmap(*command.bitmap);
  1111. auto mask_image = SkImages::RasterFromBitmap(sk_bitmap);
  1112. char const* sksl_shader = nullptr;
  1113. if (command.kind == Gfx::Bitmap::MaskKind::Luminance) {
  1114. sksl_shader = R"(
  1115. uniform shader mask_image;
  1116. half4 main(float2 coord) {
  1117. half4 color = mask_image.eval(coord);
  1118. half luminance = 0.2126 * color.b + 0.7152 * color.g + 0.0722 * color.r;
  1119. return half4(0.0, 0.0, 0.0, color.a * luminance);
  1120. }
  1121. )";
  1122. } else if (command.kind == Gfx::Bitmap::MaskKind::Alpha) {
  1123. sksl_shader = R"(
  1124. uniform shader mask_image;
  1125. half4 main(float2 coord) {
  1126. half4 color = mask_image.eval(coord);
  1127. return half4(0.0, 0.0, 0.0, color.a);
  1128. }
  1129. )";
  1130. } else {
  1131. VERIFY_NOT_REACHED();
  1132. }
  1133. auto [effect, error] = SkRuntimeEffect::MakeForShader(SkString(sksl_shader));
  1134. if (!effect) {
  1135. dbgln("SkSL error: {}", error.c_str());
  1136. VERIFY_NOT_REACHED();
  1137. }
  1138. SkMatrix mask_matrix;
  1139. auto mask_position = command.origin;
  1140. mask_matrix.setTranslate(mask_position.x(), mask_position.y());
  1141. SkRuntimeShaderBuilder builder(effect);
  1142. builder.child("mask_image") = mask_image->makeShader(SkSamplingOptions(), mask_matrix);
  1143. canvas.clipShader(builder.makeShader());
  1144. }
  1145. bool DisplayListPlayerSkia::would_be_fully_clipped_by_painter(Gfx::IntRect rect) const
  1146. {
  1147. return surface().canvas().quickReject(to_skia_rect(rect));
  1148. }
  1149. }