DisplayListPlayerSkia.cpp 47 KB

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