-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added support for shading type 0, 4, 5, 6 and 7
- Loading branch information
Showing
50 changed files
with
2,070 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Copyright (c) PdfToSvg.NET contributors. | ||
// https://github.com/dmester/pdftosvg.net | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace PdfToSvg.Drawing.Rasterization | ||
{ | ||
/// <summary> | ||
/// For rasiterizing polygons. The rasterizer does not support anti-aliasing. | ||
/// </summary> | ||
internal class Canvas | ||
{ | ||
private EdgeTable edges; | ||
private int nextID = 1; | ||
|
||
public Canvas(int width, int height) | ||
{ | ||
if (width <= 0) throw new ArgumentOutOfRangeException(nameof(width)); | ||
if (height <= 0) throw new ArgumentOutOfRangeException(nameof(height)); | ||
|
||
this.edges = new EdgeTable(width, height); | ||
Width = width; | ||
Height = height; | ||
} | ||
|
||
public int Width { get; } | ||
public int Height { get; } | ||
|
||
public void FillPolygon(Rgba32Color color, Point[] points) | ||
{ | ||
var id = nextID++; | ||
|
||
for (var i = 1; i < points.Length; i++) | ||
{ | ||
edges.Add(new Edge(id, points[i - 1], points[i], color)); | ||
} | ||
|
||
// Close polygon | ||
if (points[0].X != points[points.Length - 1].X || | ||
points[0].Y != points[points.Length - 1].Y) | ||
{ | ||
edges.Add(new Edge(id, points[points.Length - 1], points[0], color)); | ||
} | ||
} | ||
|
||
public IEnumerable<byte[]> ReadRgbaRows() | ||
{ | ||
this.edges.Sort(); | ||
|
||
var layers = new LayerManager(); | ||
|
||
var row = new byte[Width * 4]; | ||
|
||
for (var y = 0; y < Height; y++) | ||
{ | ||
var intersections = this.edges[y]; | ||
|
||
layers.Clear(); | ||
|
||
var x = 0; | ||
var rowOffset = 0; | ||
|
||
var color = layers.CurrentColor; | ||
|
||
for (var i = 0; i < intersections.Count; i++) | ||
{ | ||
var intersection = intersections[i]; | ||
|
||
var intersectionX = (int)(intersection.X + 0.5); | ||
|
||
while (x < intersectionX && x < Width) | ||
{ | ||
row[rowOffset + 0] = (byte)color.Red; | ||
row[rowOffset + 1] = (byte)color.Green; | ||
row[rowOffset + 2] = (byte)color.Blue; | ||
row[rowOffset + 3] = (byte)color.Alpha; | ||
rowOffset += 4; | ||
x++; | ||
} | ||
|
||
color = layers.Add(intersection.Edge); | ||
} | ||
|
||
while (x < Width) | ||
{ | ||
row[rowOffset + 0] = (byte)color.Red; | ||
row[rowOffset + 1] = (byte)color.Green; | ||
row[rowOffset + 2] = (byte)color.Blue; | ||
row[rowOffset + 3] = (byte)color.Alpha; | ||
rowOffset += 4; | ||
x++; | ||
} | ||
|
||
yield return row; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright (c) PdfToSvg.NET contributors. | ||
// https://github.com/dmester/pdftosvg.net | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace PdfToSvg.Drawing.Rasterization | ||
{ | ||
internal struct Edge | ||
{ | ||
public Edge(int polygonId, Point from, Point to, Rgba32Color color) | ||
{ | ||
PolygonID = polygonId; | ||
From = from; | ||
To = to; | ||
Color = color; | ||
} | ||
|
||
public Point From { get; private set; } | ||
public Point To { get; private set; } | ||
|
||
public int PolygonID { get; private set; } | ||
public Rgba32Color Color { get; private set; } | ||
|
||
public override string ToString() | ||
{ | ||
return PolygonID + ": " + From + "; " + To; | ||
} | ||
|
||
public double Intersection(double y) | ||
{ | ||
var dx = (To.X - From.X) * (From.Y - y) / (From.Y - To.Y); | ||
return From.X + dx; | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/PdfToSvg/Drawing/Rasterization/EdgeIntersectionRange.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Copyright (c) PdfToSvg.NET contributors. | ||
// https://github.com/dmester/pdftosvg.net | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Text; | ||
|
||
namespace PdfToSvg.Drawing.Rasterization | ||
{ | ||
[DebuggerDisplay("{FromX} {Width}")] | ||
internal struct EdgeIntersectionRange | ||
{ | ||
public double X; | ||
public Edge Edge; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// Copyright (c) PdfToSvg.NET contributors. | ||
// https://github.com/dmester/pdftosvg.net | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace PdfToSvg.Drawing.Rasterization | ||
{ | ||
internal class EdgeTable | ||
{ | ||
private List<EdgeIntersectionRange>[] scanlines; | ||
private int width; | ||
|
||
public EdgeTable(int width, int height) | ||
{ | ||
if (width <= 0) throw new ArgumentOutOfRangeException(nameof(width)); | ||
if (height <= 0) throw new ArgumentOutOfRangeException(nameof(height)); | ||
|
||
scanlines = new List<EdgeIntersectionRange>[height]; | ||
this.width = width; | ||
} | ||
|
||
private class EdgeComparer : IComparer<EdgeIntersectionRange> | ||
{ | ||
public int Compare(EdgeIntersectionRange x, EdgeIntersectionRange y) | ||
{ | ||
if (x.X < y.X) | ||
{ | ||
return -1; | ||
} | ||
if (x.X > y.X) | ||
{ | ||
return 1; | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
public void Add(Edge edge) | ||
{ | ||
int minY, maxY; | ||
|
||
if (edge.From.Y == edge.To.Y) | ||
{ | ||
// Skip horizontal lines | ||
return; | ||
} | ||
|
||
if (edge.From.X >= width && edge.To.X >= width) | ||
{ | ||
// Skip edges entirely to the right of the viewport | ||
return; | ||
} | ||
|
||
// Edges crossing the right side of the viewport need to | ||
// be clipped. | ||
if ((edge.From.X > width) ^ (edge.To.X > width)) | ||
{ | ||
var intersectingY = edge.From.Y + | ||
(edge.To.Y - edge.From.Y) * (width - edge.From.X) / (edge.To.X - edge.From.X); | ||
|
||
if (edge.From.X > width) | ||
{ | ||
// Keep To-point | ||
edge = new Edge(edge.PolygonID, | ||
new Point(width, intersectingY), edge.To, | ||
edge.Color); | ||
} | ||
else | ||
{ | ||
// Keep From-point | ||
edge = new Edge(edge.PolygonID, | ||
edge.From, new Point(width, intersectingY), | ||
edge.Color); | ||
} | ||
} | ||
|
||
if (edge.From.Y < 0 && edge.To.Y < 0) | ||
{ | ||
// Skip edges entirely above the viewport | ||
return; | ||
} | ||
|
||
if (edge.From.Y >= scanlines.Length && edge.To.Y >= scanlines.Length) | ||
{ | ||
// Skip edges entirely below the viewport | ||
return; | ||
} | ||
|
||
// Determine lower and upper vertical bounds | ||
if (edge.From.Y < edge.To.Y) | ||
{ | ||
minY = (int)(edge.From.Y + 0.5); | ||
maxY = (int)(edge.To.Y + 0.5); | ||
} | ||
else | ||
{ | ||
minY = (int)(edge.To.Y + 0.5); | ||
maxY = (int)(edge.From.Y + 0.5); | ||
} | ||
|
||
// We only need to add the edge to the visible scanlines | ||
if (minY < 0) | ||
{ | ||
minY = 0; | ||
} | ||
if (maxY > scanlines.Length) | ||
{ | ||
maxY = scanlines.Length; | ||
} | ||
|
||
var y = minY; | ||
|
||
while (y < maxY) | ||
{ | ||
var x = edge.Intersection(y + 0.5f); | ||
|
||
var scanline = scanlines[y]; | ||
if (scanline == null) | ||
{ | ||
scanlines[y] = scanline = new List<EdgeIntersectionRange>(); | ||
} | ||
scanline.Add(new EdgeIntersectionRange | ||
{ | ||
X = x, | ||
Edge = edge | ||
}); | ||
|
||
y++; | ||
} | ||
} | ||
|
||
public void Sort() | ||
{ | ||
var comparer = new EdgeComparer(); | ||
|
||
for (var i = 0; i < scanlines.Length; i++) | ||
{ | ||
scanlines[i]?.Sort(comparer); | ||
} | ||
} | ||
|
||
public IList<EdgeIntersectionRange> this[int y] | ||
{ | ||
get { return scanlines[y] ?? (IList<EdgeIntersectionRange>)new EdgeIntersectionRange[0]; } | ||
} | ||
} | ||
} |
Oops, something went wrong.