Skip to content

Commit

Permalink
UPD: Make pdf renderer "streamy"
Browse files Browse the repository at this point in the history
  • Loading branch information
janisstreib committed Apr 29, 2015
1 parent f6be71e commit 6e27f03
Show file tree
Hide file tree
Showing 14 changed files with 377 additions and 307 deletions.
27 changes: 14 additions & 13 deletions src/de/yellowant/xojtoimage/renderer/pdf/PdfArray.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
package de.yellowant.xojtoimage.renderer.pdf;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.List;

/**
* @author Anton Schirg
*/
public class PdfArray extends PdfObject {
public List<PdfObject> elements = new LinkedList<>();
public List<PdfObject> elements = new LinkedList<>();

@Override
public String render() {
StringBuilder sb = new StringBuilder();
sb.append("[");
String delim = "";
for (PdfObject element : elements) {
sb.append(delim).append(element.render());
delim = " ";
}
sb.append("]");
return sb.toString();
}
@Override
public void render(OutputStreamWriter out) throws IOException {
out.write("[");
String delim = "";
for (PdfObject element : elements) {
out.write(delim);
element.render(out);
delim = " ";
}
out.write("]");
}
}
28 changes: 14 additions & 14 deletions src/de/yellowant/xojtoimage/renderer/pdf/PdfDictionary.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
package de.yellowant.xojtoimage.renderer.pdf;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

/**
* @author Anton Schirg
*/
public class PdfDictionary extends PdfObject {
public Map<PdfName, PdfObject> dict = new HashMap<>();
public Map<PdfName, PdfObject> dict = new HashMap<>();

@Override
public String render() {
StringBuilder sb = new StringBuilder();
sb.append("<< ");
for (Map.Entry<PdfName, PdfObject> pdfObjectEntry : dict.entrySet()) {
sb.append(pdfObjectEntry.getKey().render());
sb.append(" ");
sb.append(pdfObjectEntry.getValue().render());
sb.append("\n");
}
sb.append(">>");
return sb.toString();
}
@Override
public void render(OutputStreamWriter out) throws IOException {
out.write("<< ");
for (Map.Entry<PdfName, PdfObject> pdfObjectEntry : dict.entrySet()) {
pdfObjectEntry.getKey().render(out);
out.write(" ");
pdfObjectEntry.getValue().render(out);
out.write("\n");
}
out.write(">>");
}
}
167 changes: 89 additions & 78 deletions src/de/yellowant/xojtoimage/renderer/pdf/PdfDocument.java
Original file line number Diff line number Diff line change
@@ -1,88 +1,99 @@
package de.yellowant.xojtoimage.renderer.pdf;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.LinkedList;
import java.util.List;

