导航

View Code
using System;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.IO.Packaging;
using System.Windows.Documents;
using System.Windows.Documents.Serialization;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls;
// CharacterHit
using System.Printing;

public partial class ViewXPSDetail : System.Web.UI.Page
{
    public int Pages { get; set; }
    public bool FinishConvert { get; set; }



    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {

        }
    }

    protected void ShowXPSBtn_Click(object sender, EventArgs e)
    {
        AddBackGroundStart();
    }

    //xps转成jpg
    private bool SaveXpsPage(string xpsPath)
    {
        try
        {
            FileConvert fileConvert = new FileConvert();
            fileConvert.FileFullPath = xpsPath;

            Thread thread = new Thread(fileConvert.SaveFileToJpg);
            thread.SetApartmentState(ApartmentState.STA);

            thread.Start();
            while (!fileConvert.FinishConvert)
            {
                Thread.Sleep(100);
            }
            return true;
        }
        catch (Exception)
        {
            Pages = 0;
            return false;
        }
    }

    public void AddBackGroundStart()
    {
        Thread thread = new Thread(AddBackGround);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }

    public void AddBackGround()
    {
        string oldFileName = Server.MapPath("Content/") + FileUpload1.FileName;

        string newFileName = Server.MapPath("Content/NewHighLight.xps");


        if (!File.Exists(oldFileName))
            return;

        // Open original XPS document
        using (XpsDocument xpsOld = new XpsDocument(oldFileName, FileAccess.ReadWrite))
        {
            FixedDocumentSequence seqOld = xpsOld.GetFixedDocumentSequence();

            // Create new XPS document

            Package container = Package.Open(newFileName, FileMode.Create);

            XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(new XpsDocument(container));

            // Needed for writing multiple pages

            SerializerWriterCollator vxpsd = writer.CreateVisualsCollator();

            
            int pageno = 1;

            if (seqOld == null)
                return;

            foreach (DocumentReference r in seqOld.References)
            {
                FixedDocument d = r.GetDocument(false);

                // Walk through each page

                foreach (PageContent pc in d.Pages)
                {
                    if (pc == null) continue;

                    FixedPage fixedPage = pc.GetPageRoot(false);


                    if (fixedPage == null) continue;

                    double width = fixedPage.Width;

                    double height = fixedPage.Height;

                    Size sz = new Size(width, height);


                    //// Convert to WPF Visual
                    fixedPage.Measure(sz);
                    fixedPage.Arrange(new Rect(new Point(), sz));
                    fixedPage.UpdateLayout();

                    ContainerVisual newpage = new ContainerVisual();
                    newpage.Children.Add(fixedPage);

                    //// 高亮
                    var backgroundRect = GetBackgroundRect(fixedPage, txtKeyWord.Text.Trim());
                    if (backgroundRect != null && backgroundRect.Count > 0)
                    {
                        backgroundRect.ForEach(q => newpage.Children.Add(CreateBackGround(q.X, q.Y, q.Width, q.Height)));
                    }

                    ////水印
                    newpage.Children.Add(CreateWatermark(width, height, "Takako (" + pageno.ToString() + ")"));
                    
                    ////横向还是纵向
                    PrintTicket pt = new PrintTicket();
                    
                    pt.PageMediaSize = new PageMediaSize(width, height);
                    pt.PageOrientation = (width > height) ? PageOrientation.Landscape : PageOrientation.Portrait;
                    vxpsd.Write(newpage, pt);

                    pageno++;

                }
            }
            vxpsd.EndBatchWrite();
            container.Close();
        }
    }

    /// <summary>
    /// 创建背景色
    /// alpha 的值为 0 表示透明,alpha 的值为 255 则表示不透明.
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <returns></returns>
    private Visual CreateBackGround(double x, double y, double width, double height)
    {
        DrawingVisual background = new DrawingVisual();

        using (DrawingContext dc = background.RenderOpen())
        {
            dc.DrawRectangle(new SolidColorBrush(Color.FromArgb(100, 255, 255, 0)), null, new Rect(x, y, width, height));
        }

        return background;
    }

    /// <summary>
    /// 创建水印
    /// </summary>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <param name="message"></param>
    /// <returns></returns>
    private Visual CreateWatermark(double width, double height, string message)
    {
        DrawingVisual watermark = new DrawingVisual();
        using (DrawingContext ctx = watermark.RenderOpen())
        {
            FormattedText text = new FormattedText(message,

                            System.Globalization.CultureInfo.CurrentCulture,

                            FlowDirection.LeftToRight,

                            new Typeface("Times New Roman"), 96 * 1.5,

                            new SolidColorBrush(Color.FromScRgb(0.3f, 1f, 0f, 0f))
            );

            // Rotate transform, keep center

            {
                double diag = Math.Sqrt(width * width + height * height);

                double cX = width / 2;

                double cY = height / 2;

                double sin = height / diag;

                double cos = width / diag;

                double dx = (cX * (1.0 - cos)) + (cY * sin);

                double dy = (cY * (1.0 - cos)) - (cX * sin);

                Transform mat = new MatrixTransform(cos, sin, -sin, cos, dx, dy);

                ctx.PushTransform(mat);
            }

            // Centerlize

            double x = (width - text.Width) / 2;

            double y = (height - text.Height) / 2;

            ctx.DrawText(text, new Point(x, y));

            ctx.Pop();
        }
        return watermark;
    }

    public List<BackgroundRect> GetBackgroundRect(FixedPage page, string keyword)
    {
        List<BackgroundRect> lstBackgroundRect = new List<BackgroundRect>();
        foreach (UIElement element in page.Children)
        {
            if (element is Glyphs)
            {
                lstBackgroundRect.AddRange(GetBackgroundRect((Glyphs)element, keyword));
            }
            if (element is Canvas)
            {
                Canvas canvas = (Canvas)element;
                foreach (UIElement element2 in canvas.Children)
                {
                    if (element2 is Glyphs)
                    {
                        lstBackgroundRect.AddRange(GetBackgroundRect((Glyphs)element2, keyword));
                    }
                }
            }
        }

        return lstBackgroundRect;
    }

    public List<BackgroundRect> GetBackgroundRect(Glyphs glyphs, string keyword)
    {
        List<BackgroundRect> lstBackgroundRect = new List<BackgroundRect>();

        string value = glyphs.UnicodeString;

        if (value.Contains(keyword))
        {
            GlyphRun grun = glyphs.ToGlyphRun();


            //关键字所在的index
            List<int> indexs = new List<int>();
            indexs = GetIndexs(value, keyword);

            //算出高度
            double height = glyphs.FontRenderingEmSize * glyphs.RenderTransform.Value.M22;

            foreach (int index in indexs)
            {
                //算出宽度
                double width = 0;
                for (int i = index; i < keyword.Length + index; i++)
                {
                    width += grun.AdvanceWidths[i] * glyphs.RenderTransform.Value.M11;
                }

                //算出X:X = OriginX + 关键字前面字的宽度 + 偏移量
                //用office 2007 Save as XPS or PDF得出的 OriginX非常准确,但用打印机确定生成OriginX 看上去需要往右偏一点,不要问我为什么,莫名其妙它就是偏左!!!
                double x = glyphs.OriginX * glyphs.RenderTransform.Value.M11;

                for (int i = 0; i < index; i++)
                {
                    x += grun.AdvanceWidths[i] * glyphs.RenderTransform.Value.M11;
                }

                //算出Y
                double y = glyphs.OriginY * glyphs.RenderTransform.Value.M22;

                IChangeRect ICR = new ChangeRect3();
                BackgroundRect br = ICR.GetNewRect(new BackgroundRect() { X = x, Y = y, Width = width, Height = height });

                lstBackgroundRect.Add(br);
            }
        }
        return lstBackgroundRect;
    }

    /// <summary>
    /// 找出某一个节点中所有关键字的Index
    /// </summary>
    /// <param name="value"></param>
    /// <param name="keyword"></param>
    /// <returns></returns>
    public List<int> GetIndexs(string value, string keyword)
    {
        //空白的别搜了,浪费时间浪费内容。
        if (string.IsNullOrEmpty(keyword))
            return new List<int>();

        List<int> lstIndex = new List<int>();

        int index = value.IndexOf(keyword);
        if (index != -1)
        {
            lstIndex.Add(index);
            while (index != -1)
            {
                index = value.IndexOf(keyword, index + keyword.Length, value.Length - index - keyword.Length);
                if (index != -1)
                {
                    lstIndex.Add(index);
                }
            }
        }

        return lstIndex;
    }
}

public class BackgroundRect
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
}

public interface IChangeRect 
{
    BackgroundRect GetNewRect(BackgroundRect oldRect);
}

/// <summary>
/// 维持原先的不变
/// </summary>
public class ChangeRect1 : IChangeRect
{
    public BackgroundRect GetNewRect(BackgroundRect oldRect)
    {
        return oldRect;
    }
}

/// <summary>
/// X轴往右偏移21.5
/// </summary>
public class ChangeRect2 : IChangeRect
{
    public BackgroundRect GetNewRect(BackgroundRect oldRect)
    {
        oldRect.X += 21.5;
        return oldRect;
    }
}

/// <summary>
/// 用我们自己的驱动,Y轴是有偏移的,需要自定义一下!!!
/// </summary>
public class ChangeRect3 : IChangeRect
{
    public BackgroundRect GetNewRect(BackgroundRect oldRect)
    {
        oldRect.X += 21.5;

        double size = (int)oldRect.Height;
        if (size > 0 && size <= 15)
        {
            oldRect.Y += 5;
        }
        else
        {
            oldRect.Y -= (size - 15) * 4 / 5;
        }

        return oldRect;
    }
}