File: src\Framework\MS\Internal\Text\TextDpi.cs
Project: wpf\PresentationFramework.csproj (PresentationFramework)
//---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: TextDpi.cs
//
// Description: Helpers to handle text dpi conversions and limitations.
//
// History:
//  04/25/2003 : Microsoft - moving from Avalon branch.
//
//---------------------------------------------------------------------------
 
using System;                   // Double, ...
using System.Windows;           // DependencyObject
using System.Windows.Documents; // TextElement, ...
using System.Windows.Media;     // FontFamily
using MS.Internal.PtsHost.UnsafeNativeMethods;  // PTS
 
namespace MS.Internal.Text
{
    // ----------------------------------------------------------------------
    // Helpers to handle text dpi conversions and limitations.
    // ----------------------------------------------------------------------
    internal static class TextDpi
    {
        // ------------------------------------------------------------------
        // Minimum width for text measurement.
        // ------------------------------------------------------------------
        internal static double MinWidth { get { return _minSize; } }
 
        // ------------------------------------------------------------------
        // Maximum width for text measurement.
        // ------------------------------------------------------------------
        internal static double MaxWidth { get { return _maxSize; } }
 
        // ------------------------------------------------------------------
        // Convert from logical measurement unit to text measurement unit.
        //
        //      d - value in logical measurement unit
        //
        // Returns: value in text measurement unit.
        // ------------------------------------------------------------------
        internal static int ToTextDpi(double d)
        {
            if (DoubleUtil.IsZero(d)) { return 0; }
            else if (d > 0)
            {
                if (d > _maxSize) { d = _maxSize; }
                else if (d < _minSize) { d = _minSize; }
            }
            else
            {
                if (d < -_maxSize) { d = -_maxSize; }
                else if (d > -_minSize) { d = -_minSize; }
            }
            return (int)Math.Round(d * _scale);
        }
 
        // ------------------------------------------------------------------
        // Convert from text measurement unit to logical measurement unit.
        //
        //      i - value in text measurement unit
        //
        // Returns: value in logical measurement unit.
        // ------------------------------------------------------------------
        internal static double FromTextDpi(int i)
        {
            return ((double)i) / _scale;
        }
 
        // ------------------------------------------------------------------
        // Convert point from logical measurement unit to text measurement unit.
        // ------------------------------------------------------------------
        internal static PTS.FSPOINT ToTextPoint(Point point)
        {
            PTS.FSPOINT fspoint = new PTS.FSPOINT();
            fspoint.u = ToTextDpi(point.X);
            fspoint.v = ToTextDpi(point.Y);
            return fspoint;
        }
 
        // ------------------------------------------------------------------
        // Convert size from logical measurement unit to text measurement unit.
        // ------------------------------------------------------------------
        internal static PTS.FSVECTOR ToTextSize(Size size)
        {
            PTS.FSVECTOR fsvector = new PTS.FSVECTOR();
            fsvector.du = ToTextDpi(size.Width);
            fsvector.dv = ToTextDpi(size.Height);
            return fsvector;
        }
 
        // ------------------------------------------------------------------
        // Convert rect from text measurement unit to logical measurement unit.
        // ------------------------------------------------------------------
        internal static Rect FromTextRect(PTS.FSRECT fsrect)
        {
            return new Rect(
                FromTextDpi(fsrect.u),
                FromTextDpi(fsrect.v),
                FromTextDpi(fsrect.du),
                FromTextDpi(fsrect.dv));
        }
 
        // ------------------------------------------------------------------
        // Make sure that LS/PTS limitations are not exceeded for offset
        // within a line.
        // ------------------------------------------------------------------
        internal static void EnsureValidLineOffset(ref double offset)
        {
            // Offset has to be > min allowed size && < max allowed size.
            if (offset > _maxSize) { offset = _maxSize; }
            else if (offset < -_maxSize) { offset = -_maxSize; }
        }
 
        // ------------------------------------------------------------------
        // Snaps the value to TextDPi, makeing sure that convertion to 
        // TextDpi and the to double produces the same value.
        // ------------------------------------------------------------------
        internal static void SnapToTextDpi(ref Size size)
        {
            size = new Size(FromTextDpi(ToTextDpi(size.Width)), FromTextDpi(ToTextDpi(size.Height)));
        }
 
        // ------------------------------------------------------------------
        // Make sure that LS/PTS limitations are not exceeded for line width.
        // ------------------------------------------------------------------
        internal static void EnsureValidLineWidth(ref double width)
        {
            // Line width has to be > 0 && < max allowed size.
            if (width > _maxSize) { width = _maxSize; }
            else if (width < _minSize) { width = _minSize; }
        }
        internal static void EnsureValidLineWidth(ref Size size)
        {
            // Line width has to be > 0 && < max allowed size.
            if (size.Width > _maxSize) { size.Width = _maxSize; }
            else if (size.Width < _minSize) { size.Width = _minSize; }
        }
        internal static void EnsureValidLineWidth(ref int width)
        {
            // Line width has to be > 0 && < max allowed size.
            if (width > _maxSizeInt) { width = _maxSizeInt; }
            else if (width < _minSizeInt) { width = _minSizeInt; }
        }
 
