/*
* Copyright (C) 2013 FooProject
* * 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 .
*/
using System;
using System.Collections.Generic;
using Windows.Graphics.Display;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using SharpDX;
using DXGI = SharpDX.DXGI;
using D2D = SharpDX.Direct2D1;
using D3D = SharpDX.Direct3D;
using D3D11 = SharpDX.Direct3D11;
using FooEditEngine.Metro;
using DotNetTextStore;
using DotNetTextStore.UnmanagedAPI.TSF;
using DotNetTextStore.UnmanagedAPI.WinDef;
namespace FooEditEngine
{
sealed class D2DRender : D2DRenderBase,IEditorRender
{
SurfaceImageSource SurfaceImage;
DXGI.ISurfaceImageSourceNative SurfaceImageNative;
D2D.Device D2DDevice;
D2D.DeviceContext D2DContext;
D2D.Bitmap1 Bitmap;
Size Size = new Size();
DXGI.Surface Surface;
TextStore2 store;
public D2DRender(FooTextBox textbox,Windows.UI.Xaml.Shapes.Rectangle rect,TextStore2 store)
: base()
{
this.ConstructDeviceResource(rect.ActualWidth,rect.ActualHeight);
this.InitTextFormat(textbox.FontFamily, textbox.FontSize);
this.store = store;
this.Size.Width = rect.ActualWidth;
this.Size.Height = rect.ActualHeight;
this.CreateSurface(rect, rect.ActualWidth, rect.ActualHeight);
base.PreDrawOneLine = D2DRender_PreDrawOneLine;
this.Foreground = D2DRenderBase.ToColor4( textbox.Foreground);
this.Background = D2DRenderBase.ToColor4(textbox.Background);
this.Hilight = D2DRenderBase.ToColor4(textbox.Hilight);
this.Keyword1 = D2DRenderBase.ToColor4(textbox.Keyword1);
this.Keyword2 = D2DRenderBase.ToColor4(textbox.Keyword2);
this.Literal = D2DRenderBase.ToColor4(textbox.Literal);
this.Url = D2DRenderBase.ToColor4(textbox.URL);
this.ControlChar = D2DRenderBase.ToColor4(textbox.ControlChar);
this.Comment = D2DRenderBase.ToColor4(textbox.Comment);
this.InsertCaret = D2DRenderBase.ToColor4(textbox.InsertCaret);
this.OverwriteCaret = D2DRenderBase.ToColor4(textbox.OverwriteCaret);
this.LineMarker = D2DRenderBase.ToColor4(textbox.LineMarker);
this.UpdateArea = D2DRenderBase.ToColor4(textbox.UpdateArea);
this.LineNumber = D2DRenderBase.ToColor4(textbox.LineNumber);
}
void D2DRender_PreDrawOneLine(MyTextLayout layout,LineToIndexTable lti, int row, double x, double y)
{
using (Unlocker locker = this.store.LockDocument(false))
{
int lineIndex = lti.GetIndexFromLineNumber(row);
int lineLength = lti.GetLengthFromLineNumber(row);
foreach (TextDisplayAttribute attr in this.store.EnumAttributes(lineIndex, lineIndex + lineLength))
{
if (attr.startIndex == attr.endIndex)
continue;
int length = attr.endIndex - attr.startIndex;
int start = attr.startIndex - lineIndex;
HilightType type = HilightType.None;
Color4? color = null;
switch (attr.attribute.lsStyle)
{
case TF_DA_LINESTYLE.TF_LS_DOT:
type = HilightType.Dot;
color = this.Foreground;
break;
case TF_DA_LINESTYLE.TF_LS_SOLID:
type = HilightType.Sold;
color = this.Foreground;
break;
case TF_DA_LINESTYLE.TF_LS_DASH:
type = HilightType.Dash;
color = this.Foreground;
break;
case TF_DA_LINESTYLE.TF_LS_SQUIGGLE:
type = HilightType.Squiggle;
color = this.Foreground;
break;
}
if (attr.attribute.crBk.type != TF_DA_COLORTYPE.TF_CT_NONE)
{
type = HilightType.Select;
color = this.Hilight;
}
this.DrawMarkerEffect(layout, type, start, length, x, y, attr.attribute.fBoldLine, color);
}
}
}
public override void GetDpi(out float dpix, out float dpiy)
{
Util.GetDpi(out dpix, out dpiy);
}
public bool Resize(Windows.UI.Xaml.Shapes.Rectangle rect, double width, double height)
{
if (this.Size.Width == width && this.Size.Height == height)
return false;
this.ReConstructDeviceResource(width, height);
this.CreateSurface(rect, width, height);
return true;
}
public bool IsCanDraw()
{
return this.Size.Height != 0 && this.Size.Width != 0;
}
public void DrawContent(EditView view,bool IsEnabled,Rectangle updateRect)
{
SharpDX.Mathematics.Interop.RawPoint offset;
this.Surface = this.SurfaceImageNative.BeginDraw(
new SharpDX.Rectangle(0, 0, (int)this.Size.Width, (int)this.Size.Height), out offset);
float dpix, dpiy;
this.GetDpi(out dpix, out dpiy);
D2D.BitmapProperties1 prop = new D2D.BitmapProperties1(new D2D.PixelFormat(DXGI.Format.B8G8R8A8_UNorm, D2D.AlphaMode.Premultiplied),
dpix, dpiy, D2D.BitmapOptions.Target | D2D.BitmapOptions.CannotDraw);
this.Bitmap = new D2D.Bitmap1(this.D2DContext, this.Surface, prop);
this.D2DContext.Target = this.Bitmap;
this.D2DContext.Transform = Matrix3x2.Translation(offset.X, offset.Y);
base.BegineDraw();
if (IsEnabled)
view.Draw(updateRect);
else
this.FillBackground(updateRect);
base.EndDraw();
this.Surface.Dispose();
this.Bitmap.Dispose();
this.SurfaceImageNative.EndDraw();
}
void CreateSurface(Windows.UI.Xaml.Shapes.Rectangle rect, double width, double height)
{
if (this.SurfaceImageNative != null)
this.SurfaceImageNative.Dispose();
this.SurfaceImage = new SurfaceImageSource((int)width, (int)height);
this.SurfaceImageNative = ComObject.As(this.SurfaceImage);
this.SurfaceImageNative.Device = this.DXGIDevice;
this.Size.Width = width;
this.Size.Height = height;
ImageBrush brush = new ImageBrush();
brush.ImageSource = this.SurfaceImage;
rect.Fill = brush;
}
protected override D2D.RenderTarget ConstructRender(D2D.Factory1 factory, D2D.RenderTargetProperties prop, double width, double height)
{
this.D2DDevice = new D2D.Device(factory,this.DXGIDevice);
this.D2DContext = new D2D.DeviceContext(this.D2DDevice, D2D.DeviceContextOptions.None);
return this.D2DContext;
}
protected override void ConstrctedResource()
{
}
protected override void DestructRender()
{
if (this.D2DDevice != null)
this.D2DDevice.Dispose();
if (this.D2DContext != null)
this.D2DContext.Dispose();
}
protected override void ReCreateTarget()
{
}
}
}