Browse Source

implemented basic link with linking from pdf

improved some resolving of references


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@195155 13f79535-47bb-0310-9956-ffa450edef68
pull/30/head
Keiron Liddle 22 years ago
parent
commit
76c10e58dc

+ 215
- 39
src/org/apache/fop/area/AreaTree.java View File

/* /*
* $Id$ * $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the * For details on use and redistribution please refer to the
* LICENSE file included with these sources. * LICENSE file included with these sources.
*/ */
public class AreaTree { public class AreaTree {
// allows for different models to deal with adding/rendering // allows for different models to deal with adding/rendering
// in different situations // in different situations
AreaTreeModel model;
private AreaTreeModel model;


// hashmap of arraylists containing pages with id area // hashmap of arraylists containing pages with id area
HashMap idLocations = new HashMap();
private HashMap idLocations = new HashMap();
// list of id's yet to be resolved and arraylists of pages // list of id's yet to be resolved and arraylists of pages
HashMap resolve = new HashMap();
ArrayList treeExtensions = new ArrayList();

private HashMap resolve = new HashMap();
private ArrayList treeExtensions = new ArrayList();

/**
* Create a render pages area tree model.
* @param rend the renderer that will be used
* @return RenderPagesModel the new area tree model
*/
public RenderPagesModel createRenderPagesModel(Renderer rend) { public RenderPagesModel createRenderPagesModel(Renderer rend) {
return new RenderPagesModel(rend); return new RenderPagesModel(rend);
} }


/**
* Create a new store pages model.
* @return StorePagesModel the new model
*/
public static StorePagesModel createStorePagesModel() { public static StorePagesModel createStorePagesModel() {
return new StorePagesModel(); return new StorePagesModel();
} }


/**
* Set the tree model to use for this area tree.
* The different models can have different behaviour
* when pages area added and other changes.
* @param m the area tree model
*/
public void setTreeModel(AreaTreeModel m) { public void setTreeModel(AreaTreeModel m) {
model = m; model = m;
} }


/**
* Start a new page sequence.
* This signals that a new page sequence has started in the document.
* @param title the title of the new page sequence or null if no title
*/
public void startPageSequence(Title title) { public void startPageSequence(Title title) {
model.startPageSequence(title); model.startPageSequence(title);
} }


/**
* Add a new page to the area tree.
* @param page the page to add
*/
public void addPage(PageViewport page) { public void addPage(PageViewport page) {
model.addPage(page); model.addPage(page);
} }


/**
* Add an id reference pointing to a page viewport.
* @param id the id of the reference
* @param pv the page viewport that contains the id reference
*/
public void addIDRef(String id, PageViewport pv) { public void addIDRef(String id, PageViewport pv) {
ArrayList list = (ArrayList)idLocations.get(id);
if(list == null) {
List list = (List)idLocations.get(id);
if (list == null) {
list = new ArrayList(); list = new ArrayList();
idLocations.put(id, list); idLocations.put(id, list);
} }
list.add(pv); list.add(pv);


ArrayList todo = (ArrayList)resolve.get(id);
if(todo != null) {
for(int count = 0; count < todo.size(); count++) {
List todo = (List)resolve.get(id);
if (todo != null) {
for (int count = 0; count < todo.size(); count++) {
Resolveable res = (Resolveable)todo.get(count); Resolveable res = (Resolveable)todo.get(count);
res.resolve(id, list); res.resolve(id, list);
} }
} }
} }


/**
* Get the list of id references for an id.
* @param id the id to lookup
* @return the list of id references.
*/
public List getIDReferences(String id) {
return (List)idLocations.get(id);
}

/**
* Add an unresolved object with a given id.
* @param id the id reference that needs resolving
* @param res the Resolveable object to resolve
*/
public void addUnresolvedID(String id, Resolveable res) { public void addUnresolvedID(String id, Resolveable res) {
ArrayList todo = (ArrayList)resolve.get(id); ArrayList todo = (ArrayList)resolve.get(id);
if(todo == null) {
if (todo == null) {
todo = new ArrayList(); todo = new ArrayList();
resolve.put(id, todo); resolve.put(id, todo);
} }
todo.add(res); todo.add(res);
} }


/**
* Add a tree extension.
* This checks if the extension is resolveable and attempts
* to resolve or add the resolveable ids for later resolution.
* @param ext the tree extension to add.
*/
public void addTreeExtension(TreeExt ext) { public void addTreeExtension(TreeExt ext) {
treeExtensions.add(ext); treeExtensions.add(ext);
if(ext.isResolveable()) {
if (ext.isResolveable()) {
Resolveable res = (Resolveable)ext; Resolveable res = (Resolveable)ext;
String[] ids = res.getIDs(); String[] ids = res.getIDs();
for(int count = 0; count < ids.length; count++) {
if(idLocations.containsKey(ids[count])) {
for (int count = 0; count < ids.length; count++) {
if (idLocations.containsKey(ids[count])) {
res.resolve(ids[count], (ArrayList)idLocations.get(ids[count])); res.resolve(ids[count], (ArrayList)idLocations.get(ids[count]));
} else { } else {
ArrayList todo = (ArrayList)resolve.get(ids[count]); ArrayList todo = (ArrayList)resolve.get(ids[count]);
if(todo == null) {
if (todo == null) {
todo = new ArrayList(); todo = new ArrayList();
resolve.put(ids[count], todo); resolve.put(ids[count], todo);
} }
todo.add(ext); todo.add(ext);
} }
} }
} else {
handleTreeExtension(ext, TreeExt.IMMEDIATELY);
} }
} }


/**
* Handle a tree extension.
* This sends the extension to the model for handling.
* @param ext the tree extension to handle
* @param when when the extension should be handled by the model
*/
public void handleTreeExtension(TreeExt ext, int when) { public void handleTreeExtension(TreeExt ext, int when) {
// queue tree extension according to the when // queue tree extension according to the when
model.addExtension(ext, when); model.addExtension(ext, when);
} }


/**
* Signal end of document.
* This indicates that the document is complete and any unresolved
* reference can be dealt with.
*/
public void endDocument() { public void endDocument() {
for(Iterator iter = resolve.keySet().iterator(); iter.hasNext(); ) {
for (Iterator iter = resolve.keySet().iterator(); iter.hasNext();) {
String id = (String)iter.next(); String id = (String)iter.next();
ArrayList list = (ArrayList)resolve.get(id); ArrayList list = (ArrayList)resolve.get(id);
for(int count = 0; count < list.size(); count++) {
for (int count = 0; count < list.size(); count++) {
Resolveable res = (Resolveable)list.get(count); Resolveable res = (Resolveable)list.get(count);
if(!res.isResolved()) {
if (!res.isResolved()) {
res.resolve(id, null); res.resolve(id, null);
} }
} }
model.endDocument(); model.endDocument();
} }


// this is the model for the area tree object
public static abstract class AreaTreeModel {
/**
* This is the model for the area tree object.
* The model implementation can handle the page sequence,
* page and extensions.
*/
public abstract static class AreaTreeModel {
/**
* Start a page sequence on this model.
* @param title the title of the new page sequence
*/
public abstract void startPageSequence(Title title); public abstract void startPageSequence(Title title);

/**
* Add a page to this moel.
* @param page the page to add to the model.
*/
public abstract void addPage(PageViewport page); public abstract void addPage(PageViewport page);

/**
* Add an extension to this model.
* @param ext the extension to add
* @param when when the extension should be handled
*/
public abstract void addExtension(TreeExt ext, int when); public abstract void addExtension(TreeExt ext, int when);

/**
* Signal the end of the document for any processing.
*/
public abstract void endDocument(); public abstract void endDocument();
} }


// this class stores all the pages in the document
// for interactive agents
/**
* This class stores all the pages in the document
* for interactive agents.
* The pages are stored and can be retrieved in any order.
*/
public static class StorePagesModel extends AreaTreeModel { public static class StorePagesModel extends AreaTreeModel {
ArrayList pageSequence = null;
ArrayList titles = new ArrayList();
ArrayList currSequence;
ArrayList extensions = new ArrayList();

public StorePagesModel() {}
private ArrayList pageSequence = null;
private ArrayList titles = new ArrayList();
private ArrayList currSequence;
private ArrayList extensions = new ArrayList();

/**
* Create a new store pages model
*/
public StorePagesModel() {
}


/**
* Start a new page sequence.
* This creates a new list for the pages in the new page sequence.
* @param title the title of the page sequence.
*/
public void startPageSequence(Title title) { public void startPageSequence(Title title) {
titles.add(title); titles.add(title);
if (pageSequence == null) { if (pageSequence == null) {
pageSequence.add(currSequence); pageSequence.add(currSequence);
} }


/**
* Add a page.
* @param page the page to add to the current page sequence
*/
public void addPage(PageViewport page) { public void addPage(PageViewport page) {
currSequence.add(page); currSequence.add(page);
} }


/**
* Get the page sequence count.
* @return the number of page sequences in the document.
*/
public int getPageSequenceCount() { public int getPageSequenceCount() {
return pageSequence.size(); return pageSequence.size();
} }


/**
* Get the title for a page sequence.
* @param count the page sequence count
* @return the title of the page sequence
*/
public Title getTitle(int count) { public Title getTitle(int count) {
return (Title) titles.get(count); return (Title) titles.get(count);
} }


/**
* Get the page count.
* @param seq the page sequence to count.
* @return returns the number of pages in a page sequence
*/
public int getPageCount(int seq) { public int getPageCount(int seq) {
ArrayList sequence = (ArrayList) pageSequence.get(seq); ArrayList sequence = (ArrayList) pageSequence.get(seq);
return sequence.size(); return sequence.size();
} }


/**
* Get the page for a position in the document.
* @param seq the page sequence number
* @param count the page count in the sequence
* @return the PageViewport for the particular page
*/
public PageViewport getPage(int seq, int count) { public PageViewport getPage(int seq, int count) {
ArrayList sequence = (ArrayList) pageSequence.get(seq); ArrayList sequence = (ArrayList) pageSequence.get(seq);
return (PageViewport) sequence.get(count); return (PageViewport) sequence.get(count);
} }


/**
* Add an extension to the store page model.
* The extension is stored so that it can be retrieved in the
* appropriate position.
* @param ext the extension to add
* @param when when the extension should be handled
*/
public void addExtension(TreeExt ext, int when) { public void addExtension(TreeExt ext, int when) {
int seq, page; int seq, page;
switch(when) { switch(when) {
extensions.add(ext); extensions.add(ext);
} }


/**
* Get the list of extensions that apply at a particular
* position in the document.
* @param seq the page sequence number
* @param count the page count in the sequence
* @return the list of extensions
*/
public List getExtensions(int seq, int count) { public List getExtensions(int seq, int count) {
return null; return null;
} }


/**
* Get the end of document extensions for this stroe pages model.
* @return the list of end extensions
*/
public List getEndExtensions() { public List getEndExtensions() {
return extensions; return extensions;
} }


/**
* End document, do nothing.
*/
public void endDocument() { public void endDocument() {
} }
} }


// this uses the store pages model to store the pages
// each page is either rendered if ready or prepared
// for later rendering
/**
* This uses the store pages model to store the pages
* each page is either rendered if ready or prepared
* for later rendering.
* Once a page is rendered it is cleared to release the
* contents but the PageViewport is retained.
*/
public static class RenderPagesModel extends StorePagesModel { public static class RenderPagesModel extends StorePagesModel {
Renderer renderer;
ArrayList prepared = new ArrayList();
ArrayList pendingExt = new ArrayList();
ArrayList endDocExt = new ArrayList();

private Renderer renderer;
private ArrayList prepared = new ArrayList();
private ArrayList pendingExt = new ArrayList();
private ArrayList endDocExt = new ArrayList();

/**
* Create a new render pages model with the given renderer.
* @param rend the renderer to render pages to
*/
public RenderPagesModel(Renderer rend) { public RenderPagesModel(Renderer rend) {
renderer = rend; renderer = rend;
} }


/**
* Start a new page sequence.
* This tells the renderer that a new page sequence has
* started with the given title.
* @param title the title of the new page sequence
*/
public void startPageSequence(Title title) { public void startPageSequence(Title title) {
super.startPageSequence(title); super.startPageSequence(title);
renderer.startPageSequence(title); renderer.startPageSequence(title);
} }


/**
* Add a page to the render page model.
* If the page is finished it can be rendered immediately.
* If the page needs resolving then if the renderer supports
* out of order rendering it can prepare the page. Otherwise
* the page is added to a queue.
* @param page the page to add to the model
*/
public void addPage(PageViewport page) { public void addPage(PageViewport page) {
super.addPage(page); super.addPage(page);
// if page finished // if page finished
try { try {
renderer.renderPage(page); renderer.renderPage(page);
} catch(Exception e) {
} catch (Exception e) {
// use error handler to handle this FOP or IO Exception // use error handler to handle this FOP or IO Exception
} }
page.clear(); page.clear();
prepared.add(page); prepared.add(page);
} }


/**
* Add an extension to this model.
* If handle immediately then send directly to the renderer.
* The after page ones are handled after the next page is added.
* End of document extensions are added to a list to be
* handled at the end.
* @param ext the extension
* @param when when to render the extension
*/
public void addExtension(TreeExt ext, int when) { public void addExtension(TreeExt ext, int when) {
switch(when) { switch(when) {
case TreeExt.IMMEDIATELY: case TreeExt.IMMEDIATELY:
} }


private void renderExtensions(ArrayList list) { private void renderExtensions(ArrayList list) {
for(int count = 0; count < list.size(); count++) {
for (int count = 0; count < list.size(); count++) {
TreeExt ext = (TreeExt)list.get(count); TreeExt ext = (TreeExt)list.get(count);
renderer.renderExtension(ext); renderer.renderExtension(ext);
} }
} }


/**
* End the document. Render any end document extensions.
*/
public void endDocument() { public void endDocument() {
renderExtensions(endDocExt); renderExtensions(endDocExt);
} }

+ 9
- 3
src/org/apache/fop/area/Resolveable.java View File



package org.apache.fop.area; package org.apache.fop.area;


import java.util.ArrayList;
import java.util.List;
import java.io.Serializable;


public interface Resolveable {
/**
* Resolveable Interface.
* Classes that implement this can be resolved when
* an id is added to the area tree.
*/
public interface Resolveable extends Serializable {


public boolean isResolved(); public boolean isResolved();


* @param pages the list of pages with the id area * @param pages the list of pages with the id area
* may be null if not found * may be null if not found
*/ */
public void resolve(String id, ArrayList pages);
public void resolve(String id, List pages);
} }

+ 1
- 1
src/org/apache/fop/area/Trait.java View File

s_hmTraitInfo.put(ID_LINK, s_hmTraitInfo.put(ID_LINK,
new TraitInfo("id-link", String.class)); new TraitInfo("id-link", String.class));
s_hmTraitInfo.put(INTERNAL_LINK, s_hmTraitInfo.put(INTERNAL_LINK,
new TraitInfo("internal-link", String.class));
new TraitInfo("internal-link", PageViewport.class));
s_hmTraitInfo.put(EXTERNAL_LINK, s_hmTraitInfo.put(EXTERNAL_LINK,
new TraitInfo("external-link", String.class)); new TraitInfo("external-link", String.class));
s_hmTraitInfo.put(FONT_NAME, s_hmTraitInfo.put(FONT_NAME,

+ 1
- 10
src/org/apache/fop/area/inline/FilledArea.java View File

* this inline parent. * this inline parent.
*/ */
public class FilledArea extends InlineParent { public class FilledArea extends InlineParent {
MinOptMax alloc;
int unitWidth;
private int unitWidth;


public FilledArea() { public FilledArea() {
} }
unitWidth = w; unitWidth = w;
} }


public void setAllocationIPD(MinOptMax all) {
alloc = all;
}

public MinOptMax getAllocationIPD() {
return alloc;
}

public List getChildAreas() { public List getChildAreas() {
int units = (int)(getWidth() / unitWidth); int units = (int)(getWidth() / unitWidth);
ArrayList newList = new ArrayList(); ArrayList newList = new ArrayList();

+ 7
- 4
src/org/apache/fop/area/inline/InlineArea.java View File

/* /*
* $Id$ * $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* Copyright (C) 2002 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the * For details on use and redistribution please refer to the
* LICENSE file included with these sources. * LICENSE file included with these sources.
*/ */
import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.BorderProps;
import org.apache.fop.fo.properties.VerticalAlign; import org.apache.fop.fo.properties.VerticalAlign;


import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;


/** /**
int height; int height;
protected int contentIPD = 0; protected int contentIPD = 0;


// position within the line area, either top or baseline
int verticalPosition = VerticalAlign.BASELINE;
// offset position from top of parent area
int verticalPosition = 0;


// store properties in array list, need better solution // store properties in array list, need better solution
ArrayList props = null; ArrayList props = null;
this.contentIPD = ipd; this.contentIPD = ipd;
} }


public int getIPD() {
return this.contentIPD;
}

public void increaseIPD(int ipd) { public void increaseIPD(int ipd) {
this.contentIPD += ipd; this.contentIPD += ipd;
} }

+ 8
- 2
src/org/apache/fop/area/inline/InlineParent.java View File

import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;


// this is an inline area that can have other inlines as children
/**
* Inline parent area.
* This is an inline area that can have other inlines as children.
*/
public class InlineParent extends InlineArea { public class InlineParent extends InlineArea {
protected ArrayList inlines = new ArrayList(); protected ArrayList inlines = new ArrayList();


public InlineParent() { public InlineParent() {
} }


/**
* Render this area.
* @param renderer the renderer to render this area in
*/
public void render(Renderer renderer) { public void render(Renderer renderer) {
renderer.renderInlineParent(this); renderer.renderInlineParent(this);
} }



/** /**
* Override generic Area method. * Override generic Area method.
*/ */

+ 16
- 7
src/org/apache/fop/area/inline/UnresolvedPageNumber.java View File



import org.apache.fop.area.PageViewport; import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Resolveable; import org.apache.fop.area.Resolveable;
import org.apache.fop.area.Trait;


import java.util.ArrayList;
import java.util.List;


public class UnresolvedPageNumber extends Word implements Resolveable { public class UnresolvedPageNumber extends Word implements Resolveable {
boolean resolved = false;
String pageRefId;
private boolean resolved = false;
private String pageRefId;


public UnresolvedPageNumber(String id) { public UnresolvedPageNumber(String id) {
pageRefId = id; pageRefId = id;
return new String[] {pageRefId}; return new String[] {pageRefId};
} }


public void resolve(String id, ArrayList pages) {
public void resolve(String id, List pages) {
resolved = true; resolved = true;
PageViewport page = (PageViewport)pages.get(0);
String str = page.getPageNumber();
word = str;
if(pages != null) {
PageViewport page = (PageViewport)pages.get(0);
String str = page.getPageNumber();
word = str;

// update ipd
String name = (String) getTrait(Trait.FONT_NAME);
int size = ((Integer) getTrait(Trait.FONT_SIZE)).intValue();
//FontMetric metrics = fontInfo.getMetricsFor(name);
//FontState fs = new FontState(name, metrics, size);
}
} }


public boolean isResolved() { public boolean isResolved() {

+ 1
- 1
src/org/apache/fop/extensions/BookmarkData.java View File

return (String[])idRefs.keySet().toArray(new String[] {}); return (String[])idRefs.keySet().toArray(new String[] {});
} }


public void resolve(String id, ArrayList pages) {
public void resolve(String id, List pages) {
if(!id.equals(idRef)) { if(!id.equals(idRef)) {
BookmarkData bd = (BookmarkData)idRefs.get(id); BookmarkData bd = (BookmarkData)idRefs.get(id);
idRefs.remove(id); idRefs.remove(id);

+ 85
- 8
src/org/apache/fop/fo/flow/BasicLink.java View File

import org.apache.fop.fo.properties.*; import org.apache.fop.fo.properties.*;
import org.apache.fop.layout.*; import org.apache.fop.layout.*;
import org.apache.fop.datatypes.ColorType; import org.apache.fop.datatypes.ColorType;
import org.apache.fop.area.inline.InlineParent;
import org.apache.fop.area.Trait;
import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.Area;
import org.apache.fop.layoutmgr.InlineStackingLayoutManager;
import org.apache.fop.layoutmgr.LMiter;
import org.apache.fop.layoutmgr.LayoutManager;


// Java // Java
import java.util.Enumeration; import java.util.Enumeration;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.util.List; import java.util.List;
import java.util.ArrayList;


public class BasicLink extends Inline { public class BasicLink extends Inline {
String link = null;
boolean external = false;


public BasicLink(FONode parent) { public BasicLink(FONode parent) {
super(parent); super(parent);


// add start and end properties for the link // add start and end properties for the link
public void addLayoutManager(List lms) { public void addLayoutManager(List lms) {
super.addLayoutManager(lms);
setup();
lms.add(new InlineStackingLayoutManager(this,
new LMiter(children.listIterator())) {
protected InlineParent createArea() {
InlineParent area = super.createArea();
setupLinkArea(parentLM, area);
return area;
}
});
}

protected void setupLinkArea(LayoutManager parentLM, InlineParent area) {
if(link == null) {
return;
}
if(external) {
area.addTrait(Trait.EXTERNAL_LINK, link);
} else {
PageViewport page = parentLM.resolveRefID(link);
if(page != null) {
area.addTrait(Trait.INTERNAL_LINK, page);
} else {
LinkResolver res = new LinkResolver(link, area);
parentLM.addUnresolvedArea(link, res);
}
}
} }


public void setup() { public void setup() {
// this.properties.get("baseline-shift"); // this.properties.get("baseline-shift");
// this.properties.get("destination-place-offset"); // this.properties.get("destination-place-offset");
// this.properties.get("dominant-baseline"); // this.properties.get("dominant-baseline");
// this.properties.get("external-destination");
String ext = properties.get("external-destination").getString();
setupID(); setupID();
// this.properties.get("indicate-destination");
// this.properties.get("internal-destination");
// this.properties.get("indicate-destination");
String internal = properties.get("internal-destination").getString();
if(ext.length() > 0) {
link = ext;
external = true;
} else if(internal.length() > 0) {
link = internal;
} else {
getLogger().error("basic-link requires an internal or external destination");
}
// this.properties.get("keep-together"); // this.properties.get("keep-together");
// this.properties.get("keep-with-next"); // this.properties.get("keep-with-next");
// this.properties.get("keep-with-previous"); // this.properties.get("keep-with-previous");
// this.properties.get("line-height"); // this.properties.get("line-height");
// this.properties.get("line-height-shift-adjustment"); // this.properties.get("line-height-shift-adjustment");
// this.properties.get("show-destination");
// this.properties.get("target-processing-context");
// this.properties.get("target-presentation-context");
// this.properties.get("target-stylesheet");
// this.properties.get("show-destination");
// this.properties.get("target-processing-context");
// this.properties.get("target-presentation-context");
// this.properties.get("target-stylesheet");

}

protected static class LinkResolver implements Resolveable {
private boolean resolved = false;
private String idRef;
// NOTE: there will be a problem with serialization
private Area area;

public LinkResolver(String id, Area a) {
idRef = id;
area = a;
}

public boolean isResolved() {
return resolved;
}

public String[] getIDs() {
return new String[] {idRef};
}

/**
* Resolve by removing the id link and replacing with
* an internal link.
*/
public void resolve(String id, List pages) {
if(idRef.equals(id) && pages != null) {
PageViewport page = (PageViewport)pages.get(0);
area.addTrait(Trait.INTERNAL_LINK, page);
}
}


} }


} }


+ 8
- 14
src/org/apache/fop/fo/flow/Leader.java View File

public void addLayoutManager(List list) { public void addLayoutManager(List list) {
LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this) { LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this) {
public InlineArea get(LayoutContext context) { public InlineArea get(LayoutContext context) {
int refIPD = context.getRefIPD();
return getInlineArea(refIPD);
return getInlineArea();
}

protected MinOptMax getAllocationIPD(int refIPD) {
return getAllocIPD(refIPD);
} }
}; };
lm.setAlignment(properties.get("leader-alignment").getEnum()); lm.setAlignment(properties.get("leader-alignment").getEnum());
list.add(lm); list.add(lm);
} }


protected InlineArea getInlineArea(int refIPD) {
protected InlineArea getInlineArea() {
if(leaderArea == null) { if(leaderArea == null) {
createLeaderArea(); createLeaderArea();
} }
MinOptMax alloc = getAllocationIPD(refIPD);
if(leaderArea instanceof Stretch) {
((Stretch)leaderArea).setAllocationIPD(alloc);
} else if(leaderArea instanceof FilledArea) {
((FilledArea)leaderArea).setAllocationIPD(alloc);
}
leaderArea.setWidth(alloc.opt);
return leaderArea; return leaderArea;
} }




leaderArea = leader; leaderArea = leader;
} else if (leaderPattern == LeaderPattern.SPACE) { } else if (leaderPattern == LeaderPattern.SPACE) {
Space space = new Space();

leaderArea = space;
leaderArea = new Space();
} else if(leaderPattern == LeaderPattern.DOTS) { } else if(leaderPattern == LeaderPattern.DOTS) {
Word w = new Word(); Word w = new Word();
char dot = '.'; // userAgent.getLeaderDotChar(); char dot = '.'; // userAgent.getLeaderDotChar();


} }


protected MinOptMax getAllocationIPD(int ipd) {
protected MinOptMax getAllocIPD(int ipd) {
// length of the leader // length of the leader
int opt = getLength("leader-length.optimum", ipd); int opt = getLength("leader-length.optimum", ipd);
int min = getLength("leader-length.minimum", ipd); int min = getLength("leader-length.minimum", ipd);

+ 35
- 32
src/org/apache/fop/fo/flow/PageNumberCitation.java View File

import org.apache.fop.apps.FOPException; import org.apache.fop.apps.FOPException;
import org.apache.fop.layoutmgr.LeafNodeLayoutManager; import org.apache.fop.layoutmgr.LeafNodeLayoutManager;
import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.PageViewport;
import org.apache.fop.util.CharUtilities; import org.apache.fop.util.CharUtilities;
import org.apache.fop.apps.StructureHandler; import org.apache.fop.apps.StructureHandler;
import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutContext;
} }


public void addAreas(PositionIterator posIter, public void addAreas(PositionIterator posIter,
LayoutContext context) {
LayoutContext context) {
super.addAreas(posIter, context); super.addAreas(posIter, context);
if(unresolved) {
parentLM.addUnresolvedArea(refId, (Resolveable)inline);
if (unresolved) {
parentLM.addUnresolvedArea(refId,
(Resolveable) inline);
} }
} }
} }
); );
} }


// is id can be resolved then simply return a word, otherwise
// if id can be resolved then simply return a word, otherwise
// return a resolveable area // return a resolveable area
private InlineArea getInlineArea(LayoutManager parentLM) { private InlineArea getInlineArea(LayoutManager parentLM) {
if (refId.equals("")) { if (refId.equals("")) {
getLogger().error("page-number-citation must contain \"ref-id\""); getLogger().error("page-number-citation must contain \"ref-id\"");
return null; return null;
} }
String str = parentLM.resolveRefID(refId);
if(str != null) {
// get page string from parent, build area
Word word = new Word();
inline = word;
int width = getStringWidth(str);
word.setWord(str);
inline.setIPD(width);
inline.setHeight(fontState.getAscender() -
fontState.getDescender());
inline.setOffset(fontState.getAscender());

inline.addTrait(Trait.FONT_NAME, fontState.getFontName());
inline.addTrait(Trait.FONT_SIZE,
new Integer(fontState.getFontSize()));
PageViewport page = parentLM.resolveRefID(refId);
if (page != null) {
String str = page.getPageNumber();
// get page string from parent, build area
Word word = new Word();
inline = word;
int width = getStringWidth(str);
word.setWord(str);
inline.setIPD(width);
inline.setHeight(fontState.getAscender() -
fontState.getDescender());
inline.setOffset(fontState.getAscender());

inline.addTrait(Trait.FONT_NAME, fontState.getFontName());
inline.addTrait(Trait.FONT_SIZE,
new Integer(fontState.getFontSize()));
unresolved = false;
} else { } else {
unresolved = true;
inline = new UnresolvedPageNumber(refId);
str = "MMM"; // reserve three spaces for page number
int width = getStringWidth(str);
inline.setIPD(width);
inline.setHeight(fontState.getAscender() -
fontState.getDescender());
inline.setOffset(fontState.getAscender());

inline.addTrait(Trait.FONT_NAME, fontState.getFontName());
inline.addTrait(Trait.FONT_SIZE,
new Integer(fontState.getFontSize()));

unresolved = true;
inline = new UnresolvedPageNumber(refId);
String str = "MMM"; // reserve three spaces for page number
int width = getStringWidth(str);
inline.setIPD(width);
inline.setHeight(fontState.getAscender() -
fontState.getDescender());
inline.setOffset(fontState.getAscender());

inline.addTrait(Trait.FONT_NAME, fontState.getFontName());
inline.addTrait(Trait.FONT_SIZE,
new Integer(fontState.getFontSize()));
} }
return inline; return inline;
} }

+ 2
- 1
src/org/apache/fop/layoutmgr/AbstractLayoutManager.java View File

import org.apache.fop.fo.FONode; import org.apache.fop.fo.FONode;
import org.apache.fop.area.Area; import org.apache.fop.area.Area;
import org.apache.fop.area.Resolveable; import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.PropertyManager; import org.apache.fop.fo.PropertyManager;


import java.util.ListIterator; import java.util.ListIterator;
return parentLM.getCurrentPageNumber(); return parentLM.getCurrentPageNumber();
} }


public String resolveRefID(String ref) {
public PageViewport resolveRefID(String ref) {
return parentLM.resolveRefID(ref); return parentLM.resolveRefID(ref);
} }



+ 8
- 3
src/org/apache/fop/layoutmgr/ContentLayoutManager.java View File

import org.apache.fop.area.Area; import org.apache.fop.area.Area;
import org.apache.fop.area.MinOptMax; import org.apache.fop.area.MinOptMax;
import org.apache.fop.area.Resolveable; import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;


import java.util.ArrayList; import java.util.ArrayList;


public class ContentLayoutManager implements LayoutManager { public class ContentLayoutManager implements LayoutManager {
Area holder; Area holder;
int stackSize; int stackSize;
LayoutManager parentLM;


public ContentLayoutManager(Area area) { public ContentLayoutManager(Area area) {
holder = area; holder = area;
} }


public void setParentLM(LayoutManager lm) { public void setParentLM(LayoutManager lm) {
parentLM = lm;
} }


public boolean canBreakBefore(LayoutContext lc) { public boolean canBreakBefore(LayoutContext lc) {
} }


public String getCurrentPageNumber() { public String getCurrentPageNumber() {
return "";
return parentLM.getCurrentPageNumber();
} }


public String resolveRefID(String ref) {
return null;
public PageViewport resolveRefID(String ref) {
return parentLM.resolveRefID(ref);;
} }


public void addIDToPage(String id) { public void addIDToPage(String id) {
parentLM.addIDToPage(id);
} }


public void addUnresolvedArea(String id, Resolveable res) { public void addUnresolvedArea(String id, Resolveable res) {
parentLM.addUnresolvedArea(id, res);
} }
} }



+ 6
- 0
src/org/apache/fop/layoutmgr/FlowLayoutManager.java View File

MinOptMax stackSize = new MinOptMax(); MinOptMax stackSize = new MinOptMax();


while ((curLM = getChildLM()) != null) { while ((curLM = getChildLM()) != null) {
if(curLM.generatesInlineAreas()) {
// problem
curLM.setFinished(true);
continue;
}

// Make break positions and return page break // Make break positions and return page break
// Set up a LayoutContext // Set up a LayoutContext
MinOptMax bpd = context.getStackLimit(); MinOptMax bpd = context.getStackLimit();

+ 8
- 1
src/org/apache/fop/layoutmgr/InlineStackingLayoutManager.java View File

} }
*****/ *****/


protected InlineParent createArea() {
return new InlineParent();
}

/** /**
* Generate and add areas to parent area. * Generate and add areas to parent area.
* Set size of each area. * Set size of each area.
*/ */
public void addAreas(PositionIterator parentIter, public void addAreas(PositionIterator parentIter,
LayoutContext context) { LayoutContext context) {
setCurrentArea(new InlineParent());
InlineParent parent = createArea();
parent.setHeight(context.getLineHeight());
parent.setOffset(0);
setCurrentArea(parent);


setChildContext(new LayoutContext(context)); // Store current value setChildContext(new LayoutContext(context)); // Store current value



+ 2
- 1
src/org/apache/fop/layoutmgr/LayoutManager.java View File



import org.apache.fop.area.Area; import org.apache.fop.area.Area;
import org.apache.fop.area.Resolveable; import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;


/** /**
* The interface for all LayoutManagers. * The interface for all LayoutManagers.


public String getCurrentPageNumber(); public String getCurrentPageNumber();


public String resolveRefID(String ref);
public PageViewport resolveRefID(String ref);


public void addIDToPage(String id); public void addIDToPage(String id);



+ 18
- 6
src/org/apache/fop/layoutmgr/LeafNodeLayoutManager.java View File

private InlineArea curArea = null; private InlineArea curArea = null;
private int alignment; private int alignment;
private int lead; private int lead;
private MinOptMax ipd;


public LeafNodeLayoutManager(FObj fobj) { public LeafNodeLayoutManager(FObj fobj) {
super(fobj); super(fobj);
BreakPoss.CAN_BREAK_AFTER | BreakPoss.CAN_BREAK_AFTER |
BreakPoss.CAN_BREAK_BEFORE | BreakPoss.ISFIRST | BreakPoss.CAN_BREAK_BEFORE | BreakPoss.ISFIRST |
BreakPoss.ISLAST); BreakPoss.ISLAST);
bp.setStackingSize(curArea.getAllocationIPD());
ipd = getAllocationIPD(context.getRefIPD());
bp.setStackingSize(ipd);
bp.setNonStackingSize(curArea.getAllocationBPD()); bp.setNonStackingSize(curArea.getAllocationBPD());
bp.setTrailingSpace(new SpaceSpecifier(false)); bp.setTrailingSpace(new SpaceSpecifier(false));


return bp; return bp;
} }


protected MinOptMax getAllocationIPD(int refIPD) {
return new MinOptMax(curArea.getIPD());
}

public void resetPosition(Position resetPos) { public void resetPosition(Position resetPos) {
// only reset if setting null, start again // only reset if setting null, start again
if(resetPos == null) { if(resetPos == null) {


addID(); addID();


offsetArea(context);
widthAdjustArea(context);

while (posIter.hasNext()) {
posIter.next();
}
}

protected void offsetArea(LayoutContext context) {
int bpd = curArea.getHeight(); int bpd = curArea.getHeight();
switch(alignment) { switch(alignment) {
case VerticalAlign.MIDDLE: case VerticalAlign.MIDDLE:
curArea.setOffset(context.getBaseline() - bpd); curArea.setOffset(context.getBaseline() - bpd);
break; break;
} }
}


protected void widthAdjustArea(LayoutContext context) {
double dAdjust = context.getIPDAdjust(); double dAdjust = context.getIPDAdjust();
MinOptMax ipd = curArea.getAllocationIPD();
int width = ipd.opt; int width = ipd.opt;
if(dAdjust < 0) { if(dAdjust < 0) {
width = (int)(width + dAdjust * (ipd.opt - ipd.min)); width = (int)(width + dAdjust * (ipd.opt - ipd.min));
width = (int)(width + dAdjust * (ipd.max - ipd.opt)); width = (int)(width + dAdjust * (ipd.max - ipd.opt));
} }
curArea.setWidth(width); curArea.setWidth(width);

while (posIter.hasNext()) {
posIter.next();
}
} }


public boolean canBreakBefore(LayoutContext context) { public boolean canBreakBefore(LayoutContext context) {

+ 6
- 1
src/org/apache/fop/layoutmgr/PageLayoutManager.java View File

return "" + pageCount; return "" + pageCount;
} }


public String resolveRefID(String ref) {
public PageViewport resolveRefID(String ref) {
List list = areaTree.getIDReferences(ref);
if(list != null && list.size() > 0) {
return (PageViewport)list.get(0);
}
return null; return null;
} }




public void addUnresolvedArea(String id, Resolveable res) { public void addUnresolvedArea(String id, Resolveable res) {
// add unresolved to tree // add unresolved to tree
// should really add to the page viewport so it can serialize
areaTree.addUnresolvedID(id, res); areaTree.addUnresolvedID(id, res);
} }



+ 3
- 3
src/org/apache/fop/pdf/PDFDocument.java View File

import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;


/** /**
* class representing a PDF document. * class representing a PDF document.
* @param linkType the link type * @param linkType the link type
* @return the PDFLink object created * @return the PDFLink object created
*/ */
public PDFLink makeLink(Rectangle rect, String destination,
public PDFLink makeLink(Rectangle2D rect, String destination,
int linkType) { int linkType) {


PDFLink linkObject; PDFLink linkObject;
this.trailerObjects.add(object); this.trailerObjects.add(object);
} }


public PDFLink makeLink(Rectangle rect, String page, String dest) {
public PDFLink makeLink(Rectangle2D rect, String page, String dest) {
PDFLink link = new PDFLink(++this.objectcount, rect); PDFLink link = new PDFLink(++this.objectcount, rect);
this.objects.add(link); this.objects.add(link);



+ 6
- 6
src/org/apache/fop/pdf/PDFLink.java View File

package org.apache.fop.pdf; package org.apache.fop.pdf;


// Java // Java
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;


/** /**
* class representing an /Annot object of /Subtype /Link * class representing an /Annot object of /Subtype /Link
* @param number the object's number * @param number the object's number
* @param producer the application producing the PDF * @param producer the application producing the PDF
*/ */
public PDFLink(int number, Rectangle r) {
public PDFLink(int number, Rectangle2D r) {
/* generic creation of PDF object */ /* generic creation of PDF object */
super(number); super(number);


this.ulx = r.x;
this.uly = r.y;
this.brx = r.x + r.width;
this.bry = r.y - r.height;
this.ulx = (float)r.getX();
this.uly = (float)r.getY();
this.brx = (float)(r.getX() + r.getWidth());
this.bry = (float)(r.getY() - r.getHeight());
this.color = "0 0 0"; // just for now this.color = "0 0 0"; // just for now


} }

+ 89
- 29
src/org/apache/fop/render/pdf/PDFRenderer.java View File

/* /*
* $Id$ * $Id$
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
* Copyright (C) 2001-2002 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the * For details on use and redistribution please refer to the
* LICENSE file included with these sources. * LICENSE file included with these sources.
*/ */
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;


public void renderExtension(TreeExt ext) { public void renderExtension(TreeExt ext) {
// render bookmark extension // render bookmark extension
if(ext instanceof BookmarkData) {
if (ext instanceof BookmarkData) {
renderRootExtensions((BookmarkData)ext); renderRootExtensions((BookmarkData)ext);
} }
} }
} }


public void startPageSequence(Title seqTitle) { public void startPageSequence(Title seqTitle) {
if(seqTitle != null) {
if (seqTitle != null) {
String str = convertTitleToString(seqTitle); String str = convertTitleToString(seqTitle);
PDFInfo info = this.pdfDoc.getInfo(); PDFInfo info = this.pdfDoc.getInfo();
info.setTitle(str); info.setTitle(str);


currentStream.add("ET\n"); currentStream.add("ET\n");


if(bv.getClip()) {
if (bv.getClip()) {
Rectangle2D rect = bv.getBounds(); Rectangle2D rect = bv.getBounds();


currentStream.add("q\n"); currentStream.add("q\n");


Rectangle2D rect = bv.getBounds(); Rectangle2D rect = bv.getBounds();


if(ctm != null) {
if (ctm != null) {
currentIPPosition = 0; currentIPPosition = 0;
currentBPPosition = 0; currentBPPosition = 0;




double[] vals = ctm.toArray(); double[] vals = ctm.toArray();
boolean aclock = vals[2] == 1.0; boolean aclock = vals[2] == 1.0;
if(vals[2] == 1.0) {
if (vals[2] == 1.0) {
ctm = ctm.translate(-saveBP - rect.getHeight(), -saveIP); ctm = ctm.translate(-saveBP - rect.getHeight(), -saveIP);
} else if(vals[0] == -1.0) {
} else if (vals[0] == -1.0) {
ctm = ctm.translate(-saveIP - rect.getWidth(), -saveBP - rect.getHeight()); ctm = ctm.translate(-saveIP - rect.getWidth(), -saveBP - rect.getHeight());
} else { } else {
ctm = ctm.translate(saveBP, saveIP - rect.getWidth()); ctm = ctm.translate(saveBP, saveIP - rect.getWidth());
} }
} }


if(bv.getClip()) {
if (bv.getClip()) {
currentStream.add("q\n"); currentStream.add("q\n");
float x = (float)rect.getX() / 1000f; float x = (float)rect.getX() / 1000f;
float y = (float)rect.getY() / 1000f; float y = (float)rect.getY() / 1000f;
clip(x, y, width, height); clip(x, y, width, height);
} }


if(ctm != null) {
if (ctm != null) {
startVParea(ctm); startVParea(ctm);
} }
renderBlocks(children); renderBlocks(children);
if(ctm != null) {
if (ctm != null) {
endVParea(); endVParea();
} }
if (bv.getClip()) { if (bv.getClip()) {
currentStream.add("Q\n"); currentStream.add("Q\n");
} }
if(ctm != null) {
if (ctm != null) {
currentStream.add("BT\n"); currentStream.add("BT\n");
} }


// clip if necessary // clip if necessary


if(rect != null) {
if (rect != null) {
currentIPPosition = saveIP; currentIPPosition = saveIP;
currentBPPosition = saveBP; currentBPPosition = saveBP;
currentBPPosition += (int)(rect.getHeight()); currentBPPosition += (int)(rect.getHeight());
} }
} }


/**
* Clip an area.
* write a clipping operation given coordinates in the current
* transform.
* @param x the x coordinate
* @param y the y coordinate
* @param width the width of the area
* @param height the height of the area
*/
protected void clip(float x, float y, float width, float height) { protected void clip(float x, float y, float width, float height) {
currentStream.add(x + " " + y + " m\n"); currentStream.add(x + " " + y + " m\n");
currentStream.add((x + width) + " " + y + " l\n"); currentStream.add((x + width) + " " + y + " l\n");
closeText(); closeText();
} }


/**
* Render inline parent area.
* For pdf this handles the inline parent area traits such as
* links, border, background.
* @param ip the inline parent area
*/
public void renderInlineParent(InlineParent ip) {
Object tr = ip.getTrait(Trait.INTERNAL_LINK);
boolean internal = false;
String dest = null;
if (tr == null) {
dest = (String)ip.getTrait(Trait.EXTERNAL_LINK);
} else {
PageViewport pv = (PageViewport)tr;
dest = (String)pageReferences.get(pv);
internal = true;
}
if (dest != null) {
float start = currentBlockIPPosition;
float top = (ip.getOffset() + currentBPPosition) / 1000f;
float height = ip.getHeight() / 1000f;
super.renderInlineParent(ip);
float width = (currentBlockIPPosition - start) / 1000f;
start = start / 1000f;
// add link to pdf document
Rectangle2D rect = new Rectangle2D.Float(start, top, width, height);
// transform rect to absolute coords
AffineTransform transform = currentState.getTransform();
rect = transform.createTransformedShape(rect).getBounds();
rect = new Rectangle2D.Double(rect.getX(), rect.getY() + rect.getHeight(), rect.getWidth(), rect.getHeight());

int type = internal ? PDFLink.INTERNAL : PDFLink.EXTERNAL;
PDFLink pdflink = pdfDoc.makeLink(rect, dest, type);
currentPage.addAnnotation(pdflink);
} else {
super.renderInlineParent(ip);
}
}

public void renderCharacter(Character ch) { public void renderCharacter(Character ch) {


super.renderCharacter(ch); super.renderCharacter(ch);
if (!textOpen || bl != prevWordY) { if (!textOpen || bl != prevWordY) {
closeText(); closeText();


pdf.append("1 0 0 -1 " + (rx / 1000f) + " " +
(bl / 1000f) + " Tm [" + startText);
pdf.append("1 0 0 -1 " + (rx / 1000f) + " "
+ (bl / 1000f) + " Tm [" + startText);
prevWordY = bl; prevWordY = bl;
textOpen = true; textOpen = true;
} else { } else {
if (emDiff < -33000) { if (emDiff < -33000) {
closeText(); closeText();


pdf.append("1 0 0 1 " + (rx / 1000f) + " " +
(bl / 1000f) + " Tm [" + startText);
pdf.append("1 0 0 1 " + (rx / 1000f) + " "
+ (bl / 1000f) + " Tm [" + startText);
textOpen = true; textOpen = true;
} else { } else {
pdf.append(Float.toString(emDiff)); pdf.append(Float.toString(emDiff));
(int) uniBytes[i]; (int) uniBytes[i];


String hexString = Integer.toHexString(b); String hexString = Integer.toHexString(b);
if (hexString.length() == 1)
if (hexString.length() == 1) {
buf = buf.append("0" + hexString); buf = buf.append("0" + hexString);
else
} else {
buf = buf.append(hexString); buf = buf.append(hexString);
}
} }
return buf.toString(); return buf.toString();
} }
} }


private void updateFont(String name, int size, StringBuffer pdf) { private void updateFont(String name, int size, StringBuffer pdf) {
if ((!name.equals(this.currentFontName)) ||
(size != this.currentFontSize)) {
if ((!name.equals(this.currentFontName))
|| (size != this.currentFontSize)) {
closeText(); closeText();


this.currentFontName = name; this.currentFontName = name;
try { try {
this.pdfDoc.output(ostream); this.pdfDoc.output(ostream);
} catch (IOException ioe) { } catch (IOException ioe) {
// ioexception will be caught later
} }
} }


protected void placeImage(int x, int y, int w, int h, int xobj) { protected void placeImage(int x, int y, int w, int h, int xobj) {
currentStream.add("q\n" + ((float) w) + " 0 0 " +
((float) - h) + " " +
(((float) currentBlockIPPosition) / 1000f + x) + " " +
(((float)(currentBPPosition + 1000 * h)) / 1000f +
y) + " cm\n" + "/Im" + xobj + " Do\nQ\n");
currentStream.add("q\n" + ((float) w) + " 0 0 "
+ ((float) - h) + " "
+ (((float) currentBlockIPPosition) / 1000f + x) + " "
+ (((float)(currentBPPosition + 1000 * h)) / 1000f
+ y) + " cm\n" + "/Im" + xobj + " Do\nQ\n");


} }




} }


/**
* Render an inline viewport.
* This renders an inline viewport by clipping if necessary.
* @param viewport the viewport to handle
*/
public void renderViewport(Viewport viewport) { public void renderViewport(Viewport viewport) {
closeText(); closeText();
currentStream.add("ET\n"); currentStream.add("ET\n");
currentStream.add("BT\n"); currentStream.add("BT\n");
} }


/**
* Render leader area.
* This renders a leader area which is an area with a rule.
* @param area the leader area to render
*/
public void renderLeader(Leader area) { public void renderLeader(Leader area) {
closeText(); closeText();
currentStream.add("ET\n"); currentStream.add("ET\n");
float startx = ((float) currentBlockIPPosition) / 1000f; float startx = ((float) currentBlockIPPosition) / 1000f;
float starty = ((currentBPPosition + area.getOffset()) / 1000f); float starty = ((currentBPPosition + area.getOffset()) / 1000f);
float endx = (currentBlockIPPosition + area.getWidth()) / 1000f; float endx = (currentBlockIPPosition + area.getWidth()) / 1000f;
if(!alt) {
if (!alt) {
currentStream.add(area.getRuleThickness() / 1000f + " w\n"); currentStream.add(area.getRuleThickness() / 1000f + " w\n");


currentStream.add(startx + " " + starty + " m\n"); currentStream.add(startx + " " + starty + " m\n");
currentStream.add(endx + " " + starty + " l\n"); currentStream.add(endx + " " + starty + " l\n");
currentStream.add("S\n"); currentStream.add("S\n");
} else { } else {
if(style == RuleStyle.DOUBLE) {
if (style == RuleStyle.DOUBLE) {
float third = area.getRuleThickness() / 3000f; float third = area.getRuleThickness() / 3000f;
currentStream.add(third + " w\n"); currentStream.add(third + " w\n");
currentStream.add(startx + " " + starty + " m\n"); currentStream.add(startx + " " + starty + " m\n");
currentStream.add(startx + " " + (starty + 2 * half) + " l\n"); currentStream.add(startx + " " + (starty + 2 * half) + " l\n");
currentStream.add("h\n"); currentStream.add("h\n");
currentStream.add("f\n"); currentStream.add("f\n");
if(style == RuleStyle.GROOVE) {
if (style == RuleStyle.GROOVE) {
currentStream.add("0 g\n"); currentStream.add("0 g\n");
currentStream.add(startx + " " + starty + " m\n"); currentStream.add(startx + " " + starty + " m\n");
currentStream.add(endx + " " + starty + " l\n"); currentStream.add(endx + " " + starty + " l\n");

Loading…
Cancel
Save