/*
http://www.cgsoso.com/forum-211-1.html
CG搜搜 Unity3d 每日Unity3d插件免费更新 更有VIP资源!
CGSOSO 主打游戏开发,影视设计等CG资源素材。
插件如若商用,请务必官网购买!
daily assets update for try.
U should buy the asset from home store if u use it in your project!
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Paroxe.PdfRenderer.Internal;
using UnityEngine;
using System.Threading;
using System.Collections;
using Paroxe.PdfRenderer.WebGL;
namespace Paroxe.PdfRenderer
{
///
/// This class allow the application to render pages into textures.
///
public class PDFRenderer : IDisposable
{
private bool m_Disposed;
#if !UNITY_WEBGL || UNITY_EDITOR
private PDFBitmap m_Bitmap;
private byte[] m_IntermediateBuffer;
#endif
public PDFRenderer()
{
PDFLibrary.AddRef("PDFRenderer");
}
~PDFRenderer()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!m_Disposed)
{
if (disposing)
{
#if !UNITY_WEBGL || UNITY_EDITOR
m_Bitmap.Dispose();
m_Bitmap = null;
#endif
}
PDFLibrary.RemoveRef("PDFRenderer");
m_Disposed = true;
}
}
#if UNITY_WEBGL
public class RenderPageParameters
{
public IntPtr pageHandle;
public Texture2D existingTexture;
public Vector2 newTextureSize;
public RenderPageParameters(IntPtr pageHandle, Texture2D existingTexture, Vector2 newTextureSize)
{
this.pageHandle = pageHandle;
this.existingTexture = existingTexture;
this.newTextureSize = newTextureSize;
}
}
#endif
public static PDFJS_Promise RenderPageToExistingTextureAsync(PDFPage page, Texture2D tex)
{
PDFJS_Promise renderPromise = new PDFJS_Promise();
#if !UNITY_WEBGL || UNITY_EDITOR
using (PDFRenderer renderer = new PDFRenderer())
{
renderPromise.HasFinished = true;
renderPromise.HasSucceeded = true;
renderPromise.HasReceivedJSResponse = true;
renderer.RenderPageToExistingTexture(page, tex);
renderPromise.Result = tex;
}
#else
RenderPageParameters parameters = new RenderPageParameters(page.NativePointer, tex, new Vector2(tex.width, tex.height));
PDFJS_Library.Instance.PreparePromiseCoroutine(RenderPageCoroutine, renderPromise, parameters).Start();
#endif
return renderPromise;
}
public static PDFJS_Promise RenderPageToTextureAsync(PDFPage page, int width, int height)
{
return RenderPageToTextureAsync(page, new Vector2(width, height));
}
public static PDFJS_Promise RenderPageToTextureAsync(PDFPage page, Vector2 size)
{
PDFJS_Promise renderPromise = new PDFJS_Promise();
#if !UNITY_WEBGL || UNITY_EDITOR
using (PDFRenderer renderer = new PDFRenderer())
{
renderPromise.HasFinished = true;
renderPromise.HasSucceeded = true;
renderPromise.HasReceivedJSResponse = true;
renderPromise.Result = renderer.RenderPageToTexture(page, (int)size.x, (int)size.y);
}
#else
RenderPageParameters parameters = new RenderPageParameters(page.NativePointer, null, size);
PDFJS_Library.Instance.PreparePromiseCoroutine(RenderPageCoroutine, renderPromise, parameters).Start();
#endif
return renderPromise;
}
public static PDFJS_Promise RenderPageToTextureAsync(PDFPage page, float scale = 1.0f)
{
PDFJS_Promise renderPromise = new PDFJS_Promise();
#if !UNITY_WEBGL || UNITY_EDITOR
using (PDFRenderer renderer = new PDFRenderer())
{
renderPromise.HasFinished = true;
renderPromise.HasSucceeded = true;
renderPromise.HasReceivedJSResponse = true;
Vector2 size = page.GetPageSize(scale);
renderPromise.Result = renderer.RenderPageToTexture(page, (int)size.x, (int)size.y);
}
#else
RenderPageParameters parameters = new RenderPageParameters(page.NativePointer, null, page.GetPageSize(scale));
PDFJS_Library.Instance.PreparePromiseCoroutine(RenderPageCoroutine, renderPromise, parameters).Start();
#endif
return renderPromise;
}
#if UNITY_WEBGL && !UNITY_EDITOR
private static IEnumerator RenderPageCoroutine(PDFJS_PromiseCoroutine promiseCoroutine, IPDFJS_Promise promise, object parameters)
{
PDFJS_Promise renderToCanvasPromise = new PDFJS_Promise();
PDFJS_Library.Instance.PreparePromiseCoroutine(null, renderToCanvasPromise, null);
IntPtr pageHandle = ((RenderPageParameters)parameters).pageHandle;
Texture2D texture = ((RenderPageParameters)parameters).existingTexture;
Vector2 newtextureSize = ((RenderPageParameters)parameters).newTextureSize;
Vector2 pageSize = PDFPage.GetPageSize(pageHandle, 1.0f);
float scale = 1.0f;
if (texture != null)
{
float wf = pageSize.x / texture.width;
float hf = pageSize.y / texture.height;
scale = 1.0f / Mathf.Max(wf, hf);
}
else
{
float wf = pageSize.x / ((int)newtextureSize.x);
float hf = pageSize.y / ((int)newtextureSize.y);
scale = 1.0f / Mathf.Max(wf, hf);
}
PDFJS_RenderPageIntoCanvas(renderToCanvasPromise.PromiseHandle, pageHandle.ToInt32(), scale);
while (!renderToCanvasPromise.HasReceivedJSResponse)
yield return null;
if (renderToCanvasPromise.HasSucceeded)
{
int canvasHandle = int.Parse(renderToCanvasPromise.JSObjectHandle);
using (PDFJS_WebGLCanvas canvas = new PDFJS_WebGLCanvas(new IntPtr(canvasHandle)))
{
PDFJS_Promise renderToTexturePromise = promise as PDFJS_Promise;
if (texture == null)
{
texture = new Texture2D((int)newtextureSize.x, (int)newtextureSize.y, TextureFormat.ARGB32, false);
texture.filterMode = FilterMode.Bilinear;
texture.Apply();
}
PDFJS_RenderCanvasIntoTexture(canvasHandle, texture.GetNativeTexturePtr().ToInt32());
renderToTexturePromise.Result = texture;
renderToTexturePromise.HasSucceeded = true;
renderToTexturePromise.HasFinished = true;
promiseCoroutine.ExecuteThenAction(true, texture);
}
}
else
{
PDFJS_Promise renderToTexturePromise = promise as PDFJS_Promise;
renderToTexturePromise.Result = null;
renderToTexturePromise.HasSucceeded = false;
renderToTexturePromise.HasFinished = true;
promiseCoroutine.ExecuteThenAction(false, null);
}
}
#endif
#if !UNITY_WEBGL || UNITY_EDITOR
///
/// Render page into a new byte array.
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
byte[] RenderPageToByteArray(PDFPage page)
{
return RenderPageToByteArray(page, (int) page.GetPageSize().x, (int) page.GetPageSize().y, null,
RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new byte array.
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
byte[] RenderPageToByteArray(PDFPage page, int width, int height)
{
return RenderPageToByteArray(page, width, height, null, RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new byte array.
///
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
byte[] RenderPageToByteArray(PDFPage page, int width, int height,
IPDFColoredRectListProvider rectsProvider)
{
return RenderPageToByteArray(page, width, height, rectsProvider, RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new byte array.
///
///
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
byte[] RenderPageToByteArray(PDFPage page, int width, int height,
IPDFColoredRectListProvider rectsProvider, RenderSettings settings)
{
if (m_Bitmap == null || !m_Bitmap.HasSameSize(width, height))
{
if (m_Bitmap != null)
m_Bitmap.Dispose();
m_Bitmap = new PDFBitmap(width, height, false);
}
m_Bitmap.FillRect(0, 0, width, height, int.MaxValue);
int flags = settings == null
? RenderSettings.defaultRenderSettings.ComputeRenderingFlags()
: settings.ComputeRenderingFlags();
FPDF_RenderPageBitmap(m_Bitmap.NativePointer, page.NativePointer, 0, 0, width, height, 0, flags);
IntPtr bufferPtr = m_Bitmap.GetBuffer();
if (bufferPtr == IntPtr.Zero)
return null;
int length = width * height * 4;
if (m_IntermediateBuffer == null || m_IntermediateBuffer.Length < length)
m_IntermediateBuffer = new byte[width * height * 4];
Marshal.Copy(bufferPtr, m_IntermediateBuffer, 0, width * height * 4);
#if !UNITY_WEBGL
IList coloredRects = rectsProvider != null
? rectsProvider.GetBackgroundColoredRectList(page)
: null;
if (coloredRects != null && coloredRects.Count > 0)
{
foreach (PDFColoredRect coloredRect in coloredRects)
{
var r = (int)(coloredRect.color.r * 255) & 0xFF;
var g = (int)(coloredRect.color.g * 255) & 0xFF;
var b = (int)(coloredRect.color.b * 255) & 0xFF;
var a = (int)(coloredRect.color.a * 255) & 0xFF;
float alpha = (a / (float)255);
float reverseAlpha = 1.0f - alpha;
Rect deviceRect = page.ConvertPageRectToDeviceRect(coloredRect.pageRect, new Vector2(width, height));
for (int y = 0; y < -(int)deviceRect.height; ++y)
{
for (int x = 0; x < (int)deviceRect.width; ++x)
{
int s = (((int)deviceRect.y + y + (int)deviceRect.height) * width + (int)deviceRect.x + x) * 4;
var sr = m_IntermediateBuffer[s];
var sg = m_IntermediateBuffer[s + 1];
var sb = m_IntermediateBuffer[s + 2];
m_IntermediateBuffer[s] = (byte)Mathf.Clamp(alpha * r + (reverseAlpha * sr), 0, 255);
m_IntermediateBuffer[s + 1] = (byte)Mathf.Clamp(alpha * g + (reverseAlpha * sg), 0, 255);
m_IntermediateBuffer[s + 2] = (byte)Mathf.Clamp(alpha * b + (reverseAlpha * sb), 0, 255);
m_IntermediateBuffer[s + 3] = 0xFF;
}
}
}
}
#endif
return m_IntermediateBuffer;
}
///
/// Render page into a new Texture2D.
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
Texture2D RenderPageToTexture(PDFPage page)
{
return RenderPageToTexture(page, (int) page.GetPageSize().x, (int) page.GetPageSize().y, null,
RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new Texture2D.
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
Texture2D RenderPageToTexture(PDFPage page, int width, int height)
{
return RenderPageToTexture(page, width, height, null, RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new Texture2D.
///
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
Texture2D RenderPageToTexture(PDFPage page, int width, int height,
IPDFColoredRectListProvider rectsProvider)
{
return RenderPageToTexture(page, width, height, rectsProvider, RenderSettings.defaultRenderSettings);
}
///
/// Render page into a new Texture2D.
///
///
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
Texture2D RenderPageToTexture(PDFPage page, int width, int height,
IPDFColoredRectListProvider rectsProvider, RenderSettings settings)
{
Texture2D newTex = new Texture2D(width, height, TextureFormat.RGBA32, false);
RenderPageToExistingTexture(page, newTex, rectsProvider, settings);
return newTex;
}
///
/// Render page into an existing Texture2D.
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
void RenderPageToExistingTexture(PDFPage page, Texture2D texture)
{
RenderPageToExistingTexture(page, texture, null, RenderSettings.defaultRenderSettings);
}
///
/// Render page into an existing Texture2D.
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
void RenderPageToExistingTexture(PDFPage page, Texture2D texture,
IPDFColoredRectListProvider rectsProvider)
{
RenderPageToExistingTexture(page, texture, rectsProvider, RenderSettings.defaultRenderSettings);
}
///
/// Render page into an existing Texture2D.
///
///
///
///
///
#if !UNITY_WEBGL
public
#else
private
#endif
void RenderPageToExistingTexture(PDFPage page, Texture2D texture,
IPDFColoredRectListProvider rectsProvider, RenderSettings settings)
{
byte[] byteArray = RenderPageToByteArray(page, texture.width, texture.height, rectsProvider, settings);
if (byteArray != null)
{
if ((texture.format != TextureFormat.RGBA32
&& texture.format != TextureFormat.ARGB32
&& texture.format != TextureFormat.BGRA32
&& texture.format != (TextureFormat)37) || texture.mipmapCount > 1)
{
Color32[] pixels = new Color32[texture.width * texture.height];
for (int i = 0; i < pixels.Length; ++i)
pixels[i] = new Color32(
byteArray[i * 4],
byteArray[i * 4 + 1],
byteArray[i * 4 + 2],
byteArray[i * 4 + 3]);
texture.SetPixels32(pixels);
texture.Apply();
}
else
{
texture.LoadRawTextureData(byteArray);
texture.Apply();
}
}
}
#endif
///
/// Allows the application to specify render settings.
///
[Serializable]
public class RenderSettings
{
public bool disableSmoothPath = false;
public bool disableSmoothText = false;
public bool grayscale = false;
public bool optimizeTextForLCDDisplay = false;
public bool renderAnnotations = false;
public bool renderForPrinting = false;
public static RenderSettings defaultRenderSettings
{
get { return new RenderSettings(); }
}
public int ComputeRenderingFlags()
{
int flags = 0x10;
if (renderAnnotations)
flags |= 0x01;
if (optimizeTextForLCDDisplay)
flags |= 0x02;
if (grayscale)
flags |= 0x08;
if (renderForPrinting)
flags |= 0x800;
if (disableSmoothText)
flags |= 0x1000;
if (disableSmoothPath)
flags |= 0x1000;
return flags;
}
}
#region NATIVE
#if UNITY_WEBGL && !UNITY_EDITOR
[DllImport(PDFLibrary.PLUGIN_ASSEMBLY)]
private static extern void PDFJS_RenderPageIntoCanvas(string promiseHandle, int pageHandle, float scale);
[DllImport(PDFLibrary.PLUGIN_ASSEMBLY)]
private static extern void PDFJS_RenderCanvasIntoTexture(int canvasHandle, int textureHandle);
#else
[DllImport(PDFLibrary.PLUGIN_ASSEMBLY)]
private static extern void FPDF_RenderPageBitmap(IntPtr bitmap, IntPtr page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags);
#endif
#endregion
}
}