vendor: import KillerPDF 1.7.5 source (GPL-3.0) as the base for MMD PDF
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace KillerPDF
|
||||
{
|
||||
// Keeps the document scrollbar reactive (thumb sized to the visible proportion) while
|
||||
// guaranteeing it never shrinks below a grabbable floor.
|
||||
//
|
||||
// WPF's Track sizes the thumb AND the repeat buttons from the raw proportional value
|
||||
// (trackLen * viewport / (range + viewport)). Thumb.MinHeight does NOT feed that math - it
|
||||
// only stretches the thumb's render, so on a long document the thumb overflows its tiny
|
||||
// proportional slot and the increase RepeatButton paints over the overflow (the "8px"
|
||||
// scrollbar). Enforcing the minimum here, by raising the ViewportSize the Track sees, makes
|
||||
// the Track size the thumb and the buttons from the same floored value - no overflow, no
|
||||
// overlap, still proportional whenever there is room.
|
||||
//
|
||||
// Bindings (in order): ViewportSize, Maximum, Minimum, ActualWidth, ActualHeight, Orientation.
|
||||
// ConverterParameter: the floor in pixels (default 64).
|
||||
public sealed class ThumbViewportFloorConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
double vp = AsDouble(values, 0);
|
||||
// Anything unexpected -> hand back the real ViewportSize so behavior is unchanged.
|
||||
if (double.IsNaN(vp) || vp <= 0) return vp;
|
||||
|
||||
double max = AsDouble(values, 1);
|
||||
double min = AsDouble(values, 2);
|
||||
double width = AsDouble(values, 3);
|
||||
double height = AsDouble(values, 4);
|
||||
bool vertical = values.Length <= 5 || values[5] is not Orientation o
|
||||
|| o == Orientation.Vertical;
|
||||
|
||||
double trackLen = vertical ? height : width;
|
||||
double range = max - min;
|
||||
if (double.IsNaN(trackLen) || trackLen <= 0 || range <= 0) return vp;
|
||||
|
||||
double floor = 64;
|
||||
if (parameter != null &&
|
||||
double.TryParse(parameter.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out var p) && p > 0)
|
||||
floor = p;
|
||||
|
||||
// Never let the floor eat the whole track; leave room for the thumb to travel.
|
||||
floor = Math.Min(floor, trackLen * 0.5);
|
||||
if (trackLen <= floor) return vp;
|
||||
|
||||
// ViewportSize that yields a thumb exactly = floor; take the larger of it and the real VP.
|
||||
double vpForFloor = floor * range / (trackLen - floor);
|
||||
return Math.Max(vp, vpForFloor);
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
private static double AsDouble(object[] values, int i)
|
||||
{
|
||||
if (values == null || i >= values.Length) return double.NaN;
|
||||
object v = values[i];
|
||||
if (v == null || v == DependencyProperty.UnsetValue) return double.NaN;
|
||||
try { return System.Convert.ToDouble(v, CultureInfo.InvariantCulture); }
|
||||
catch { return double.NaN; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user