        // ------------------------------------------------------------------
        // Make sure that PTS limitations are not exceeded for page size.
        // ------------------------------------------------------------------
        internal static void EnsureValidPageSize(ref Size size)
        {
            // Page size has to be > 0 && < max allowed size.
            if (size.Width > _maxSize) { size.Width = _maxSize; }
            else if (size.Width < _minSize) { size.Width = _minSize; }
            if (size.Height > _maxSize) { size.Height = _maxSize; }
            else if (size.Height < _minSize) { size.Height = _minSize; }
        }
        internal static void EnsureValidPageWidth(ref double width)
        {
            // Page size has to be > 0 && < max allowed size.
            if (width > _maxSize) { width = _maxSize; }
            else if (width < _minSize) { width = _minSize; }
        }
        internal static void EnsureValidPageMargin(ref Thickness pageMargin, Size pageSize)
        {
            if (pageMargin.Left >= pageSize.Width) { pageMargin.Right = 0.0; }
            if (pageMargin.Left + pageMargin.Right >= pageSize.Width)
            {
                pageMargin.Right = Math.Max(0.0, pageSize.Width - pageMargin.Left - _minSize);
                if (pageMargin.Left + pageMargin.Right >= pageSize.Width)
                {
                    pageMargin.Left = pageSize.Width - _minSize;
                }
            }
            if (pageMargin.Top >= pageSize.Height) { pageMargin.Bottom = 0.0; }
            if (pageMargin.Top + pageMargin.Bottom >= pageSize.Height)
            {
                pageMargin.Bottom = Math.Max(0.0, pageSize.Height - pageMargin.Top - _minSize);;
                if (pageMargin.Top + pageMargin.Bottom >= pageSize.Height)
                {
                    pageMargin.Top = pageSize.Height - _minSize;
                }
            }
        }
 
        // ------------------------------------------------------------------
        // Make sure that LS/PTS limitations are not exceeded for object's size.
        // ------------------------------------------------------------------
        internal static void EnsureValidObjSize(ref Size size)
        {
            // Embedded object can have size == 0, but its width and height
            // have to be less than max allowed size.
            if (size.Width > _maxObjSize) { size.Width = _maxObjSize; }
            if (size.Height > _maxObjSize) { size.Height = _maxObjSize; }
        }
 
        // ------------------------------------------------------------------
        // Measuring unit for PTS presenters is int, but logical measuring
        // for the rest of the system is is double.
        // Logical measuring dpi        = 96
        // PTS presenters measuring dpi = 28800
        // ------------------------------------------------------------------
        private const double _scale = 28800.0 / 96; // 300
 
        // ------------------------------------------------------------------
        // PTS/LS limitation for max size.
        // ------------------------------------------------------------------
        private const int _maxSizeInt = 0x3FFFFFFE;
        private const double _maxSize = ((double)_maxSizeInt) / _scale; // = 3,579,139.40 pixels
 
        // ------------------------------------------------------------------
        // PTS/LS limitation for min size.
        // ------------------------------------------------------------------
        private const int _minSizeInt = 1;
        private const double _minSize = ((double)_minSizeInt) / _scale; // > 0
 
        // ------------------------------------------------------------------
        // Embedded object size is limited to 1/3 of max size accepted by LS/PTS.
        // ------------------------------------------------------------------
        private const double _maxObjSize = _maxSize / 3; // = 1,193,046.46 pixels
    }
 
#if TEXTLAYOUTDEBUG
    // ----------------------------------------------------------------------
    // Pefrormance debugging helpers.
    // ----------------------------------------------------------------------
    internal static class TextDebug
    {
        // ------------------------------------------------------------------
        // Enter the scope and log the message.
        // ------------------------------------------------------------------
        internal static void BeginScope(string name)
        {
            Log(name);
            ++_indent;
        }
 
        // ------------------------------------------------------------------
        // Exit the current scope.
        // ------------------------------------------------------------------
        internal static void EndScope()
        {
            --_indent;
        }
 
        // ------------------------------------------------------------------
        // Log message.
        // ------------------------------------------------------------------
        internal static void Log(string msg)
        {
            Console.WriteLine("> " + CurrentIndent + msg);
        }
 
        // ------------------------------------------------------------------
        // String representing current indent.
        // ------------------------------------------------------------------
        private static string CurrentIndent { get { return new string(' ', _indent * 2); } }
 
        // ------------------------------------------------------------------
        // Current indent.
        // ------------------------------------------------------------------
        private static int _indent;
    }
#endif // TEXTLAYOUTDEBUG
}