DisplayListPlayerSkia.cpp 52 KB

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