mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-07 21:48:06 +00:00
Compare commits
2 Commits
5cedcff912
...
copilot/fi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4742908983 | ||
![]() |
ccbe1c297a |
@@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
using Assimp;
|
using Assimp;
|
||||||
using HelixToolkit.Wpf;
|
using HelixToolkit.Wpf;
|
||||||
using PcdSharp.IO;
|
|
||||||
using PcdSharp.Struct;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -56,86 +54,6 @@ public partial class HelixPanel
|
|||||||
modelVisual.Content = model;
|
modelVisual.Content = model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (importerType == ImporterType.Extended_PCD)
|
|
||||||
{
|
|
||||||
// Only support PCD files with PointXYZ format
|
|
||||||
// Not supported for Color or Intensity formats
|
|
||||||
var xyzCloud = PCDReader.Read<PointXYZ>(_path);
|
|
||||||
|
|
||||||
// Create a single geometry for all points to improve performance
|
|
||||||
var pointCloudGeometry = new MeshGeometry3D();
|
|
||||||
var positions = new Point3DCollection();
|
|
||||||
var triangleIndices = new Int32Collection();
|
|
||||||
|
|
||||||
// Create material for points
|
|
||||||
var pointMaterial = new DiffuseMaterial(new SolidColorBrush(Color.FromRgb(0x60, 0x80, 0xFF)));
|
|
||||||
|
|
||||||
// Adaptive point size based on total number of points
|
|
||||||
var totalPoints = xyzCloud.Points.Count;
|
|
||||||
var pointSize = totalPoints > 10000 ? 0.05d : totalPoints > 1000 ? 0.1d : 0.2d;
|
|
||||||
|
|
||||||
// Limit points for performance (show every Nth point if too many)
|
|
||||||
var step = Math.Max(1, totalPoints / 50000); // Limit to ~50k points max
|
|
||||||
|
|
||||||
var vertexIndex = 0;
|
|
||||||
for (int i = 0; i < xyzCloud.Points.Count; i += step)
|
|
||||||
{
|
|
||||||
var point = xyzCloud.Points[i];
|
|
||||||
|
|
||||||
// Create a small cube for each point
|
|
||||||
var halfSize = pointSize / 2;
|
|
||||||
|
|
||||||
// Add 8 vertices for the cube
|
|
||||||
var baseIndex = vertexIndex;
|
|
||||||
|
|
||||||
// Front face vertices
|
|
||||||
positions.Add(new Point3D(point.X - halfSize, point.Y - halfSize, point.Z + halfSize));
|
|
||||||
positions.Add(new Point3D(point.X + halfSize, point.Y - halfSize, point.Z + halfSize));
|
|
||||||
positions.Add(new Point3D(point.X + halfSize, point.Y + halfSize, point.Z + halfSize));
|
|
||||||
positions.Add(new Point3D(point.X - halfSize, point.Y + halfSize, point.Z + halfSize));
|
|
||||||
|
|
||||||
// Back face vertices
|
|
||||||
positions.Add(new Point3D(point.X - halfSize, point.Y - halfSize, point.Z - halfSize));
|
|
||||||
positions.Add(new Point3D(point.X + halfSize, point.Y - halfSize, point.Z - halfSize));
|
|
||||||
positions.Add(new Point3D(point.X + halfSize, point.Y + halfSize, point.Z - halfSize));
|
|
||||||
positions.Add(new Point3D(point.X - halfSize, point.Y + halfSize, point.Z - halfSize));
|
|
||||||
|
|
||||||
// Add triangle indices for the cube (12 triangles, 36 indices)
|
|
||||||
// Front face
|
|
||||||
triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 2);
|
|
||||||
triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 2); triangleIndices.Add(baseIndex + 3);
|
|
||||||
// Back face
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 5);
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 7); triangleIndices.Add(baseIndex + 6);
|
|
||||||
// Left face
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 0); triangleIndices.Add(baseIndex + 3);
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 7);
|
|
||||||
// Right face
|
|
||||||
triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 5); triangleIndices.Add(baseIndex + 6);
|
|
||||||
triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 2);
|
|
||||||
// Top face
|
|
||||||
triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 2); triangleIndices.Add(baseIndex + 6);
|
|
||||||
triangleIndices.Add(baseIndex + 3); triangleIndices.Add(baseIndex + 6); triangleIndices.Add(baseIndex + 7);
|
|
||||||
// Bottom face
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 5); triangleIndices.Add(baseIndex + 1);
|
|
||||||
triangleIndices.Add(baseIndex + 4); triangleIndices.Add(baseIndex + 1); triangleIndices.Add(baseIndex + 0);
|
|
||||||
|
|
||||||
vertexIndex += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointCloudGeometry.Positions = positions;
|
|
||||||
pointCloudGeometry.TriangleIndices = triangleIndices;
|
|
||||||
|
|
||||||
// Create the model
|
|
||||||
var pointCloudModel = new GeometryModel3D
|
|
||||||
{
|
|
||||||
Geometry = pointCloudGeometry,
|
|
||||||
Material = pointMaterial,
|
|
||||||
BackMaterial = pointMaterial
|
|
||||||
};
|
|
||||||
|
|
||||||
modelVisual.Content = pointCloudModel;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var modelImporter = new ModelImporter();
|
var modelImporter = new ModelImporter();
|
||||||
@@ -172,7 +90,6 @@ file static class Importer
|
|||||||
".stl" or ".obj" or ".3ds" or ".lwo" or ".ply" => ImporterType.Default,
|
".stl" or ".obj" or ".3ds" or ".lwo" or ".ply" => ImporterType.Default,
|
||||||
".fbx" or ".3mf" or ".glb" or ".gltf" or ".dae" or ".dxf" => ImporterType.Extended,
|
".fbx" or ".3mf" or ".glb" or ".gltf" or ".dae" or ".dxf" => ImporterType.Extended,
|
||||||
".pmx" => ImporterType.Extended_MMD,
|
".pmx" => ImporterType.Extended_MMD,
|
||||||
".pcd" => ImporterType.Extended_PCD,
|
|
||||||
_ => ImporterType.Unknown,
|
_ => ImporterType.Unknown,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -180,28 +97,8 @@ file static class Importer
|
|||||||
|
|
||||||
file enum ImporterType
|
file enum ImporterType
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Reserved or unspecified import type
|
|
||||||
/// </summary>
|
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default importer supported by HelixToolkit
|
|
||||||
/// </summary>
|
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extended importer supported by Assimp
|
|
||||||
/// </summary>
|
|
||||||
Extended,
|
Extended,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extended MMD (MikuMikuDance) importer
|
|
||||||
/// </summary>
|
|
||||||
Extended_MMD,
|
Extended_MMD,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extended PCD (Point Cloud Data) importer for 3D spatial data
|
|
||||||
/// </summary>
|
|
||||||
Extended_PCD,
|
|
||||||
}
|
}
|
||||||
|
@@ -31,20 +31,17 @@ public class Plugin : IViewer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static readonly HashSet<string> WellKnownExtensions = new(
|
private static readonly HashSet<string> WellKnownExtensions = new(
|
||||||
[
|
[
|
||||||
// Default supported by HelixToolkit
|
// Default
|
||||||
".stl", ".obj", ".3ds", ".lwo", ".ply",
|
".stl", ".obj", ".3ds", ".lwo", ".ply",
|
||||||
|
|
||||||
// Extended supported by Assimp
|
// Extended
|
||||||
".fbx", ".3mf", ".blend", ".glb", ".gltf", ".dae",
|
".fbx", ".3mf", ".blend", ".glb", ".gltf", ".dae",
|
||||||
#if S_DXF
|
#if S_DXF
|
||||||
".dxf",
|
".dxf",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TBD: MMD (MikuMikuDance)
|
// Extended_MMD
|
||||||
//".pmx",
|
".pmx",
|
||||||
|
|
||||||
// PCD (Point Cloud Data)
|
|
||||||
".pcd",
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
private HelixPanel _hp;
|
private HelixPanel _hp;
|
||||||
|
@@ -55,7 +55,6 @@
|
|||||||
<PackageReference Include="HelixToolkit" Version="2.27.0" />
|
<PackageReference Include="HelixToolkit" Version="2.27.0" />
|
||||||
<PackageReference Include="HelixToolkit.Wpf" Version="2.27.0" />
|
<PackageReference Include="HelixToolkit.Wpf" Version="2.27.0" />
|
||||||
<PackageReference Include="AssimpNet" Version="5.0.0-beta1" />
|
<PackageReference Include="AssimpNet" Version="5.0.0-beta1" />
|
||||||
<PackageReference Include="PcdSharp" Version="1.0.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
using LibAPNG;
|
using LibAPNG;
|
||||||
using QuickLook.Common.ExtensionMethods;
|
using QuickLook.Common.ExtensionMethods;
|
||||||
using QuickLook.Common.Helpers;
|
|
||||||
using QuickLook.Common.Plugin;
|
using QuickLook.Common.Plugin;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -31,28 +30,20 @@ using System.Windows.Media.Imaging;
|
|||||||
|
|
||||||
namespace QuickLook.Plugin.ImageViewer.AnimatedImage.Providers;
|
namespace QuickLook.Plugin.ImageViewer.AnimatedImage.Providers;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This provider is only for Animated PNG.
|
|
||||||
/// The others will fall back to another provider.
|
|
||||||
/// </summary>
|
|
||||||
internal class APngProvider : AnimationProvider
|
internal class APngProvider : AnimationProvider
|
||||||
{
|
{
|
||||||
private readonly Frame _baseFrame;
|
private readonly Frame _baseFrame;
|
||||||
private readonly List<FrameInfo> _frames;
|
private readonly List<FrameInfo> _frames;
|
||||||
private readonly List<BitmapSource> _renderedFrames;
|
private readonly List<BitmapSource> _renderedFrames;
|
||||||
private int _lastEffectivePreviousPreviousFrameIndex;
|
private int _lastEffectivePreviousPreviousFrameIndex;
|
||||||
private AnimationProvider _fallbackImageProvider;
|
private NativeProvider _nativeImageProvider;
|
||||||
|
|
||||||
public APngProvider(Uri path, MetaProvider meta, ContextObject contextObject) : base(path, meta, contextObject)
|
public APngProvider(Uri path, MetaProvider meta, ContextObject contextObject) : base(path, meta, contextObject)
|
||||||
{
|
{
|
||||||
if (!IsAnimatedPng(path.LocalPath))
|
if (!IsAnimatedPng(path.LocalPath))
|
||||||
{
|
{
|
||||||
var useNativeProvider = SettingHelper.Get("UseNativeProvider", true, "QuickLook.Plugin.ImageViewer");
|
_nativeImageProvider = new NativeProvider(path, meta, contextObject);
|
||||||
|
Animator = _nativeImageProvider.Animator;
|
||||||
_fallbackImageProvider = useNativeProvider ?
|
|
||||||
new NativeProvider(path, meta, contextObject) :
|
|
||||||
new ImageMagickProvider(path, meta, contextObject);
|
|
||||||
Animator = _fallbackImageProvider.Animator;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +71,8 @@ internal class APngProvider : AnimationProvider
|
|||||||
|
|
||||||
public override Task<BitmapSource> GetThumbnail(Size renderSize)
|
public override Task<BitmapSource> GetThumbnail(Size renderSize)
|
||||||
{
|
{
|
||||||
if (_fallbackImageProvider != null)
|
if (_nativeImageProvider != null)
|
||||||
return _fallbackImageProvider.GetThumbnail(renderSize);
|
return _nativeImageProvider.GetThumbnail(renderSize);
|
||||||
|
|
||||||
return new Task<BitmapSource>(() =>
|
return new Task<BitmapSource>(() =>
|
||||||
{
|
{
|
||||||
@@ -94,8 +85,8 @@ internal class APngProvider : AnimationProvider
|
|||||||
|
|
||||||
public override Task<BitmapSource> GetRenderedFrame(int index)
|
public override Task<BitmapSource> GetRenderedFrame(int index)
|
||||||
{
|
{
|
||||||
if (_fallbackImageProvider != null)
|
if (_nativeImageProvider != null)
|
||||||
return _fallbackImageProvider.GetRenderedFrame(index);
|
return _nativeImageProvider.GetRenderedFrame(index);
|
||||||
|
|
||||||
if (_renderedFrames[index] != null)
|
if (_renderedFrames[index] != null)
|
||||||
return new Task<BitmapSource>(() => _renderedFrames[index]);
|
return new Task<BitmapSource>(() => _renderedFrames[index]);
|
||||||
@@ -111,10 +102,10 @@ internal class APngProvider : AnimationProvider
|
|||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
{
|
{
|
||||||
if (_fallbackImageProvider != null)
|
if (_nativeImageProvider != null)
|
||||||
{
|
{
|
||||||
_fallbackImageProvider.Dispose();
|
_nativeImageProvider.Dispose();
|
||||||
_fallbackImageProvider = null;
|
_nativeImageProvider = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +214,7 @@ internal class APngProvider : AnimationProvider
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint ToUInt32BE(byte[] data)
|
uint ToUInt32BE(byte[] data)
|
||||||
{
|
{
|
||||||
Array.Reverse(data);
|
Array.Reverse(data);
|
||||||
return BitConverter.ToUInt32(data, 0);
|
return BitConverter.ToUInt32(data, 0);
|
||||||
|
@@ -40,6 +40,11 @@ internal class NativeProvider : AnimationProvider
|
|||||||
public override Task<BitmapSource> GetThumbnail(Size renderSize)
|
public override Task<BitmapSource> GetThumbnail(Size renderSize)
|
||||||
{
|
{
|
||||||
var fullSize = Meta.GetSize();
|
var fullSize = Meta.GetSize();
|
||||||
|
|
||||||
|
//var decodeWidth = (int) Math.Round(fullSize.Width *
|
||||||
|
// Math.Min(renderSize.Width / 2 / fullSize.Width,
|
||||||
|
// renderSize.Height / 2 / fullSize.Height));
|
||||||
|
//var decodeHeight = (int) Math.Round(fullSize.Height / fullSize.Width * decodeWidth);
|
||||||
var decodeWidth =
|
var decodeWidth =
|
||||||
(int)Math.Round(Math.Min(Meta.GetSize().Width, Math.Max(1d, Math.Floor(renderSize.Width))));
|
(int)Math.Round(Math.Min(Meta.GetSize().Width, Math.Max(1d, Math.Floor(renderSize.Width))));
|
||||||
var decodeHeight =
|
var decodeHeight =
|
||||||
|
@@ -65,16 +65,8 @@ public class Plugin : IViewer
|
|||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
// Option of UseColorProfile:
|
|
||||||
// Default is False (disable color profile conversion)
|
|
||||||
// Note that enabling this feature will slow down image previewing, especially on large images.
|
|
||||||
var useColorProfile = SettingHelper.Get("UseColorProfile", false, "QuickLook.Plugin.ImageViewer");
|
var useColorProfile = SettingHelper.Get("UseColorProfile", false, "QuickLook.Plugin.ImageViewer");
|
||||||
|
|
||||||
// Option of UseNativeProvider:
|
|
||||||
// Default is True (disable precise colors and choose faster response)
|
|
||||||
// Note that disabling this feature may slightly slow down image previewing but you can get precise colors.
|
|
||||||
var useNativeProvider = SettingHelper.Get("UseNativeProvider", true, "QuickLook.Plugin.ImageViewer");
|
|
||||||
|
|
||||||
AnimatedImage.AnimatedImage.Providers.Add(
|
AnimatedImage.AnimatedImage.Providers.Add(
|
||||||
new KeyValuePair<string[], Type>(
|
new KeyValuePair<string[], Type>(
|
||||||
useColorProfile ? [".apng"] : [".apng", ".png"],
|
useColorProfile ? [".apng"] : [".apng", ".png"],
|
||||||
@@ -84,10 +76,11 @@ public class Plugin : IViewer
|
|||||||
typeof(GifProvider)));
|
typeof(GifProvider)));
|
||||||
AnimatedImage.AnimatedImage.Providers.Add(
|
AnimatedImage.AnimatedImage.Providers.Add(
|
||||||
new KeyValuePair<string[], Type>(
|
new KeyValuePair<string[], Type>(
|
||||||
useColorProfile ? [] : (useNativeProvider ? [".bmp", ".jpg", ".jpeg", ".jfif", ".tif", ".tiff"] : []),
|
useColorProfile ? [] : [".bmp", ".jpg", ".jpeg", ".jfif", ".tif", ".tiff"],
|
||||||
typeof(NativeProvider)));
|
typeof(NativeProvider)));
|
||||||
AnimatedImage.AnimatedImage.Providers.Add(
|
AnimatedImage.AnimatedImage.Providers.Add(
|
||||||
new KeyValuePair<string[], Type>([".jxr"],
|
new KeyValuePair<string[], Type>(
|
||||||
|
useColorProfile ? [] : [".jxr"],
|
||||||
typeof(WmpProvider)));
|
typeof(WmpProvider)));
|
||||||
AnimatedImage.AnimatedImage.Providers.Add(
|
AnimatedImage.AnimatedImage.Providers.Add(
|
||||||
new KeyValuePair<string[], Type>([".icns"],
|
new KeyValuePair<string[], Type>([".icns"],
|
||||||
|
@@ -59,7 +59,7 @@
|
|||||||
<PackageReference Include="QuickLook.ImageGlass.WebP" Version="1.4.0">
|
<PackageReference Include="QuickLook.ImageGlass.WebP" Version="1.4.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.7.0">
|
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.6.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3351.48">
|
||||||
|
@@ -16,12 +16,10 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
using Microsoft.Web.WebView2.Core;
|
using Microsoft.Web.WebView2.Core;
|
||||||
using QuickLook.Common.Helpers;
|
|
||||||
using QuickLook.Plugin.HtmlViewer;
|
using QuickLook.Plugin.HtmlViewer;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@@ -80,21 +78,7 @@ public class MarkdownPanel : WebpagePanel
|
|||||||
var content = encoding.GetString(bytes);
|
var content = encoding.GetString(bytes);
|
||||||
|
|
||||||
var template = ReadString("/md2html.html");
|
var template = ReadString("/md2html.html");
|
||||||
|
var html = template.Replace("{{content}}", content);
|
||||||
// Support automatic RTL for markdown files
|
|
||||||
bool isRtl = false;
|
|
||||||
if (CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft)
|
|
||||||
{
|
|
||||||
string isSupportRTL = TranslationHelper.Get("IsSupportRTL",
|
|
||||||
failsafe: bool.TrueString,
|
|
||||||
domain: Assembly.GetExecutingAssembly().GetName().Name);
|
|
||||||
|
|
||||||
if (bool.TrueString.Equals(isSupportRTL, StringComparison.OrdinalIgnoreCase))
|
|
||||||
isRtl = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var html = template.Replace("{{content}}", content)
|
|
||||||
.Replace("{{rtl}}", isRtl ? "rtl" : "ltr");
|
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html dir="{{rtl}}">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
<script src="highlight.js/highlight.min.js"></script>
|
<script src="highlight.js/highlight.min.js"></script>
|
||||||
|
|
||||||
<script src="js/markdownItAnchor.umd.js"></script>
|
<script src="js/markdownItAnchor.umd.js"></script>
|
||||||
<script src="js/mermaid.min.js"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body class="markdown-body">
|
<body class="markdown-body">
|
||||||
<link rel="stylesheet" href="css/github-markdown.css" />
|
<link rel="stylesheet" href="css/github-markdown.css" />
|
||||||
@@ -145,61 +144,6 @@
|
|||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RTL support */
|
|
||||||
html[dir="rtl"] .container {
|
|
||||||
flex-direction: row-reverse;
|
|
||||||
}
|
|
||||||
|
|
||||||
html[dir="rtl"] #toc {
|
|
||||||
right: 0;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
html[dir="rtl"] .table-of-contents a {
|
|
||||||
border-right: 2px solid transparent;
|
|
||||||
border-left: none;
|
|
||||||
margin-right: -1em;
|
|
||||||
margin-left: 0;
|
|
||||||
padding-right: calc(1em - 2px);
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
html[dir="rtl"] .table-of-contents .active {
|
|
||||||
border-right: 2px solid var(--fgColor-accent);
|
|
||||||
border-left: none;
|
|
||||||
margin-right: -1em;
|
|
||||||
margin-left: 0;
|
|
||||||
padding-right: calc(1em - 2px);
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mermaid diagram styles */
|
|
||||||
.mermaid {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
margin: 1em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mermaid svg {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
border-radius: 6px;
|
|
||||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mermaid-placeholder {
|
|
||||||
border: 2px dashed var(--borderColor-default);
|
|
||||||
background: var(--bgColor-muted);
|
|
||||||
color: var(--fgColor-muted);
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mermaid-placeholder pre {
|
|
||||||
background: var(--bgColor-default);
|
|
||||||
border: 1px solid var(--borderColor-default);
|
|
||||||
color: var(--fgColor-default);
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<textarea id="text-input" style="display: none">{{content}}</textarea>
|
<textarea id="text-input" style="display: none">{{content}}</textarea>
|
||||||
@@ -216,9 +160,6 @@
|
|||||||
typographer: false,
|
typographer: false,
|
||||||
quotes: "“”‘’",
|
quotes: "“”‘’",
|
||||||
highlight: function (str, lang) {
|
highlight: function (str, lang) {
|
||||||
if (lang === 'mermaid') {
|
|
||||||
return '<div class="mermaid">' + str + '</div>';
|
|
||||||
}
|
|
||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
return (
|
return (
|
||||||
@@ -249,62 +190,6 @@
|
|||||||
document.getElementById("text-input").value
|
document.getElementById("text-input").value
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initialize Mermaid after markdown rendering
|
|
||||||
if (window.mermaid) {
|
|
||||||
// Determine theme based on system preference
|
|
||||||
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
||||||
|
|
||||||
mermaid.initialize({
|
|
||||||
startOnLoad: false,
|
|
||||||
theme: isDarkMode ? 'dark' : 'default',
|
|
||||||
securityLevel: 'loose', // Allow HTML in diagrams for enhanced features
|
|
||||||
fontFamily: 'Segoe UI, Helvetica, Arial, sans-serif',
|
|
||||||
themeVariables: {
|
|
||||||
primaryColor: isDarkMode ? '#58a6ff' : '#0969da',
|
|
||||||
primaryTextColor: isDarkMode ? '#f0f6fc' : '#24292f',
|
|
||||||
primaryBorderColor: isDarkMode ? '#30363d' : '#d0d7de',
|
|
||||||
lineColor: isDarkMode ? '#484f58' : '#656d76',
|
|
||||||
sectionBkgColor: isDarkMode ? '#21262d' : '#f6f8fa',
|
|
||||||
altSectionBkgColor: isDarkMode ? '#161b22' : '#ffffff',
|
|
||||||
gridColor: isDarkMode ? '#21262d' : '#f6f8fa',
|
|
||||||
cScale0: isDarkMode ? '#58a6ff' : '#0969da',
|
|
||||||
cScale1: isDarkMode ? '#a5f3fc' : '#54aeff',
|
|
||||||
cScale2: isDarkMode ? '#ff7b72' : '#d1242f'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Render Mermaid diagrams with error handling
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Mermaid rendering error:', error);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
// Listen for theme changes and re-render diagrams
|
|
||||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
||||||
if (window.mermaid) {
|
|
||||||
const newTheme = e.matches ? 'dark' : 'default';
|
|
||||||
mermaid.initialize({
|
|
||||||
startOnLoad: false,
|
|
||||||
theme: newTheme,
|
|
||||||
securityLevel: 'loose',
|
|
||||||
fontFamily: 'Segoe UI, Helvetica, Arial, sans-serif'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Re-render all Mermaid diagrams
|
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Mermaid re-rendering error:', error);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* codes below are adopted from https://codepen.io/jtojnar/full/Juiop */
|
/* codes below are adopted from https://codepen.io/jtojnar/full/Juiop */
|
||||||
var ToC = `<nav role='navigation' class='table-of-contents'>
|
var ToC = `<nav role='navigation' class='table-of-contents'>
|
||||||
<h2>Contents</h2>
|
<h2>Contents</h2>
|
||||||
@@ -452,21 +337,6 @@
|
|||||||
if (e.code === "Space") {
|
if (e.code === "Space") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support keyboard shortcuts for RTL and LTR text direction
|
|
||||||
// RTL: Ctrl + RShift
|
|
||||||
// LTR: Ctrl + LShift
|
|
||||||
if ((e.ctrlKey || e.metaKey)) {
|
|
||||||
if (e.shiftKey && e.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
|
|
||||||
// Right Shift + Ctrl: RTL
|
|
||||||
document.documentElement.setAttribute('dir', 'rtl');
|
|
||||||
e.preventDefault();
|
|
||||||
} else if (e.shiftKey && e.location === KeyboardEvent.DOM_KEY_LOCATION_LEFT) {
|
|
||||||
// Left Shift + Ctrl: LTR
|
|
||||||
document.documentElement.setAttribute('dir', 'ltr');
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -21,7 +21,6 @@ using PureSharpCompress.Readers;
|
|||||||
using QuickLook.Common.Helpers;
|
using QuickLook.Common.Helpers;
|
||||||
using QuickLook.Common.Plugin;
|
using QuickLook.Common.Plugin;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
@@ -31,18 +30,8 @@ namespace QuickLook.Plugin.ThumbnailViewer;
|
|||||||
|
|
||||||
internal static class Handler
|
internal static class Handler
|
||||||
{
|
{
|
||||||
// List<Pair<formats, type>>
|
|
||||||
public static List<KeyValuePair<string[], Type>> Providers = [];
|
|
||||||
|
|
||||||
public static void Prepare(string path, ContextObject context)
|
public static void Prepare(string path, ContextObject context)
|
||||||
{
|
{
|
||||||
// Temporary codes
|
|
||||||
if (path.EndsWith(".pdn", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
new PdnProvider().Prepare(path, context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using Stream imageData = ViewImage(path);
|
using Stream imageData = ViewImage(path);
|
||||||
@@ -58,12 +47,6 @@ internal static class Handler
|
|||||||
|
|
||||||
public static Stream ViewImage(string path)
|
public static Stream ViewImage(string path)
|
||||||
{
|
{
|
||||||
// Temporary codes
|
|
||||||
if (path.EndsWith(".pdn", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return new PdnProvider().ViewImage(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using ZipArchive archive = ZipArchive.Open(path, new());
|
using ZipArchive archive = ZipArchive.Open(path, new());
|
||||||
|
@@ -34,7 +34,6 @@ public class Plugin : IViewer
|
|||||||
".cdr", // CorelDraw
|
".cdr", // CorelDraw
|
||||||
".fig", // Figma
|
".fig", // Figma
|
||||||
".kra", // Krita
|
".kra", // Krita
|
||||||
".pdn", // Paint.NET
|
|
||||||
".pip", ".pix", // Pixso
|
".pip", ".pix", // Pixso
|
||||||
".sketch", // Sketch
|
".sketch", // Sketch
|
||||||
".xd", // AdobeXD
|
".xd", // AdobeXD
|
||||||
@@ -47,8 +46,6 @@ public class Plugin : IViewer
|
|||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
Handler.Providers.Add(new KeyValuePair<string[], Type>(
|
|
||||||
[".pdn"], typeof(PdnProvider)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
public bool CanHandle(string path)
|
||||||
|
@@ -1,93 +0,0 @@
|
|||||||
// Copyright © 2017-2025 QL-Win Contributors
|
|
||||||
//
|
|
||||||
// This file is part of QuickLook program.
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
using QuickLook.Common.Helpers;
|
|
||||||
using QuickLook.Common.Plugin;
|
|
||||||
using QuickLook.Plugin.ImageViewer;
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace QuickLook.Plugin.ThumbnailViewer;
|
|
||||||
|
|
||||||
internal class PdnProvider
|
|
||||||
{
|
|
||||||
public void Prepare(string path, ContextObject context)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using Stream imageData = ViewImage(path);
|
|
||||||
BitmapImage bitmap = imageData.ReadAsBitmapImage();
|
|
||||||
context.SetPreferredSizeFit(new Size(bitmap.PixelWidth, bitmap.PixelHeight), 0.8d);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Error reading thumbnail from {path}: {ex.Message}");
|
|
||||||
context.PreferredSize = new Size { Width = 800, Height = 600 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stream ViewImage(string path)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using TextReader reader = new StreamReader(path, Encoding.UTF8);
|
|
||||||
string line = reader.ReadLine();
|
|
||||||
|
|
||||||
if (!line.StartsWith("PDN"))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int indexOfStart = line.IndexOf("<");
|
|
||||||
int indexOfEnd = line.LastIndexOf(">");
|
|
||||||
|
|
||||||
if (indexOfStart < 0 || indexOfEnd < 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
string xml = line.Substring(indexOfStart, indexOfEnd - indexOfStart + 1);
|
|
||||||
|
|
||||||
// <pdnImage>
|
|
||||||
// <custom>
|
|
||||||
// <thumb png="..." />
|
|
||||||
// </custom>
|
|
||||||
// </pdnImage>
|
|
||||||
XDocument doc = XDocument.Parse(xml);
|
|
||||||
var pngBase64 = doc.Root
|
|
||||||
?.Element("custom")
|
|
||||||
?.Element("thumb")
|
|
||||||
?.Attribute("png")
|
|
||||||
?.Value;
|
|
||||||
|
|
||||||
if (pngBase64 != null)
|
|
||||||
{
|
|
||||||
byte[] imageBytes = Convert.FromBase64String(pngBase64);
|
|
||||||
MemoryStream ms = new(imageBytes);
|
|
||||||
return ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ProcessHelper.WriteLog(e.ToString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -220,6 +220,9 @@ public partial class App : Application
|
|||||||
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
|
ThemeManager.Apply(OSThemeHelper.AppsUseDarkTheme() ? ApplicationTheme.Dark : ApplicationTheme.Light);
|
||||||
UxTheme.ApplyPreferredAppMode();
|
UxTheme.ApplyPreferredAppMode();
|
||||||
|
|
||||||
|
// Handle power management events to prevent crashes after sleep/wake
|
||||||
|
SystemEvents.PowerModeChanged += OnPowerModeChanged;
|
||||||
|
|
||||||
// Initialize TrayIcon
|
// Initialize TrayIcon
|
||||||
_ = TrayIconManager.GetInstance();
|
_ = TrayIconManager.GetInstance();
|
||||||
|
|
||||||
@@ -303,6 +306,9 @@ public partial class App : Application
|
|||||||
if (!_cleanExit)
|
if (!_cleanExit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Unsubscribe from power management events
|
||||||
|
SystemEvents.PowerModeChanged -= OnPowerModeChanged;
|
||||||
|
|
||||||
_isRunning.ReleaseMutex();
|
_isRunning.ReleaseMutex();
|
||||||
|
|
||||||
PipeServerManager.GetInstance().Dispose();
|
PipeServerManager.GetInstance().Dispose();
|
||||||
@@ -330,4 +336,28 @@ public partial class App : Application
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (e.Mode)
|
||||||
|
{
|
||||||
|
case PowerModes.Suspend:
|
||||||
|
// System is going to sleep - close any open preview windows to prevent graphics issues
|
||||||
|
ProcessHelper.WriteLog("System entering sleep mode - closing preview windows");
|
||||||
|
ViewWindowManager.GetInstance().ClosePreview();
|
||||||
|
break;
|
||||||
|
case PowerModes.Resume:
|
||||||
|
// System waking up - log for debugging
|
||||||
|
ProcessHelper.WriteLog("System resumed from sleep mode");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Don't let power management exceptions crash the app
|
||||||
|
ProcessHelper.WriteLog($"Error handling power mode change: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -418,9 +418,9 @@
|
|||||||
<MW_BrowseFolder>Przeglądaj {0}</MW_BrowseFolder>
|
<MW_BrowseFolder>Przeglądaj {0}</MW_BrowseFolder>
|
||||||
<MW_StayTop>Przypnij do ekranu</MW_StayTop>
|
<MW_StayTop>Przypnij do ekranu</MW_StayTop>
|
||||||
<MW_PreventClosing>Zablokuj zamykanie</MW_PreventClosing>
|
<MW_PreventClosing>Zablokuj zamykanie</MW_PreventClosing>
|
||||||
|
<MW_BrowseFolder>Przeglądaj {0}</MW_BrowseFolder>
|
||||||
<MW_Open>Otwórz {0}</MW_Open>
|
<MW_Open>Otwórz {0}</MW_Open>
|
||||||
<MW_OpenWith>Otwórz w {0}</MW_OpenWith>
|
<MW_OpenWith>Otwórz w {0}</MW_OpenWith>
|
||||||
<MW_OpenWithMenu>Otwórz za pomocą...</MW_OpenWithMenu>
|
|
||||||
<MW_Run>Uruchom {0}</MW_Run>
|
<MW_Run>Uruchom {0}</MW_Run>
|
||||||
<MW_Share>Udostępnij</MW_Share>
|
<MW_Share>Udostępnij</MW_Share>
|
||||||
<MW_Reload>Przeładuj</MW_Reload>
|
<MW_Reload>Przeładuj</MW_Reload>
|
||||||
@@ -441,7 +441,6 @@
|
|||||||
<InfoPanel_File>{0} plik</InfoPanel_File>
|
<InfoPanel_File>{0} plik</InfoPanel_File>
|
||||||
<InfoPanel_Files>{0} plików</InfoPanel_Files>
|
<InfoPanel_Files>{0} plików</InfoPanel_Files>
|
||||||
<InfoPanel_FolderAndFile>({0} i {1})</InfoPanel_FolderAndFile>
|
<InfoPanel_FolderAndFile>({0} i {1})</InfoPanel_FolderAndFile>
|
||||||
<InfoPanel_CantPreventClosing>Anulowanie dla funkcji blokady zamykania okna nie jest wspierane</InfoPanel_CantPreventClosing>
|
|
||||||
</pl>
|
</pl>
|
||||||
<pt-BR>
|
<pt-BR>
|
||||||
<UI_FontFamily>Segoe UI</UI_FontFamily>
|
<UI_FontFamily>Segoe UI</UI_FontFamily>
|
||||||
|
Reference in New Issue
Block a user