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

@@ -1,6 +1,6 @@
/*
* $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
* LICENSE file included with these sources.
*/
@@ -34,45 +34,74 @@ import java.util.Iterator;
public class AreaTree {
// allows for different models to deal with adding/rendering
// in different situations
AreaTreeModel model;
private AreaTreeModel model;

// 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
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) {
return new RenderPagesModel(rend);
}

/**
* Create a new store pages model.
* @return StorePagesModel the new model
*/
public static StorePagesModel createStorePagesModel() {
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) {
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) {
model.startPageSequence(title);
}

/**
* Add a new page to the area tree.
* @param page the page to add
*/
public void addPage(PageViewport 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) {
ArrayList list = (ArrayList)idLocations.get(id);
if(list == null) {
List list = (List)idLocations.get(id);
if (list == null) {
list = new ArrayList();
idLocations.put(id, list);
}
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);
res.resolve(id, list);
}
@@ -80,47 +109,80 @@ public class AreaTree {
}
}

/**
* 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) {
ArrayList todo = (ArrayList)resolve.get(id);
if(todo == null) {
if (todo == null) {
todo = new ArrayList();
resolve.put(id, todo);
}
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) {
treeExtensions.add(ext);
if(ext.isResolveable()) {
if (ext.isResolveable()) {
Resolveable res = (Resolveable)ext;
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]));
} else {
ArrayList todo = (ArrayList)resolve.get(ids[count]);
if(todo == null) {
if (todo == null) {
todo = new ArrayList();
resolve.put(ids[count], todo);
}
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) {
// queue tree extension according to the 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() {
for(Iterator iter = resolve.keySet().iterator(); iter.hasNext(); ) {
for (Iterator iter = resolve.keySet().iterator(); iter.hasNext();) {
String id = (String)iter.next();
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);
if(!res.isResolved()) {
if (!res.isResolved()) {
res.resolve(id, null);
}
}
@@ -128,24 +190,59 @@ public class AreaTree {
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);

/**
* Add a page to this moel.
* @param page the page to add to the model.
*/
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);

