<fo:flow flow-name="xsl-region-body">
<fo:block font-size="18pt" font-weight="bold">1. FOP test for images</fo:block>
<fo:block id="N2531">
- <fox:destination internal-destination="N2531"/>
+ <!--fox:destination internal-destination="N2531"/-->
<fo:block font-size="16pt" font-weight="bold" space-before.minimum="1em" space-before.optimum="1.5em" space-before.maximum="2em">A GIF image in FOP</fo:block>
<fo:block>
<fo:external-graphic src="file:../graphics/xml_feather.gif"/>
</fo:block>
</fo:block>
<fo:block id="N2535">
- <fox:destination internal-destination="N2535"/>
+ <!--fox:destination internal-destination="N2535"/-->
<fo:block font-size="16pt" font-weight="bold" space-before.minimum="1em" space-before.optimum="1.5em" space-before.maximum="2em">A transparent GIF image in FOP</fo:block>
<fo:block>
<fo:external-graphic src="file:../graphics/xml_feather_transparent.gif"/>
</fo:block>
</fo:block>
<fo:block id="N2545">
- <fox:destination internal-destination="N2545"/>
+ <!--fox:destination internal-destination="N2545"/-->
<fo:block font-size="16pt" font-weight="bold" space-before.minimum="1em" space-before.optimum="1.5em" space-before.maximum="2em">A JPEG image in FOP</fo:block>
<fo:block>
<fo:external-graphic src="file:../graphics/fop.jpg"/>
</fo:block>
</fo:block>
<fo:block id="N2550">
- <fox:destination internal-destination="N2550"/>
+ <!--fox:destination internal-destination="N2550"/-->
<fo:block font-size="16pt" font-weight="bold" space-before.minimum="1em" space-before.optimum="1.5em" space-before.maximum="2em">A BMP image in FOP</fo:block>
<fo:block>
<fo:external-graphic src="file:../graphics/linux.bmp"/>
</fo:block>
</fo:block>
<fo:block id="N2559">
- <fox:destination internal-destination="N2559"/>
+ <!--fox:destination internal-destination="N2559"/-->
<fo:block font-size="16pt" font-weight="bold" space-before.minimum="1em" space-before.optimum="1.5em" space-before.maximum="2em"/>
This section is only required to show that the layout still works.
</fo:block>
<fo:flow flow-name="xsl-region-body">
<fo:block id="AppendixA" font-size="18pt" font-weight="bold">A. Appendix</fo:block>
- <fox:destination internal-destination="AppendixA"/>
+ <!--fox:destination internal-destination="AppendixA"/-->
</fo:flow>
</fo:page-sequence>
// Java
import java.util.List;
-import java.awt.geom.Rectangle2D;
// XML
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;
// FOP
-import org.apache.fop.area.inline.Image;
-import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.ImageFactory;
import org.apache.fop.layoutmgr.ExternalGraphicLayoutManager;
/**
*/
public class ExternalGraphic extends FObj {
private String url;
- private int breakAfter;
- private int breakBefore;
- private int align;
- private int startIndent;
- private int endIndent;
- private int spaceBefore;
- private int spaceAfter;
- private int viewWidth = -1;
- private int viewHeight = -1;
- private boolean clip = false;
- private Rectangle2D placement = null;
/**
* Create a new External graphic node.
*/
protected void addProperties(Attributes attlist) throws SAXParseException {
super.addProperties(attlist);
- getFOInputHandler().image(this);
- }
-
- /**
- * Setup this image.
- * This gets the sizes for the image and the dimensions and clipping.
- * @todo move logic to LM class and/or addProperties() as appropriate
- */
- private void setup() {
url = this.propertyList.get(PR_SRC).getString();
- if (url == null) {
- return;
- }
- url = ImageFactory.getURL(url);
-
- // assume lr-tb for now and just use the .optimum value of the range
- Length ipd = propertyList.get(PR_INLINE_PROGRESSION_DIMENSION).
- getLengthRange().getOptimum().getLength();
- if (!ipd.isAuto()) {
- viewWidth = ipd.getValue();
- } else {
- ipd = propertyList.get(PR_WIDTH).getLength();
- if (!ipd.isAuto()) {
- viewWidth = ipd.getValue();
- }
- }
- Length bpd = propertyList.get(PR_BLOCK_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
- if (!bpd.isAuto()) {
- viewHeight = bpd.getValue();
- } else {
- bpd = propertyList.get(PR_HEIGHT).getLength();
- if (!bpd.isAuto()) {
- viewHeight = bpd.getValue();
- }
- }
-
- // if we need to load this image to get its size
- FopImage fopimage = null;
-
- int cwidth = -1;
- int cheight = -1;
- Length ch = propertyList.get(PR_CONTENT_HEIGHT).getLength();
- if (!ch.isAuto()) {
- /*if (ch.scaleToFit()) {
- if (viewHeight != -1) {
- cheight = viewHeight;
- }
- } else {*/
- cheight = ch.getValue();
- }
- Length cw = propertyList.get(PR_CONTENT_WIDTH).getLength();
- if (!cw.isAuto()) {
- /*if (cw.scaleToFit()) {
- if (viewWidth != -1) {
- cwidth = viewWidth;
- }
- } else {*/
- cwidth = cw.getValue();
- }
-
- int scaling = propertyList.get(PR_SCALING).getEnum();
- if ((scaling == Scaling.UNIFORM) || (cwidth == -1) || cheight == -1) {
- ImageFactory fact = ImageFactory.getInstance();
- fopimage = fact.getImage(url, getUserAgent());
- if (fopimage == null) {
- // error
- url = null;
- return;
- }
- // load dimensions
- if (!fopimage.load(FopImage.DIMENSIONS)) {
- // error
- url = null;
- return;
- }
- if (cwidth == -1 && cheight == -1) {
- cwidth = (int)(fopimage.getWidth() * 1000);
- cheight = (int)(fopimage.getHeight() * 1000);
- } else if (cwidth == -1) {
- cwidth = (int)(fopimage.getWidth() * cheight) / fopimage.getHeight();
- } else if (cheight == -1) {
- cheight = (int)(fopimage.getHeight() * cwidth) / fopimage.getWidth();
- } else {
- // adjust the larger
- double rat1 = cwidth / (fopimage.getWidth() * 1000f);
- double rat2 = cheight / (fopimage.getHeight() * 1000f);
- if (rat1 < rat2) {
- // reduce cheight
- cheight = (int)(rat1 * fopimage.getHeight() * 1000);
- } else {
- cwidth = (int)(rat2 * fopimage.getWidth() * 1000);
- }
- }
- }
-
- if (viewWidth == -1) {
- viewWidth = cwidth;
- }
- if (viewHeight == -1) {
- viewHeight = cheight;
- }
-
- if (cwidth > viewWidth || cheight > viewHeight) {
- int overflow = propertyList.get(PR_OVERFLOW).getEnum();
- if (overflow == Overflow.HIDDEN) {
- clip = true;
- } else if (overflow == Overflow.ERROR_IF_OVERFLOW) {
- getLogger().error("Image: " + url
- + " overflows the viewport, clipping to viewport");
- clip = true;
- }
- }
-
- int xoffset = 0;
- int yoffset = 0;
- int da = propertyList.get(PR_DISPLAY_ALIGN).getEnum();
- switch(da) {
- case DisplayAlign.BEFORE:
- break;
- case DisplayAlign.AFTER:
- yoffset = viewHeight - cheight;
- break;
- case DisplayAlign.CENTER:
- yoffset = (viewHeight - cheight) / 2;
- break;
- case DisplayAlign.AUTO:
- default:
- break;
- }
-
- int ta = propertyList.get(PR_TEXT_ALIGN).getEnum();
- switch(ta) {
- case TextAlign.CENTER:
- xoffset = (viewWidth - cwidth) / 2;
- break;
- case TextAlign.END:
- xoffset = viewWidth - cwidth;
- break;
- case TextAlign.START:
- break;
- case TextAlign.JUSTIFY:
- default:
- break;
- }
- placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight);
- }
-
- /**
- * @return the ViewHeight (in millipoints??)
- * @todo check that each of these accessors are needed
- */
- public int getViewHeight() {
- return viewHeight;
+ getFOInputHandler().image(this);
}
public String getURL() {
return url;
}
- public int getViewWidth() {
- return viewWidth;
- }
-
- public boolean getClip() {
- return clip;
- }
-
- public Rectangle2D getPlacement() {
- return placement;
- }
-
/**
* @see org.apache.fop.fo.FObj#addLayoutManager(List)
*/
public void addLayoutManager(List list) {
- setup();
if (getURL() != null) {
ExternalGraphicLayoutManager lm = new ExternalGraphicLayoutManager(this);
list.add(lm);
// XML
import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
// FOP
public class Footnote extends FObj {
private Inline inlineFO = null;
- private FootnoteBody body;
+ private FootnoteBody footnoteBody;
/**
* @param parent FONode that is the parent of this object
getFOInputHandler().startFootnote(this);
}
+ /**
+ * @see org.apache.fop.fo.FONode#validateChildNode(Locator, String, String)
+ * XSL Content Model: (inline,footnote-body)
+ * @todo: implement additional constraint: An fo:footnote is not permitted
+ * to have an fo:float, fo:footnote, or fo:marker as a descendant.
+ * @todo: implement additional constraint: An an fo:footnote is not
+ * permitted to have as a descendant an fo:block-container that
+ * generates an absolutely positioned area.
+ */
+ protected void validateChildNode(Locator loc, String nsURI, String localName)
+ throws SAXParseException {
+ if (nsURI == FO_URI && localName.equals("inline")) {
+ if (inlineFO != null) {
+ tooManyNodesError(loc, "fo:inline");
+ }
+ } else if (nsURI == FO_URI && localName.equals("footnote-body")) {
+ if (inlineFO == null) {
+ nodesOutOfOrderError(loc, "fo:inline", "fo:footnote-body");
+ } else if (footnoteBody != null) {
+ tooManyNodesError(loc, "fo:footnote-body");
+ }
+ } else {
+ invalidChildError(loc, nsURI, localName);
+ }
+ }
+
+ /**
+ * Make sure content model satisfied, if so then tell the
+ * StructureRenderer that we are at the end of the flow.
+ * @see org.apache.fop.fo.FONode#end
+ */
+ protected void endOfNode() throws SAXParseException {
+ super.endOfNode();
+ if (inlineFO == null || footnoteBody == null) {
+ missingChildElementError("(inline,footnote-body)");
+ }
+ getFOInputHandler().endFootnote(this);
+ }
+
/**
* @see org.apache.fop.fo.FONode#addChildNode(FONode)
*/
public void addChildNode(FONode child) {
- String name = child.getName();
- if ("fo:inline".equals(name)) {
- inlineFO = (Inline)child;
- } else if ("fo:footnote-body".equals(name)) {
- body = (FootnoteBody)child;
- } else {
- getLogger().error("invalid child of footnote: " + name);
+ if (((FObj)child).getNameId() == FO_INLINE) {
+ inlineFO = (Inline) child;
+ } else if (((FObj)child).getNameId() == FO_FOOTNOTE_BODY) {
+ footnoteBody = (FootnoteBody) child;
}
}
return inlineFO;
}
- protected void endOfNode() throws SAXParseException {
- super.endOfNode();
- getFOInputHandler().endFootnote(this);
- }
-
/**
* @see org.apache.fop.fo.FObj#addLayoutManager(List)
*/
getInlineFO().addLayoutManager(list);
}
+ /**
+ * @see org.apache.fop.fo.FObj#getName()
+ */
public String getName() {
return "fo:footnote";
}
package org.apache.fop.fo.flow;
// Java
+import java.util.List;
+import java.util.ListIterator;
import java.util.ArrayList;
// XML
import org.apache.fop.datatypes.ColorType;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
-import org.apache.fop.layoutmgr.AddLMVisitor;
+import org.apache.fop.layoutmgr.table.TableLayoutManager;
+import org.apache.fop.layoutmgr.table.Body;
+import org.apache.fop.layoutmgr.table.Column;
import org.apache.fop.fo.properties.CommonAccessibility;
import org.apache.fop.fo.properties.CommonAural;
import org.apache.fop.fo.properties.CommonBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonRelativePosition;
import org.apache.fop.fo.properties.LengthRangeProperty;
-import org.apache.fop.fo.LMVisited;
/**
* Class modelling the fo:table object. See Sec. 6.7.3 of the XSL-FO Standard.
*/
-public class Table extends FObj implements LMVisited {
+public class Table extends FObj {
private static final int MINCOLWIDTH = 10000; // 10pt
/** collection of columns in this table */
getFOInputHandler().startTable(this);
}
+ protected void endOfNode() throws SAXParseException {
+ getFOInputHandler().endTable(this);
+ }
+
/**
* @see org.apache.fop.fo.FONode#addChildNode(FONode)
*/
return false;
}
- public ArrayList getColumns() {
+ private ArrayList getColumns() {
return columns;
}
- public TableBody getTableHeader() {
+ private TableBody getTableHeader() {
return tableHeader;
}
- public TableBody getTableFooter() {
+ private TableBody getTableFooter() {
return tableFooter;
}
/**
- * This is a hook for the AddLMVisitor class to be able to access
- * this object.
- * @param aLMV the AddLMVisitor object that can access this object.
+ * @see org.apache.fop.fo.FObj#addLayoutManager(List)
+ * @todo see if can/should move much of this logic into TableLayoutManager
+ * and/or TableBody and TableColumn FO subclasses.
*/
- public void acceptVisitor(AddLMVisitor aLMV) {
- aLMV.serveTable(this);
+ public void addLayoutManager(List list) {
+ TableLayoutManager tlm = new TableLayoutManager(this);
+ ArrayList columns = getColumns();
+ if (columns != null) {
+ ArrayList columnLMs = new ArrayList();
+ ListIterator iter = columns.listIterator();
+ while (iter.hasNext()) {
+ columnLMs.add(getTableColumnLayoutManager((TableColumn)iter.next()));
+ }
+ tlm.setColumns(columnLMs);
+ }
+ if (getTableHeader() != null) {
+ tlm.setTableHeader(getTableBodyLayoutManager(getTableHeader()));
+ }
+ if (getTableFooter() != null) {
+ tlm.setTableFooter(getTableBodyLayoutManager(getTableFooter()));
+ }
+ list.add(tlm);
}
- protected void endOfNode() throws SAXParseException {
- getFOInputHandler().endTable(this);
+ public Column getTableColumnLayoutManager(TableColumn node) {
+ node.initialize();
+ Column clm = new Column(node);
+ return clm;
+ }
+
+ public Body getTableBodyLayoutManager(TableBody node) {
+ Body blm = new Body(node);
+ return blm;
}
public String getName() {
getFOInputHandler().startRow(this);
}
+
+ protected void endOfNode() throws SAXParseException {
+ getFOInputHandler().endRow(this);
+ }
+
/**
* @return keepWithPrevious
*/
Row rlm = new Row(this);
list.add(rlm);
}
-
- protected void endOfNode() throws SAXParseException {
- getFOInputHandler().endRow(this);
- }
+ /**
+ * @see org.apache.fop.fo.FObj#getName()
+ */
public String getName() {
return "fo:table-row";
}
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
-import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.apache.fop.fo.flow.Inline;
import org.apache.fop.fo.flow.InstreamForeignObject;
import org.apache.fop.fo.flow.Leader;
-import org.apache.fop.fo.flow.Table;
-import org.apache.fop.fo.flow.TableAndCaption;
-import org.apache.fop.fo.flow.TableBody;
-import org.apache.fop.fo.flow.TableCell;
-import org.apache.fop.fo.flow.TableColumn;
-import org.apache.fop.fo.flow.TableRow;
import org.apache.fop.fo.flow.Wrapper;
-import org.apache.fop.fo.pagination.Title;
-import org.apache.fop.fo.properties.CommonBackground;
-import org.apache.fop.fo.properties.CommonBorderAndPadding;
-import org.apache.fop.layoutmgr.table.Body;
-import org.apache.fop.layoutmgr.table.Column;
-import org.apache.fop.layoutmgr.table.TableLayoutManager;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.fo.LMVisited;
return areaCurrent;
}
-
- public void serveTable(Table node) {
- TableLayoutManager tlm = new TableLayoutManager(node);
- ArrayList columns = node.getColumns();
- if (columns != null) {
- ArrayList columnLMs = new ArrayList();
- ListIterator iter = columns.listIterator();
- while (iter.hasNext()) {
- columnLMs.add(getTableColumnLayoutManager((TableColumn)iter.next()));
- }
- tlm.setColumns(columnLMs);
- }
- if (node.getTableHeader() != null) {
- tlm.setTableHeader(getTableBodyLayoutManager(node.getTableHeader()));
- }
- if (node.getTableFooter() != null) {
- tlm.setTableFooter(getTableBodyLayoutManager(node.getTableFooter()));
- }
- currentLMList.add(tlm);
- }
-
- public LayoutManager getTableColumnLayoutManager(TableColumn node) {
- node.initialize();
- Column clm = new Column(node);
- return clm;
- }
-
- public Body getTableBodyLayoutManager(TableBody node) {
- Body blm = new Body(node);
- return blm;
- }
}
package org.apache.fop.layoutmgr;
+// Java
+import java.awt.geom.Rectangle2D;
+
+// FOP
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.Viewport;
+import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.flow.ExternalGraphic;
import org.apache.fop.fo.properties.CommonBorderAndPadding;
import org.apache.fop.fo.properties.CommonBackground;
+import org.apache.fop.image.FopImage;
+import org.apache.fop.image.ImageFactory;
/**
* LayoutManager for the fo:external-graphic formatting object
ExternalGraphic graphic = null;
+ private String url;
+ private int breakAfter;
+ private int breakBefore;
+ private int align;
+ private int startIndent;
+ private int endIndent;
+ private int spaceBefore;
+ private int spaceAfter;
+ private int viewWidth = -1;
+ private int viewHeight = -1;
+ private boolean clip = false;
+ private Rectangle2D placement = null;
+
/**
* Constructor
*
super(node);
graphic = node;
+ setup();
InlineArea area = getExternalGraphicInlineArea();
setCurrentArea(area);
setAlignment(graphic.getProperty(PR_VERTICAL_ALIGN).getEnum());
- setLead(graphic.getViewHeight());
+ setLead(viewHeight);
+ }
+
+ /**
+ * Setup this image.
+ * This gets the sizes for the image and the dimensions and clipping.
+ * @todo see if can simplify property handling logic
+ */
+ private void setup() {
+ url = ImageFactory.getURL(graphic.getURL());
+
+ // assume lr-tb for now and just use the .optimum value of the range
+ Length ipd = graphic.getPropertyList().get(PR_INLINE_PROGRESSION_DIMENSION).
+ getLengthRange().getOptimum().getLength();
+ if (!ipd.isAuto()) {
+ viewWidth = ipd.getValue();
+ } else {
+ ipd = graphic.getPropertyList().get(PR_WIDTH).getLength();
+ if (!ipd.isAuto()) {
+ viewWidth = ipd.getValue();
+ }
+ }
+ Length bpd = graphic.getPropertyList().get(PR_BLOCK_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
+ if (!bpd.isAuto()) {
+ viewHeight = bpd.getValue();
+ } else {
+ bpd = graphic.getPropertyList().get(PR_HEIGHT).getLength();
+ if (!bpd.isAuto()) {
+ viewHeight = bpd.getValue();
+ }
+ }
+
+ // if we need to load this image to get its size
+ FopImage fopimage = null;
+
+ int cwidth = -1;
+ int cheight = -1;
+ Length ch = graphic.getPropertyList().get(PR_CONTENT_HEIGHT).getLength();
+ if (!ch.isAuto()) {
+ /*if (ch.scaleToFit()) {
+ if (viewHeight != -1) {
+ cheight = viewHeight;
+ }
+ } else {*/
+ cheight = ch.getValue();
+ }
+ Length cw = graphic.getPropertyList().get(PR_CONTENT_WIDTH).getLength();
+ if (!cw.isAuto()) {
+ /*if (cw.scaleToFit()) {
+ if (viewWidth != -1) {
+ cwidth = viewWidth;
+ }
+ } else {*/
+ cwidth = cw.getValue();
+ }
+
+ int scaling = graphic.getPropertyList().get(PR_SCALING).getEnum();
+ if ((scaling == Scaling.UNIFORM) || (cwidth == -1) || cheight == -1) {
+ ImageFactory fact = ImageFactory.getInstance();
+ fopimage = fact.getImage(url, graphic.getUserAgent());
+ if (fopimage == null) {
+ // error
+ url = null;
+ return;
+ }
+ // load dimensions
+ if (!fopimage.load(FopImage.DIMENSIONS)) {
+ // error
+ url = null;
+ return;
+ }
+ if (cwidth == -1 && cheight == -1) {
+ cwidth = (int)(fopimage.getWidth() * 1000);
+ cheight = (int)(fopimage.getHeight() * 1000);
+ } else if (cwidth == -1) {
+ cwidth = (int)(fopimage.getWidth() * cheight) / fopimage.getHeight();
+ } else if (cheight == -1) {
+ cheight = (int)(fopimage.getHeight() * cwidth) / fopimage.getWidth();
+ } else {
+ // adjust the larger
+ double rat1 = cwidth / (fopimage.getWidth() * 1000f);
+ double rat2 = cheight / (fopimage.getHeight() * 1000f);
+ if (rat1 < rat2) {
+ // reduce cheight
+ cheight = (int)(rat1 * fopimage.getHeight() * 1000);
+ } else {
+ cwidth = (int)(rat2 * fopimage.getWidth() * 1000);
+ }
+ }
+ }
+
+ if (viewWidth == -1) {
+ viewWidth = cwidth;
+ }
+ if (viewHeight == -1) {
+ viewHeight = cheight;
+ }
+
+ if (cwidth > viewWidth || cheight > viewHeight) {
+ int overflow = graphic.getPropertyList().get(PR_OVERFLOW).getEnum();
+ if (overflow == Overflow.HIDDEN) {
+ clip = true;
+ } else if (overflow == Overflow.ERROR_IF_OVERFLOW) {
+ graphic.getLogger().error("Image: " + url
+ + " overflows the viewport, clipping to viewport");
+ clip = true;
+ }
+ }
+
+ int xoffset = 0;
+ int yoffset = 0;
+ int da = graphic.getPropertyList().get(PR_DISPLAY_ALIGN).getEnum();
+ switch(da) {
+ case DisplayAlign.BEFORE:
+ break;
+ case DisplayAlign.AFTER:
+ yoffset = viewHeight - cheight;
+ break;
+ case DisplayAlign.CENTER:
+ yoffset = (viewHeight - cheight) / 2;
+ break;
+ case DisplayAlign.AUTO:
+ default:
+ break;
+ }
+
+ int ta = graphic.getPropertyList().get(PR_TEXT_ALIGN).getEnum();
+ switch(ta) {
+ case TextAlign.CENTER:
+ xoffset = (viewWidth - cwidth) / 2;
+ break;
+ case TextAlign.END:
+ xoffset = viewWidth - cwidth;
+ break;
+ case TextAlign.START:
+ break;
+ case TextAlign.JUSTIFY:
+ default:
+ break;
+ }
+ placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight);
}
/**
public InlineArea getExternalGraphicInlineArea() {
Image imArea = new Image(graphic.getURL());
Viewport vp = new Viewport(imArea);
- vp.setWidth(graphic.getViewWidth());
- vp.setHeight(graphic.getViewHeight());
- vp.setClip(graphic.getClip());
- vp.setContentPosition(graphic.getPlacement());
+ vp.setWidth(viewWidth);
+ vp.setHeight(viewHeight);
+ vp.setClip(clip);
+ vp.setContentPosition(placement);
vp.setOffset(0);
// Common Border, Padding, and Background Properties