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;
}
}