/**
* Signal the end of the document for any processing.
*/
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 {
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) {
titles.add(title);
if (pageSequence == null) {
@@ -155,28 +252,59 @@ public class AreaTree {
pageSequence.add(currSequence);
}

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

/**
* Get the page sequence count.
* @return the number of page sequences in the document.
*/
public int getPageSequenceCount() {
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) {
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) {
ArrayList sequence = (ArrayList) pageSequence.get(seq);
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) {
ArrayList sequence = (ArrayList) pageSequence.get(seq);
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) {
int seq, page;
switch(when) {
@@ -192,42 +320,78 @@ public class AreaTree {
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) {
return null;
}

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

/**
* End document, do nothing.
*/
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 {
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) {
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) {
super.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) {
super.addPage(page);
// if page finished
try {
renderer.renderPage(page);
} catch(Exception e) {
} catch (Exception e) {
// use error handler to handle this FOP or IO Exception
}
page.clear();
@@ -240,6 +404,15 @@ public class AreaTree {
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) {
switch(when) {
case TreeExt.IMMEDIATELY:
@@ -255,12 +428,15 @@ public class AreaTree {
}

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);
renderer.renderExtension(ext);
}
}

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

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

@@ -7,9 +7,15 @@

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();

@@ -22,5 +28,5 @@ public interface Resolveable {
* @param pages the list of pages with the id area
* 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

@@ -57,7 +57,7 @@ public class Trait implements Serializable {
s_hmTraitInfo.put(ID_LINK,
new TraitInfo("id-link", String.class));
s_hmTraitInfo.put(INTERNAL_LINK,
new TraitInfo("internal-link", String.class));
new TraitInfo("internal-link", PageViewport.class));
s_hmTraitInfo.put(EXTERNAL_LINK,
new TraitInfo("external-link", String.class));
s_hmTraitInfo.put(FONT_NAME,

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

@@ -20,8 +20,7 @@ import java.util.ArrayList;
* this inline parent.
*/
public class FilledArea extends InlineParent {
MinOptMax alloc;
int unitWidth;
private int unitWidth;

public FilledArea() {
}
@@ -30,14 +29,6 @@ public class FilledArea extends InlineParent {
unitWidth = w;
}

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

public MinOptMax getAllocationIPD() {
return alloc;
}

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

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

@@ -1,6 +1,6 @@
/*
* $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
* LICENSE file included with these sources.
*/
@@ -14,7 +14,6 @@ import org.apache.fop.render.Renderer;
import org.apache.fop.traits.BorderProps;
import org.apache.fop.fo.properties.VerticalAlign;

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

/**
@@ -29,8 +28,8 @@ public class InlineArea extends Area {
int height;
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
ArrayList props = null;
@@ -53,6 +52,10 @@ public class InlineArea extends Area {
this.contentIPD = ipd;
}

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

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

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

@@ -14,18 +14,24 @@ import org.apache.fop.render.Renderer;
import java.util.List;
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 {
protected ArrayList inlines = new ArrayList();

public InlineParent() {
}

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


/**
* Override generic Area method.
*/

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

@@ -9,12 +9,13 @@ package org.apache.fop.area.inline;

import org.apache.fop.area.PageViewport;
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 {
boolean resolved = false;
String pageRefId;
private boolean resolved = false;
private String pageRefId;

public UnresolvedPageNumber(String id) {
pageRefId = id;
@@ -25,11 +26,19 @@ public class UnresolvedPageNumber extends Word implements Resolveable {
return new String[] {pageRefId};
}

public void resolve(String id, ArrayList pages) {
public void resolve(String id, List pages) {
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() {

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

@@ -91,7 +91,7 @@ public class BookmarkData implements Resolveable, TreeExt {
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)) {
BookmarkData bd = (BookmarkData)idRefs.get(id);
idRefs.remove(id);

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

@@ -13,13 +13,24 @@ import org.apache.fop.apps.FOPException;
import org.apache.fop.fo.properties.*;
import org.apache.fop.layout.*;
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
import java.util.Enumeration;
import java.awt.Rectangle;
import java.util.List;
import java.util.ArrayList;

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

public BasicLink(FONode parent) {
super(parent);
@@ -27,7 +38,32 @@ public class BasicLink extends Inline {

// add start and end properties for the link
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() {
@@ -55,20 +91,61 @@ public class BasicLink extends Inline {
// this.properties.get("baseline-shift");
// this.properties.get("destination-place-offset");
// this.properties.get("dominant-baseline");
// this.properties.get("external-destination");
String ext = properties.get("external-destination").getString();
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-with-next");
// this.properties.get("keep-with-previous");
// this.properties.get("line-height");
// 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

@@ -55,25 +55,21 @@ public class Leader extends FObjMixed {
public void addLayoutManager(List list) {
LeafNodeLayoutManager lm = new LeafNodeLayoutManager(this) {
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());
list.add(lm);
}

protected InlineArea getInlineArea(int refIPD) {
protected InlineArea getInlineArea() {
if(leaderArea == null) {
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;
}

@@ -88,9 +84,7 @@ public class Leader extends FObjMixed {

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

leaderArea = space;
leaderArea = new Space();
} else if(leaderPattern == LeaderPattern.DOTS) {
Word w = new Word();
char dot = '.'; // userAgent.getLeaderDotChar();
@@ -226,7 +220,7 @@ public class Leader extends FObjMixed {

}

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

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

@@ -16,6 +16,7 @@ import org.apache.fop.layout.*;
import org.apache.fop.apps.FOPException;
import org.apache.fop.layoutmgr.LeafNodeLayoutManager;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.PageViewport;
import org.apache.fop.util.CharUtilities;
import org.apache.fop.apps.StructureHandler;
import org.apache.fop.layoutmgr.LayoutContext;
@@ -67,52 +68,54 @@ public class PageNumberCitation extends FObj {
}

public void addAreas(PositionIterator posIter,
LayoutContext context) {
LayoutContext 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
private InlineArea getInlineArea(LayoutManager parentLM) {
if (refId.equals("")) {
getLogger().error("page-number-citation must contain \"ref-id\"");
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 {
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;
}

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

@@ -11,6 +11,7 @@ import org.apache.fop.fo.FObj;
import org.apache.fop.fo.FONode;
import org.apache.fop.area.Area;
import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.PropertyManager;

import java.util.ListIterator;
@@ -260,7 +261,7 @@ public abstract class AbstractLayoutManager implements LayoutManager {
return parentLM.getCurrentPageNumber();
}

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


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

@@ -11,6 +11,7 @@ package org.apache.fop.layoutmgr;
import org.apache.fop.area.Area;
import org.apache.fop.area.MinOptMax;
import org.apache.fop.area.Resolveable;
import org.apache.fop.area.PageViewport;

import java.util.ArrayList;

@@ -22,6 +23,7 @@ import java.util.ArrayList;
public class ContentLayoutManager implements LayoutManager {
Area holder;
int stackSize;
LayoutManager parentLM;

public ContentLayoutManager(Area area) {
holder = area;
@@ -76,6 +78,7 @@ public class ContentLayoutManager implements LayoutManager {
}

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

public boolean canBreakBefore(LayoutContext lc) {
@@ -107,17 +110,19 @@ public class ContentLayoutManager implements LayoutManager {
}

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) {
parentLM.addIDToPage(id);
}

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


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

@@ -42,6 +42,12 @@ public class FlowLayoutManager extends BlockStackingLayoutManager {
MinOptMax stackSize = new MinOptMax();

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

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

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

@@ -378,6 +378,10 @@ public class InlineStackingLayoutManager extends AbstractLayoutManager {
}
*****/

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

/**
* Generate and add areas to parent area.
* Set size of each area.
@@ -388,7 +392,10 @@ public class InlineStackingLayoutManager extends AbstractLayoutManager {
*/
public void addAreas(PositionIterator parentIter,
LayoutContext context) {
setCurrentArea(new InlineParent());
InlineParent parent = createArea();
parent.setHeight(context.getLineHeight());
parent.setOffset(0);
setCurrentArea(parent);

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


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

@@ -10,6 +10,7 @@ package org.apache.fop.layoutmgr;

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

/**
* The interface for all LayoutManagers.
@@ -65,7 +66,7 @@ public interface LayoutManager {

public String getCurrentPageNumber();

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

public void addIDToPage(String id);


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

@@ -23,6 +23,7 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {
private InlineArea curArea = null;
private int alignment;
private int lead;
private MinOptMax ipd;

public LeafNodeLayoutManager(FObj fobj) {
super(fobj);
@@ -76,7 +77,8 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {
BreakPoss.CAN_BREAK_AFTER |
BreakPoss.CAN_BREAK_BEFORE | BreakPoss.ISFIRST |
BreakPoss.ISLAST);
bp.setStackingSize(curArea.getAllocationIPD());
ipd = getAllocationIPD(context.getRefIPD());
bp.setStackingSize(ipd);
bp.setNonStackingSize(curArea.getAllocationBPD());
bp.setTrailingSpace(new SpaceSpecifier(false));

@@ -101,6 +103,10 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {
return bp;
}

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

public void resetPosition(Position resetPos) {
// only reset if setting null, start again
if(resetPos == null) {
@@ -113,6 +119,15 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {

addID();

offsetArea(context);
widthAdjustArea(context);

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

protected void offsetArea(LayoutContext context) {
int bpd = curArea.getHeight();
switch(alignment) {
case VerticalAlign.MIDDLE:
@@ -129,9 +144,10 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {
curArea.setOffset(context.getBaseline() - bpd);
break;
}
}

protected void widthAdjustArea(LayoutContext context) {
double dAdjust = context.getIPDAdjust();
MinOptMax ipd = curArea.getAllocationIPD();
int width = ipd.opt;
if(dAdjust < 0) {
width = (int)(width + dAdjust * (ipd.opt - ipd.min));
@@ -139,10 +155,6 @@ public class LeafNodeLayoutManager extends AbstractLayoutManager {
width = (int)(width + dAdjust * (ipd.max - ipd.opt));
}
curArea.setWidth(width);

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

public boolean canBreakBefore(LayoutContext context) {

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

@@ -138,7 +138,11 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable
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;
}

@@ -155,6 +159,7 @@ public class PageLayoutManager extends AbstractLayoutManager implements Runnable

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


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

@@ -21,7 +21,7 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;

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

PDFLink linkObject;
@@ -1216,7 +1216,7 @@ public class PDFDocument {
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);
this.objects.add(link);


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

@@ -8,7 +8,7 @@
package org.apache.fop.pdf;

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

/**
* class representing an /Annot object of /Subtype /Link
@@ -30,14 +30,14 @@ public class PDFLink extends PDFObject {
* @param number the object's number
* @param producer the application producing the PDF
*/
public PDFLink(int number, Rectangle r) {
public PDFLink(int number, Rectangle2D r) {
/* generic creation of PDF object */
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

}

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

@@ -1,6 +1,6 @@
/*
* $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
* LICENSE file included with these sources.
*/
@@ -35,6 +35,7 @@ import org.w3c.dom.Document;
import java.io.IOException;
import java.io.OutputStream;
import java.awt.geom.Rectangle2D;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.HashMap;
import java.util.List;
@@ -178,7 +179,7 @@ public class PDFRenderer extends PrintRenderer {

public void renderExtension(TreeExt ext) {
// render bookmark extension
if(ext instanceof BookmarkData) {
if (ext instanceof BookmarkData) {
renderRootExtensions((BookmarkData)ext);
}
}
@@ -209,7 +210,7 @@ public class PDFRenderer extends PrintRenderer {
}

public void startPageSequence(Title seqTitle) {
if(seqTitle != null) {
if (seqTitle != null) {
String str = convertTitleToString(seqTitle);
PDFInfo info = this.pdfDoc.getInfo();
info.setTitle(str);
@@ -326,7 +327,7 @@ public class PDFRenderer extends PrintRenderer {

currentStream.add("ET\n");

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

currentStream.add("q\n");
@@ -354,7 +355,7 @@ public class PDFRenderer extends PrintRenderer {

Rectangle2D rect = bv.getBounds();

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

@@ -362,16 +363,16 @@ public class PDFRenderer extends PrintRenderer {

double[] vals = ctm.toArray();
boolean aclock = vals[2] == 1.0;
if(vals[2] == 1.0) {
if (vals[2] == 1.0) {
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());
} else {
ctm = ctm.translate(saveBP, saveIP - rect.getWidth());
}
}

if(bv.getClip()) {
if (bv.getClip()) {
currentStream.add("q\n");
float x = (float)rect.getX() / 1000f;
float y = (float)rect.getY() / 1000f;
@@ -380,24 +381,24 @@ public class PDFRenderer extends PrintRenderer {
clip(x, y, width, height);
}

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

// clip if necessary

if(rect != null) {
if (rect != null) {
currentIPPosition = saveIP;
currentBPPosition = saveBP;
currentBPPosition += (int)(rect.getHeight());
@@ -405,6 +406,15 @@ public class PDFRenderer extends PrintRenderer {
}
}

/**
* 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) {
currentStream.add(x + " " + y + " m\n");
currentStream.add((x + width) + " " + y + " l\n");
@@ -420,6 +430,45 @@ public class PDFRenderer extends PrintRenderer {
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) {

super.renderCharacter(ch);
@@ -453,8 +502,8 @@ public class PDFRenderer extends PrintRenderer {
if (!textOpen || bl != prevWordY) {
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;
textOpen = true;
} else {
@@ -467,8 +516,8 @@ public class PDFRenderer extends PrintRenderer {
if (emDiff < -33000) {
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;
} else {
pdf.append(Float.toString(emDiff));
@@ -553,10 +602,11 @@ public class PDFRenderer extends PrintRenderer {
(int) uniBytes[i];

String hexString = Integer.toHexString(b);
if (hexString.length() == 1)
if (hexString.length() == 1) {
buf = buf.append("0" + hexString);
else
} else {
buf = buf.append(hexString);
}
}
return buf.toString();
}
@@ -608,8 +658,8 @@ public class PDFRenderer extends PrintRenderer {
}

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();

this.currentFontName = name;
@@ -693,16 +743,16 @@ public class PDFRenderer extends PrintRenderer {
try {
this.pdfDoc.output(ostream);
} catch (IOException ioe) {
// ioexception will be caught later
}
}

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");

}

@@ -738,6 +788,11 @@ public class PDFRenderer extends PrintRenderer {

}

/**
* Render an inline viewport.
* This renders an inline viewport by clipping if necessary.
* @param viewport the viewport to handle
*/
public void renderViewport(Viewport viewport) {
closeText();
currentStream.add("ET\n");
@@ -758,6 +813,11 @@ public class PDFRenderer extends PrintRenderer {
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) {
closeText();
currentStream.add("ET\n");
@@ -783,14 +843,14 @@ public class PDFRenderer extends PrintRenderer {
float startx = ((float) currentBlockIPPosition) / 1000f;
float starty = ((currentBPPosition + area.getOffset()) / 1000f);
float endx = (currentBlockIPPosition + area.getWidth()) / 1000f;
if(!alt) {
if (!alt) {
currentStream.add(area.getRuleThickness() / 1000f + " w\n");

currentStream.add(startx + " " + starty + " m\n");
currentStream.add(endx + " " + starty + " l\n");
currentStream.add("S\n");
} else {
if(style == RuleStyle.DOUBLE) {
if (style == RuleStyle.DOUBLE) {
float third = area.getRuleThickness() / 3000f;
currentStream.add(third + " w\n");
currentStream.add(startx + " " + starty + " m\n");
@@ -810,7 +870,7 @@ public class PDFRenderer extends PrintRenderer {
currentStream.add(startx + " " + (starty + 2 * half) + " l\n");
currentStream.add("h\n");
currentStream.add("f\n");
if(style == RuleStyle.GROOVE) {
if (style == RuleStyle.GROOVE) {
currentStream.add("0 g\n");
currentStream.add(startx + " " + starty + " m\n");
currentStream.add(endx + " " + starty + " l\n");

Loading…
Cancel
Save