/**
* @author Anton Schirg
*/
public class PdfDocument {
public List<PdfPage> pages = new LinkedList<>();
public List<PdfIndirectObject> fonts = new LinkedList<>();
final PdfIndirectObject rootObject;

final PdfIndirectObject pagesObject;
final PdfArray pagesArray;
private int objectCounter = 0;
private final PdfLong pageCount;

public PdfDocument() {
PdfDictionary catalogDict = new PdfDictionary();
catalogDict.dict.put(new PdfName("Type"), new PdfName("Catalog"));
rootObject = constructIndirectObject(catalogDict);

PdfDictionary pagesDict = new PdfDictionary();
pagesDict.dict.put(new PdfName("Type"), new PdfName("Pages"));
pagesArray = new PdfArray();
pagesDict.dict.put(new PdfName("Kids"), pagesArray);
pagesObject = constructIndirectObject(pagesDict);
pageCount = new PdfLong(pagesArray.elements.size());
pagesDict.dict.put(new PdfName("Count"), pageCount);
catalogDict.dict.put(new PdfName("Pages"), new PdfIndirectReference(pagesObject));
}

public String render() {
StringBuilder sb = new StringBuilder();
sb.append("%PDF-1.0\n\n");

sb.append(rootObject.render()).append("\n\n");

sb.append(pagesObject.render()).append("\n\n");

for (PdfIndirectObject font : fonts) {
sb.append(font.render()).append("\n");
}
sb.append("\n");

for (PdfPage page : pages) {
sb.append(page.render()).append("\n");
}
sb.append("\n");

sb.append("xref\n");
sb.append("0 ").append(objectCounter + 1).append("\n\n"); //Num object incl xref

sb.append("trailer\n");
PdfDictionary trailerDict = new PdfDictionary();
trailerDict.dict.put(new PdfName("Size"), new PdfLong(objectCounter + 1));
trailerDict.dict.put(new PdfName("Root"), new PdfIndirectReference(rootObject));
sb.append(trailerDict.render()).append("\n");
sb.append("startxref\n\n");

sb.append("%%EOF");
return sb.toString();
}

public PdfIndirectObject constructIndirectObject(PdfObject object) {
objectCounter++;
return new PdfIndirectObject(object, objectCounter, 0);
}

public PdfPage addPage(double width, double height) {
PdfPage page = new PdfPage(this,width, height);
pages.add(page);
pagesArray.elements.add(new PdfIndirectReference(page.page));
pageCount.value = pagesArray.elements.size();
return page;
}

public PdfIndirectObject addFont(String baseFont) {
PdfDictionary fontDefDict = new PdfDictionary();
fontDefDict.dict.put(new PdfName("Type"), new PdfName("Font"));
fontDefDict.dict.put(new PdfName("Subtype"), new PdfName("Type1"));
fontDefDict.dict.put(new PdfName("BaseFont"), new PdfName(baseFont));
PdfIndirectObject indirectObject = constructIndirectObject(fontDefDict);
fonts.add(indirectObject);
return indirectObject;
}
public List<PdfPage> pages = new LinkedList<>();
public List<PdfIndirectObject> fonts = new LinkedList<>();
final PdfIndirectObject rootObject;

final PdfIndirectObject pagesObject;
final PdfArray pagesArray;
private int objectCounter = 0;
private final PdfLong pageCount;

public PdfDocument() {
PdfDictionary catalogDict = new PdfDictionary();
catalogDict.dict.put(new PdfName("Type"), new PdfName("Catalog"));
rootObject = constructIndirectObject(catalogDict);

PdfDictionary pagesDict = new PdfDictionary();
pagesDict.dict.put(new PdfName("Type"), new PdfName("Pages"));
pagesArray = new PdfArray();
pagesDict.dict.put(new PdfName("Kids"), pagesArray);
pagesObject = constructIndirectObject(pagesDict);
pageCount = new PdfLong(pagesArray.elements.size());
pagesDict.dict.put(new PdfName("Count"), pageCount);
catalogDict.dict.put(new PdfName("Pages"), new PdfIndirectReference(
pagesObject));
}

public void render(OutputStreamWriter out) throws IOException {
out.write("%PDF-1.0\n\n");

rootObject.render(out);
out.write("\n\n");

pagesObject.render(out);
out.write("\n\n");

for (PdfIndirectObject font : fonts) {
font.render(out);
out.write("\n");
}
out.write("\n");

for (PdfPage page : pages) {
page.render(out);
out.write("\n");
}
out.write("\n");

out.write("xref\n");
out.write("0 ");
out.write(objectCounter + 1);
out.write("\n\n"); // Num object
// incl xref

out.write("trailer\n");
PdfDictionary trailerDict = new PdfDictionary();
trailerDict.dict.put(new PdfName("Size"),
new PdfLong(objectCounter + 1));
trailerDict.dict.put(new PdfName("Root"), new PdfIndirectReference(
rootObject));
trailerDict.render(out);
out.write("\n");
out.write("startxref\n\n");

out.write("%%EOF");
}

public PdfIndirectObject constructIndirectObject(PdfObject object) {
objectCounter++;
return new PdfIndirectObject(object, objectCounter, 0);
}

public PdfPage addPage(double width, double height) {
PdfPage page = new PdfPage(this, width, height);
pages.add(page);
pagesArray.elements.add(new PdfIndirectReference(page.page));
pageCount.value = pagesArray.elements.size();
return page;
}

public PdfIndirectObject addFont(String baseFont) {
PdfDictionary fontDefDict = new PdfDictionary();
fontDefDict.dict.put(new PdfName("Type"), new PdfName("Font"));
fontDefDict.dict.put(new PdfName("Subtype"), new PdfName("Type1"));
fontDefDict.dict.put(new PdfName("BaseFont"), new PdfName(baseFont));
PdfIndirectObject indirectObject = constructIndirectObject(fontDefDict);
fonts.add(indirectObject);
return indirectObject;
}
}
57 changes: 30 additions & 27 deletions src/de/yellowant/xojtoimage/renderer/pdf/PdfExtGState.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.yellowant.xojtoimage.renderer.pdf;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -8,34 +10,35 @@
*/
public class PdfExtGState extends PdfObject {

public Map<Integer, PdfName> alphas; //Alpha in percent
int alphaNameCounter = 0;
public Map<Integer, PdfName> alphas; // Alpha in percent
int alphaNameCounter = 0;

public PdfExtGState() {
alphas = new HashMap<>();
}
public PdfExtGState() {
alphas = new HashMap<>();
}

public PdfName getAlpha(double opacity) {
int alpha = (int) (opacity * 100);
PdfName alphaName = alphas.get(alpha);
if (alphaName != null) {
return alphaName;
} else {
alphaName = new PdfName("a" + alphaNameCounter);
alphaNameCounter++;
alphas.put(alpha, alphaName);
return alphaName;
}
}
public PdfName getAlpha(double opacity) {
int alpha = (int) (opacity * 100);
PdfName alphaName = alphas.get(alpha);
if (alphaName != null) {
return alphaName;
} else {
alphaName = new PdfName("a" + alphaNameCounter);
alphaNameCounter++;
alphas.put(alpha, alphaName);
return alphaName;
}
}

@Override
public String render() {
PdfDictionary gstate = new PdfDictionary();
for (Map.Entry<Integer, PdfName> alphaEntry : alphas.entrySet()) {
PdfDictionary innerDict = new PdfDictionary();
innerDict.dict.put(new PdfName("CA"), new PdfReal(alphaEntry.getKey() / 100.0));
gstate.dict.put(alphaEntry.getValue(), innerDict);
}
return gstate.render();
}
@Override
public void render(OutputStreamWriter out) throws IOException {
PdfDictionary gstate = new PdfDictionary();
for (Map.Entry<Integer, PdfName> alphaEntry : alphas.entrySet()) {
PdfDictionary innerDict = new PdfDictionary();
innerDict.dict.put(new PdfName("CA"),
new PdfReal(alphaEntry.getKey() / 100.0));
gstate.dict.put(alphaEntry.getValue(), innerDict);
}
gstate.render(out);
}
}
39 changes: 22 additions & 17 deletions src/de/yellowant/xojtoimage/renderer/pdf/PdfIndirectObject.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
package de.yellowant.xojtoimage.renderer.pdf;

import java.io.IOException;
import java.io.OutputStreamWriter;

/**
* @author Anton Schirg
*/
public class PdfIndirectObject extends PdfObject { //TODO Make generic for contained object type
public PdfObject object;
public int number;
public int generation;
public class PdfIndirectObject extends PdfObject { // TODO Make generic for
// contained object type
public PdfObject object;
public int number;
public int generation;

public PdfIndirectObject(PdfObject object, int number, int generation) {
this.object = object;
this.number = number;
this.generation = generation;
}
public PdfIndirectObject(PdfObject object, int number, int generation) {
this.object = object;
this.number = number;
this.generation = generation;
}

@Override
public String render() {
StringBuilder sb = new StringBuilder();
sb.append(number).append(" ").append(generation).append(" obj\n");
sb.append(object.render());
sb.append("\nendobj");
return sb.toString();
}
@Override
public void render(OutputStreamWriter out) throws IOException {
out.write(number + "");
out.write(" ");
out.write(generation + "");
out.write(" obj\n");
object.render(out);
out.write("\nendobj");
}
}
Loading

0 comments on commit 6e27f03

Please sign in to comment.