![JAR search and dependency download from the Maven repository](/logo.png)
com.adobe.xfa.layout.BoxModelRenderProxy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* ADOBE CONFIDENTIAL
*
* Copyright 2007 Adobe Systems Incorporated All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of
* Adobe Systems Incorporated and its suppliers, if any. The intellectual and
* technical concepts contained herein are proprietary to Adobe Systems
* Incorporated and its suppliers and may be covered by U.S. and Foreign
* Patents, patents in process, and are protected by trade secret or copyright
* law. Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained from
* Adobe Systems Incorporated.
*/
package com.adobe.xfa.layout;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import com.adobe.xfa.Attribute;
import com.adobe.xfa.Element;
import com.adobe.xfa.EnumAttr;
import com.adobe.xfa.STRS;
import com.adobe.xfa.XFA;
import com.adobe.xfa.font.FontInfo;
import com.adobe.xfa.font.FontInstance;
import com.adobe.xfa.template.containers.Draw;
import com.adobe.xfa.template.containers.Field;
import com.adobe.xfa.template.containers.Rotate;
import com.adobe.xfa.svg.SVG;
import com.adobe.xfa.svg.SVGNode;
import com.adobe.xfa.svg.SVGTextData;
import com.adobe.xfa.ut.Angle;
import com.adobe.xfa.ut.CoordPair;
import com.adobe.xfa.ut.Rect;
import com.adobe.xfa.ut.UnitSpan;
import com.adobe.xfa.ut.Margins;
import com.adobe.xfa.ut.StringUtils;
/**
* This class provides the implementation for box model formatting
* when rendering from text run definitions. It was created for Performance
* and consistency of rendering.
* There are two formats in which we can find text run definitions:
* - Processing instructions
* - SVG
*
* The benefit of this class is that the text run definition gives
* us the width and height of the caption and content regions, which
* avoids the costly process of going through the text engine in order
* to obtain this information.
*
* For details on text caching please refer to the proposals at:
*
* http://xtg.can.adobe.com/twiki/bin/view//CacheBoilerplateXFAV23Proposal
*
* http://xtg.can.adobe.com/twiki/bin/view//SVGTextRunsXFAProposal
*
* @exclude from published api.
*/
class BoxModelRenderProxy extends BoxModelLayout {
public BoxModelRenderProxy(LayoutEnv oEnv) {
super();
m_oGfxLayoutEnv = oEnv;
m_bHasCaption = false;
mbIsProxy = false;
}
// Override
public Rect getCaptionExtent() {
return m_oCaptionExtent;
}
public Rect getContentExtent() {
return m_oContentExtent;
}
public void clear() {
m_bHasCaption = false;
m_oCaptionExtent = Rect.ZERO;
m_oContentExtent = Rect.ZERO;
super.clear();
}
public boolean allowRenderProxy() {
return true;
}
public boolean hasCaption() {
return m_bHasCaption;
}
public boolean isProxy() {
return mbIsProxy;
}
public void initialize(Element oNode) {
// This method gets called only if we're a leaf boxmodel object.
// i.e. not called when we've been sub-classed by BoxModelContentImpl
//Strategy
//Initialize the box model for a text based object (field/draw)
//1)Read initial box model settings from node, including
//-x,y,anchor
//-margins
//-border
//-caption info
//-initialize content (textual in this case)
//2)Then format the box model into subregions (content/caption) given these settings.
// This will automatically account for min/max ranges
//3)Rotate the box model, as appropriate.
//4)Record the visual extent of the box model
// Proxy box models should only be created for static objects.
assert(oNode instanceof Draw);
if (! isBoxModelCompatible(oNode))
return;
// This will initialize the box model from either SVG definition or PIs
checkProxyStatus(oNode);
// Read anchorPoint
initAnchorPoint(oNode);
// Read nominal extent, content and caption margins
initMargins(oNode);
// Read border margins, content border margins
initBorder(oNode);
// Format internals based on the info so far
//format(oNode);
// Once formatted, perform any rotation
//initRotatedContentTopLeft();
respectRotation(oNode);
// Finally, determine the visual extent.
initVisualExtent(oNode);
}
public void respectRotation(Element oNode) {
//Adjust the box model if it is rotated.
//Only support rotation on fields+draws,
//not subforms with flowing content
//Respecting min max must have already occurred.
m_bWasRotated = false;
m_oRotationAngle = Angle.ZERO;
if (oNode instanceof Draw || oNode instanceof Field) {
if (oNode.isPropertySpecified(XFA.ROTATETAG, true, 0)) {
Rotate oRotate = new Rotate(XFA.ROTATE, oNode.getAttribute(XFA.ROTATETAG).toString());
if (oRotate != null) {
Angle oAngle = oRotate.getAngle();
int lAngle = oAngle.degrees();
lAngle = lAngle % 360;
if (0 > lAngle)
lAngle += 360;
oAngle = new Angle(lAngle);
m_oRotationAngle = oAngle;
Margins oPrevMargins = m_oNEMargins;
Margins oPrevBorderMargins = m_oBorderMargins;
Margins oPrevWidgetBorderMargins = m_oContentBorderMargins;
Margins oPrevWidgetCaptionMargins = m_oCapMargins;
Margins oPrevWidgetContentMargins = m_oContMargins;
Rect rcPrevNE = getNominalExtent();
CoordPair oNewTL = CoordPair.ZERO_ZERO;
CoordPair oNewTR = CoordPair.ZERO_ZERO;
//CoordPair oNewBL = new CoordPair();
CoordPair oNewBR = CoordPair.ZERO_ZERO;
CoordPair oPrevTL = rcPrevNE.topLeft();
CoordPair oPrevTR = rcPrevNE.topRight();
CoordPair oPrevBL = rcPrevNE.bottomLeft();
CoordPair oPrevBR = rcPrevNE.bottomRight();
Rect rcPrevContentExtent = getContentExtent();
CoordPair oNewContentTL = CoordPair.ZERO_ZERO;
CoordPair oNewContentTR = CoordPair.ZERO_ZERO;
CoordPair oNewContentBL = CoordPair.ZERO_ZERO;
CoordPair oNewContentBR = CoordPair.ZERO_ZERO;
CoordPair oPrevContentTL = rcPrevContentExtent.topLeft();
CoordPair oPrevContentTR = rcPrevContentExtent.topRight();
CoordPair oPrevContentBL = rcPrevContentExtent.bottomLeft();
CoordPair oPrevContentBR = rcPrevContentExtent.bottomRight();
Rect rcPrevCaptionExtent = getCaptionExtent();
CoordPair oNewCaptionTL = CoordPair.ZERO_ZERO;
CoordPair oNewCaptionTR = CoordPair.ZERO_ZERO;
CoordPair oNewCaptionBL = CoordPair.ZERO_ZERO;
CoordPair oNewCaptionBR = CoordPair.ZERO_ZERO;
CoordPair oPrevCaptionTL = rcPrevCaptionExtent.topLeft();
CoordPair oPrevCaptionTR = rcPrevCaptionExtent.topRight();
CoordPair oPrevCaptionBL = rcPrevCaptionExtent.bottomLeft();
CoordPair oPrevCaptionBR = rcPrevCaptionExtent.bottomRight();
// Required for rotation calcs.
CoordPair oNewLocalContentTL = CoordPair.ZERO_ZERO;
CoordPair oNewLocalCaptionTL = CoordPair.ZERO_ZERO;
CoordPair oLocalAnchor = m_oAnchorPoint.subtract(oPrevTL);
CoordPair oContentOrigin = oPrevContentTL;
CoordPair oCaptionOrigin = oPrevCaptionTL;
switch (lAngle) {
case 0: { //nothing to do
//Adjust the top left of content extent for text, etc.
oNewLocalContentTL = oPrevContentTL.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedContentTopLeft = oNewLocalContentTL.subtract(oContentOrigin.rotatePoint(oLocalAnchor, oAngle));
//Adjust the top left of caption extent for text, etc.
oNewLocalCaptionTL = oPrevCaptionTL.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedCaptionTopLeft = oNewLocalCaptionTL.subtract(oContentOrigin.rotatePoint(oLocalAnchor, oAngle));
return;
}
case 270: {
//1)rotate the 4 corner points 90 degrees about 'm_oAnchorPoint'
//2)adjust new anchor point to new orientation
//3)flip content margins + border margins
//4)for both caption+non caption extents,
// rotate the 4 corner points 90 degrees about 'anchor' point
oNewTR = oPrevTL.rotatePoint(m_oAnchorPoint, oAngle);
oNewBR = oPrevTR.rotatePoint(m_oAnchorPoint, oAngle);
//oNewBL = oPrevBR.rotatePoint(m_oAnchorPoint, oAngle);
oNewTL = oPrevBL.rotatePoint(m_oAnchorPoint, oAngle);
// Calculation used to adjust to the local top left
CoordPair oAdjust = oPrevTL.subtract(oNewTL);
oNewContentTR = oPrevContentTL.rotatePoint(oLocalAnchor, oAngle);
oNewContentBR = oPrevContentTR.rotatePoint(oLocalAnchor, oAngle);
oNewContentBL = oPrevContentBR.rotatePoint(oLocalAnchor, oAngle);
oNewContentTL = oPrevContentBL.rotatePoint(oLocalAnchor, oAngle);
oNewContentTR = oNewContentTR.add(oAdjust);
oNewContentBR = oNewContentBR.add(oAdjust);
oNewContentBL = oNewContentBL.add(oAdjust);
oNewContentTL = oNewContentTL.add(oAdjust);
oNewCaptionTR = oPrevCaptionTL.rotatePoint(oLocalAnchor, oAngle);
oNewCaptionBR = oPrevCaptionTR.rotatePoint(oLocalAnchor, oAngle);
oNewCaptionBL = oPrevCaptionBR.rotatePoint(oLocalAnchor, oAngle);
oNewCaptionTL = oPrevCaptionBL.rotatePoint(oLocalAnchor, oAngle);
oNewCaptionTR = oNewCaptionTR.add(oAdjust);
oNewCaptionBR = oNewCaptionBR.add(oAdjust);
oNewCaptionBL = oNewCaptionBL.add(oAdjust);
oNewCaptionTL = oNewCaptionTL.add(oAdjust);
m_oNEMargins = new Margins(oPrevMargins.marginBottom(),
oPrevMargins.marginLeft(),
oPrevMargins.marginTop(),
oPrevMargins.marginRight());
m_oBorderMargins = new Margins(oPrevBorderMargins.marginBottom(),
oPrevBorderMargins.marginLeft(),
oPrevBorderMargins.marginTop(),
oPrevBorderMargins.marginRight());
m_oContentBorderMargins = new Margins(oPrevWidgetBorderMargins.marginBottom(),
oPrevWidgetBorderMargins.marginLeft(),
oPrevWidgetBorderMargins.marginTop(),
oPrevWidgetBorderMargins.marginRight());
m_oCapMargins = new Margins(oPrevWidgetCaptionMargins.marginBottom(),
oPrevWidgetCaptionMargins.marginLeft(),
oPrevWidgetCaptionMargins.marginTop(),
oPrevWidgetCaptionMargins.marginRight());
m_oContMargins = new Margins(oPrevWidgetContentMargins.marginBottom(),
oPrevWidgetContentMargins.marginLeft(),
oPrevWidgetContentMargins.marginTop(),
oPrevWidgetContentMargins.marginRight());
// These calc required for rotation.
//Adjust the top left of content extent for text, etc.
oNewLocalContentTL = oPrevContentBL.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedContentTopLeft = oNewLocalContentTL.subtract(oContentOrigin.rotatePoint(oLocalAnchor, oAngle));
//Adjust the top left of caption extent for text, etc.
oNewLocalCaptionTL = oPrevCaptionBL.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedCaptionTopLeft = oNewLocalCaptionTL.subtract(oCaptionOrigin.rotatePoint(oLocalAnchor, oAngle));
}
break;
case 180: {
//1)rotate the 4 corner points 180 degrees about 'm_oAnchorPoint'
//2)adjust new anchor point to new orientation
//3)flip content margins + border margins
//4)for both caption+non caption extents,
// rotate the 4 corner points 180 degrees about 'anchor' point
oNewBR = oPrevTL.rotatePoint(m_oAnchorPoint, oAngle); //A
//oNewBL = oPrevTR.rotatePoint(m_oAnchorPoint, oAngle); //B
oNewTL = oPrevBR.rotatePoint(m_oAnchorPoint, oAngle); //C
oNewTR = oPrevBL.rotatePoint(m_oAnchorPoint, oAngle); //D
// Calculation used to adjust to the local top left
CoordPair oAdjust = oPrevTL.subtract(oNewTL);
oNewContentBR = oPrevContentTL.rotatePoint(oLocalAnchor, oAngle); //A
oNewContentBL = oPrevContentTR.rotatePoint(oLocalAnchor, oAngle); //B
oNewContentTL = oPrevContentBR.rotatePoint(oLocalAnchor, oAngle); //C
oNewContentTR = oPrevContentBL.rotatePoint(oLocalAnchor, oAngle); //D
oNewContentTR = oNewContentTR.add(oAdjust);
oNewContentBR = oNewContentBR.add(oAdjust);
oNewContentBL = oNewContentBL.add(oAdjust);
oNewContentTL = oNewContentTL.add(oAdjust);
oNewCaptionBR = oPrevCaptionTL.rotatePoint(oLocalAnchor, oAngle); //A
oNewCaptionBL = oPrevCaptionTR.rotatePoint(oLocalAnchor, oAngle); //B
oNewCaptionTL = oPrevCaptionBR.rotatePoint(oLocalAnchor, oAngle); //C
oNewCaptionTR = oPrevCaptionBL.rotatePoint(oLocalAnchor, oAngle); //D
oNewCaptionTR = oNewCaptionTR.add(oAdjust);
oNewCaptionBR = oNewCaptionBR.add(oAdjust);
oNewCaptionBL = oNewCaptionBL.add(oAdjust);
oNewCaptionTL = oNewCaptionTL.add(oAdjust);
m_oNEMargins = new Margins(oPrevMargins.marginRight(),
oPrevMargins.marginBottom(),
oPrevMargins.marginLeft(),
oPrevMargins.marginTop());
m_oBorderMargins = new Margins(oPrevBorderMargins.marginRight(),
oPrevBorderMargins.marginBottom(),
oPrevBorderMargins.marginLeft(),
oPrevBorderMargins.marginTop());
m_oContentBorderMargins = new Margins(oPrevWidgetBorderMargins.marginRight(),
oPrevWidgetBorderMargins.marginBottom(),
oPrevWidgetBorderMargins.marginLeft(),
oPrevWidgetBorderMargins.marginTop());
m_oCapMargins = new Margins(oPrevWidgetCaptionMargins.marginRight(),
oPrevWidgetCaptionMargins.marginBottom(),
oPrevWidgetCaptionMargins.marginLeft(),
oPrevWidgetCaptionMargins.marginTop());
m_oContMargins = new Margins(oPrevWidgetContentMargins.marginRight(),
oPrevWidgetContentMargins.marginBottom(),
oPrevWidgetContentMargins.marginLeft(),
oPrevWidgetContentMargins.marginTop());
// These calc required for rotation.
//Adjust the top left of content extent for text, etc.
oNewLocalContentTL = oPrevContentBR.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedContentTopLeft = oNewLocalContentTL.subtract(oContentOrigin.rotatePoint(oLocalAnchor, oAngle));
//Adjust the top left of caption extent for text, etc.
oNewLocalCaptionTL = oPrevCaptionBR.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedCaptionTopLeft = oNewLocalCaptionTL.subtract(oCaptionOrigin.rotatePoint(oLocalAnchor, oAngle));
}
break;
case 90: {
//1)rotate the 4 corner points 90 degrees about 'm_oAnchorPoint'
//2)adjust new anchor point to new orientation
//3)flip content margins + border margins
//4)for both caption+non caption extents,
// rotate the 4 corner points 180 degrees about 'anchor' point
//oNewBL = oPrevTL.rotatePoint(m_oAnchorPoint, oAngle); //A
oNewTL = oPrevTR.rotatePoint(m_oAnchorPoint, oAngle); //B
oNewTR = oPrevBR.rotatePoint(m_oAnchorPoint, oAngle); //C
oNewBR = oPrevBL.rotatePoint(m_oAnchorPoint, oAngle); //D
// Calculation used to adjust to the local top left
CoordPair oAdjust = oPrevTL.subtract(oNewTL);
// Rotate the local content coordinates around the local origin.
oNewContentBL = oPrevContentTL.rotatePoint(oLocalAnchor, oAngle); //A
oNewContentTL = oPrevContentTR.rotatePoint(oLocalAnchor, oAngle); //B
oNewContentTR = oPrevContentBR.rotatePoint(oLocalAnchor, oAngle); //C
oNewContentBR = oPrevContentBL.rotatePoint(oLocalAnchor, oAngle); //D
oNewContentTR = oNewContentTR.add(oAdjust);
oNewContentBR = oNewContentBR.add(oAdjust);
oNewContentBL = oNewContentBL.add(oAdjust);
oNewContentTL = oNewContentTL.add(oAdjust);
// Rotate the local caption coordinates around the local origin.
oNewCaptionBL = oPrevCaptionTL.rotatePoint(oLocalAnchor, oAngle); //A
oNewCaptionTL = oPrevCaptionTR.rotatePoint(oLocalAnchor, oAngle); //B
oNewCaptionTR = oPrevCaptionBR.rotatePoint(oLocalAnchor, oAngle); //C
oNewCaptionBR = oPrevCaptionBL.rotatePoint(oLocalAnchor, oAngle); //D
oNewCaptionTR = oNewCaptionTR.add(oAdjust);
oNewCaptionBR = oNewCaptionBR.add(oAdjust);
oNewCaptionBL = oNewCaptionBL.add(oAdjust);
oNewCaptionTL = oNewCaptionTL.add(oAdjust);
m_oNEMargins = new Margins(oPrevMargins.marginTop(),
oPrevMargins.marginRight(),
oPrevMargins.marginBottom(),
oPrevMargins.marginLeft());
m_oBorderMargins = new Margins(oPrevBorderMargins.marginTop(),
oPrevBorderMargins.marginRight(),
oPrevBorderMargins.marginBottom(),
oPrevBorderMargins.marginLeft());
m_oContentBorderMargins = new Margins(oPrevWidgetBorderMargins.marginTop(),
oPrevWidgetBorderMargins.marginRight(),
oPrevWidgetBorderMargins.marginBottom(),
oPrevWidgetBorderMargins.marginLeft());
m_oCapMargins = new Margins(oPrevWidgetCaptionMargins.marginTop(),
oPrevWidgetCaptionMargins.marginRight(),
oPrevWidgetCaptionMargins.marginBottom(),
oPrevWidgetCaptionMargins.marginLeft());
m_oContMargins = new Margins(oPrevWidgetContentMargins.marginTop(),
oPrevWidgetContentMargins.marginRight(),
oPrevWidgetContentMargins.marginBottom(),
oPrevWidgetContentMargins.marginLeft());
// These calc required for rotation.
//Adjust the top left of content extent for text, etc.
oNewLocalContentTL = oPrevContentTR.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedContentTopLeft = oNewLocalContentTL.subtract(oContentOrigin.rotatePoint(oLocalAnchor, oAngle));
//Adjust the top left of caption extent for text, etc.
oNewLocalCaptionTL = oPrevCaptionTR.rotatePoint(oLocalAnchor, oAngle);
m_oRotatedCaptionTopLeft = oNewLocalCaptionTL.subtract(oCaptionOrigin.rotatePoint(oLocalAnchor, oAngle));
}
break;
default: {
//Only 90 degree increments are handled
//Todo: log warning message?
assert(false);
m_bWasRotated = false;
return;
}
}
//Record that rotate occurred (splitting will not be allowed)
m_bWasRotated = (0 != lAngle);
//Todo: calculate true anchor
m_oAnchorType = EnumAttr.TOP_LEFT;
m_oAnchorPoint = oNewTL;
//Set the new nominal extent
UnitSpan oNewWidth = oNewTR.x().subtract(oNewTL.x());
UnitSpan oNewHeight = oNewBR.y().subtract(oNewTR.y());
if (oNewWidth.value() < 0)
oNewWidth = oNewWidth.multiply(-1);
if (oNewHeight.value() < 0)
oNewHeight = oNewHeight.multiply(-1);
assert(oNewWidth.gte(UnitSpan.ZERO));
assert(oNewHeight.gte(UnitSpan.ZERO));
m_oNE = m_oNE.width(oNewWidth, false);
m_oNE = m_oNE.height(oNewHeight, false);
//Set the new caption + non-caption extents
m_oCaptionExtent = m_oCaptionExtent.topLeft(oNewCaptionTL);
m_oCaptionExtent = m_oCaptionExtent.bottomRight(oNewCaptionBR);
m_oCaptionExtent = m_oContentExtent.topLeft(oNewContentTL);
m_oCaptionExtent = m_oContentExtent.bottomRight(oNewContentBR);
//Todo: flip min/max widths
assert(! m_oContentExtent.isDegenerate());
}
}
}
}
protected void hasCaption(boolean bHasCaption) {
m_bHasCaption = bHasCaption;
}
protected void checkProxyStatus(Element oNode) {
if (! allowRenderProxy()) {
mbIsProxy = false;
return;
}
if (oNode.isPropertySpecified(XFA.RENDERASTAG, true, 0))
// Initialize from the embedded SVG fragment
initFromSVG(oNode);
// We don't expect to find processing instruction text runs
// if we're laying out a field.
else if (! (oNode instanceof Field))
// Init the content and caption extents based on the text cache PI's.
initFromPI(oNode);
}
protected LayoutEnv m_oGfxLayoutEnv;
protected Rect m_oContentExtent = Rect.ZERO;
protected Rect m_oCaptionExtent = Rect.ZERO;
protected boolean m_bHasCaption;
private boolean mbIsProxy;
// format override
private void initFromPI(Element oNode) {
// Retrieve the specified width/height of this object which is stored
// in a Processing Instruction (PI). They will be used as the boxmodel
// nominal extents.
// Proxies do not support notion of growability. They are fixed sized objects.
assert(oNode != null);
List oPIs = new ArrayList();
oNode.getPI(STRS.BOUNDS, oPIs, true);
// If there's no text run PIs, then we're not using the proxy capability.
mbIsProxy = (oPIs.size() != 0);
if (! mbIsProxy)
return;
StringBuilder sPIValue = new StringBuilder((String) oPIs.get(0));
StringUtils.trim(sPIValue);
StringUtils.trimStart(sPIValue);
StringTokenizer sToker = new StringTokenizer(sPIValue.toString());
// Scratch variables
String sResult = null;
int nResult = 0;
// The processing instruction has the following format
//
// Update the content width
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan moContentW = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Update the content height
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan moContentH = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Update the caption width
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan moCaptionW = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Update the caption height
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan moCaptionH = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Update the rotated content top left
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan oRCTLX = new UnitSpan(UnitSpan.INCHES_72K, nResult);
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan oRCTLY = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Update the rotated caption top left
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan oRCapTLX = new UnitSpan(UnitSpan.INCHES_72K, nResult);
sResult = sToker.nextToken();
nResult = StringUtils.safeNumber(sResult);
UnitSpan oRCapTLY = new UnitSpan(UnitSpan.INCHES_72K, nResult);
// Guard against bad values
if (0 > moContentW.value())
moContentW = UnitSpan.ZERO;
if (0 > moContentH.value())
moContentH = UnitSpan.ZERO;
if (0 > moCaptionW.value())
moCaptionW = UnitSpan.ZERO;
if (0 > moCaptionH.value())
moCaptionH = UnitSpan.ZERO;
m_oContentExtent = m_oContentExtent.topLeft(new CoordPair(oRCTLX, oRCTLY));
m_oContentExtent = m_oContentExtent.width(moContentW, false);
m_oContentExtent = m_oContentExtent.height(moContentH, false);
m_oCaptionExtent = m_oCaptionExtent.topLeft(new CoordPair(oRCapTLX, oRCapTLY));
m_oCaptionExtent = m_oCaptionExtent.width(moCaptionW, false);
m_oCaptionExtent = m_oCaptionExtent.height(moCaptionH, false);
// Set up the nominal extent
initWidthHeight(oNode, false);
}
private void initFromSVG(Element oContainer) {
mbIsProxy = true;
Element renderAs = oContainer.peekElement(XFA.RENDERASTAG, false, 0);
// Todo: some sort of standard error/escape if we hit bad SVG
// In that case we ought to revert to a full re-render.
SVGNode svg = (SVGNode) renderAs.peekElement(SVG.SVGTAG, false, 0);
m_oMinW = svg.getSVGWidth();
m_oMinW = m_oMinW.changeUnits(UnitSpan.INCHES_72K);
m_oMinH = svg.getSVGHeight();
m_oMinH = m_oMinH.changeUnits(UnitSpan.INCHES_72K);
m_oNE = m_oNE.width(m_oMinW, false);
m_oNE = m_oNE.height(m_oMinH, false);
m_oMaxW = m_oMinW;
m_oMaxH = m_oMinH;
int r = 0;
// Update the rotated content top left
UnitSpan oRCTLX = UnitSpan.ZERO;
UnitSpan oRCTLY = UnitSpan.ZERO;
SVGNode content = svg.getRegionGroup(false);
content.parseTransform(oRCTLX, oRCTLY, r);
preProcessGlyphs(content);
UnitSpan oContentW = content.getMeasurement(SVG.WIDTHTAG);
UnitSpan oContentH = content.getMeasurement(SVG.HEIGHTTAG);
// Update the rotated caption top left
UnitSpan oRCapTLX = UnitSpan.ZERO;
UnitSpan oRCapTLY = UnitSpan.ZERO;
UnitSpan oCaptionW = UnitSpan.ZERO;
UnitSpan oCaptionH = UnitSpan.ZERO;
SVGNode caption = svg.getRegionGroup(true);
if (caption == null) {
m_bHasCaption = false;
}
else {
m_bHasCaption = true;
caption.parseTransform(oRCapTLX, oRCapTLY, r);
oCaptionW = caption.getMeasurement(SVG.WIDTHTAG);
oCaptionH = caption.getMeasurement(SVG.HEIGHTTAG);
preProcessGlyphs(caption);
}
// Guard against bad values
if (0 > oContentW.value())
oContentW = UnitSpan.ZERO;
if (0 > oContentH.value())
oContentH = UnitSpan.ZERO;
if (0 > oCaptionW.value())
oCaptionW = UnitSpan.ZERO;
if (0 > oCaptionH.value())
oCaptionH = UnitSpan.ZERO;
m_oContentExtent = m_oContentExtent.topLeft(new CoordPair(oRCTLX, oRCTLY));
m_oContentExtent = m_oContentExtent.width(oContentW, false);
m_oContentExtent = m_oContentExtent.height(oContentH, false);
m_oContentExtent = m_oCaptionExtent.topLeft(new CoordPair(oRCapTLX, oRCapTLY));
m_oContentExtent = m_oCaptionExtent.width(oCaptionW, false);
m_oContentExtent = m_oCaptionExtent.height(oCaptionH, false);
}
private void preProcessGlyphs(Element group) {
for (SVGNode t = (SVGNode)group.getFirstXFAChild(); t != null; t = (SVGNode)t.getNextXFASibling()) {
if (t.getClassTag() != SVG.TEXTTAG)
continue;
String sTextEncoding;
boolean bTextBold = false;
boolean bTextItalic = false;
String sTextTypefaceName =
t.getAttribute(SVG.FONTFAMILYTAG).toString();
Attribute boldState = t.peekAttribute(SVG.FONTWEIGHTTAG);
if (boldState != null) {
bTextBold = (boldState.toString().equals(STRS.BOLD));
}
UnitSpan oTextPointSize = t.getMeasurement(SVG.FONTSIZETAG);
Attribute fontStyle = t.peekAttribute(SVG.FONTSTYLETAG);
if (fontStyle != null)
bTextItalic = (fontStyle.toString().equals(STRS.ITALIC));
sTextEncoding = t.getAttribute(SVG.CODEPAGETAG).toString();
// Create a font info, so that we can reconcile the font and
// get a proper font instance to render the text.
FontInfo oTextFontInfo = new FontInfo(sTextTypefaceName, bTextBold ? FontInfo.WEIGHT_BOLD : FontInfo.WEIGHT_NORMAL, bTextItalic);
//int eTextEncoding = FontService.getEncoding(sTextEncoding);
FontInstance oTextFontInstance =
m_oGfxLayoutEnv.fontService().reconcile(oTextFontInfo, oTextPointSize, 1, 1/*, eEncoding*/);
for (SVGNode tspan = (SVGNode)t.getFirstXFAChild(); tspan != null; tspan = (SVGNode)tspan.getNextXFASibling()) {
int nGlyphs = 0;
if (tspan.getClassTag() != SVG.TSPANTAG && tspan.getClassTag() != SVG.ALTGLYPHTAG)
continue;
// Default typeface name is that of our parent element
String sTypefaceName = sTextTypefaceName;
Attribute typeface = tspan.peekAttribute(SVG.FONTFAMILYTAG);
if (typeface != null)
sTypefaceName = typeface.toString();
// Default Bold state is that of our parent element
boolean bBold = bTextBold;
Attribute bold = tspan.peekAttribute(SVG.FONTWEIGHTTAG);
if (bold != null)
bBold = (bold.toString().equals(STRS.BOLD));
// Default point size is that of our parent element
UnitSpan oPointSize = oTextPointSize;
Attribute pointSize = tspan.peekAttribute(SVG.FONTSIZETAG);
if (pointSize != null)
oPointSize = tspan.getMeasurement(SVG.FONTSIZETAG);
// Default italic state is that of our parent element
boolean bItalic = bTextItalic;
fontStyle = tspan.peekAttribute(SVG.FONTSTYLETAG);
if (fontStyle != null)
bItalic = (fontStyle.toString().equals(STRS.ITALIC));
Attribute encoding = tspan.peekAttribute(SVG.CODEPAGETAG);
String sEncoding = "";
if (encoding != null)
sEncoding = encoding.toString();
FontInstance oFontInstance;
// If no attributes have changed from the parent element,
// then re-use the font instance we retrieved for it.
if (sTypefaceName.equals(sTextTypefaceName)
&& sEncoding.equals(sTextEncoding)
&& bBold == bTextBold
&& bItalic == bTextItalic) {
oFontInstance = oTextFontInstance;
}
else {
// Create a font info, so that we can reconcile the font and
// get a proper font instance to render the text.
FontInfo oFontInfo = new FontInfo(sTypefaceName, bBold ? FontInfo.WEIGHT_BOLD : FontInfo.WEIGHT_NORMAL, bItalic);
//int eEncoding = FontService.getEncoding(sEncoding);
oFontInstance = m_oGfxLayoutEnv.fontService().reconcile(oFontInfo, oPointSize, 1, 1/*, eEncoding*/);
}
//
// Todo: We shouldn't bail if there's no font!
//
if (oFontInstance != null) {
if (tspan.getClassTag() == SVG.ALTGLYPHTAG) {
String sContent = "" /* tspan.getAttribute(SVG.GLYPHREFTAG).toString() */;
nGlyphs = (sContent.length() + 1) / 5;
int[] pnGlyphs = new int[nGlyphs];
String whitespace = ", ";
StringTokenizer sToker = new StringTokenizer(sContent, whitespace);
for (int i = 0; i < nGlyphs; i++) {
String sID = sToker.nextToken();
int nID = StringUtils.safeNumber(sID, 16);
pnGlyphs[i] = nID;
oFontInstance.getFontItem().addSubsettedGlyphs(nID, 0 /*, false */);
}
tspan.storeGlyphs(oFontInstance, pnGlyphs, nGlyphs);
}
else {
SVGTextData text = (SVGTextData) tspan.getProperty(SVG.TEXTDATATAG, 0);
if (text == null)
continue;
String sContent = text.getValue();
for (int i = 0; i < sContent.length(); i++)
oFontInstance.getFontItem().addSubsettedGlyphs(0, (int) sContent.charAt(i)/*, true */);
tspan.storeText(oFontInstance, sContent);
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy