use of org.cytoscape.view.presentation.property.values.Justification in project cytoscape-impl by cytoscape.
the class DNodeDetails method getLabelJustify.
@Override
public Justification getLabelJustify(final CyNode node, final int labelInx) {
// Check bypass
final DNodeView dnv = dGraphView.getDNodeView(node);
if (dnv.isValueLocked(NODE_LABEL_POSITION)) {
final ObjectPosition lp = dnv.getVisualProperty(NODE_LABEL_POSITION);
final Justification justify = lp.getJustify();
return justify;
}
Justification o = m_labelJustifys.get(node);
if (o == null)
if (m_labelJustifyDefault == null)
return super.getLabelJustify(node, labelInx);
else
return m_labelJustifyDefault;
return o;
}
use of org.cytoscape.view.presentation.property.values.Justification in project cytoscape-impl by cytoscape.
the class GraphRenderer method renderGraph.
/**
* Renders a graph.
* @param netView the network view; nodes in this graph must correspond to
* objKeys in nodePositions (the SpacialIndex2D parameter) and vice versa.
* @param nodePositions defines the positions and extents of nodes in graph;
* each entry (objKey) in this structure must correspond to a node in graph
* (the CyNetwork parameter) and vice versa; the order in which nodes are
* rendered is defined by a non-reversed overlap query on this structure.
* @param lod defines the different levels of detail; an appropriate level
* of detail is chosen based on the results of method calls on this
* object.
* @param nodeDetails defines details of nodes such as colors, node border
* thickness, and shape; the node arguments passed to methods on this
* object will be nodes in the graph parameter.
* @param edgeDetails defines details of edges such as colors, thickness,
* and arrow type; the edge arguments passed to methods on this
* object will be edges in the graph parameter.
* @param nodeBuff this is a computational helper that is required in the
* implementation of this method; when this method returns, nodeBuff is
* in a state such that an edge in graph has been rendered by this method
* if and only if it touches at least one node in this nodeBuff set;
* no guarantee made regarding edgeless nodes.
* @param grafx the graphics context that is to render this graph.
* @param bgPaint the background paint to use when calling grafx.clear().
* @param xCenter the xCenter parameter to use when calling grafx.clear().
* @param yCenter the yCenter parameter to use when calling grafx.clear().
* @param scaleFactor the scaleFactor parameter to use when calling
* grafx.clear().
* @param dependencies
* @return bits representing the level of detail that was rendered; the
* return value is a bitwise-or'ed value of the LOD_* constants.
*/
public static final int renderGraph(final CyNetworkView netView, final SpacialIndex2D nodePositions, final GraphLOD lod, final NodeDetails nodeDetails, final EdgeDetails edgeDetails, final LongHash nodeBuff, final GraphGraphics grafx, final Paint bgPaint, final double xCenter, final double yCenter, final double scaleFactor, final boolean haveZOrder, final Set<VisualPropertyDependency<?>> dependencies) {
// Make sure we keep our promise.
nodeBuff.empty();
if (grafx == null || grafx.image == null)
return 0;
final CyNetwork graph = netView.getModel();
// Define the visible window in node coordinate space.
final float xMin;
// Define the visible window in node coordinate space.
final float yMin;
// Define the visible window in node coordinate space.
final float xMax;
// Define the visible window in node coordinate space.
final float yMax;
xMin = (float) (xCenter - ((0.5d * grafx.image.getWidth(null)) / scaleFactor));
yMin = (float) (yCenter - ((0.5d * grafx.image.getHeight(null)) / scaleFactor));
xMax = (float) (xCenter + ((0.5d * grafx.image.getWidth(null)) / scaleFactor));
yMax = (float) (yCenter + ((0.5d * grafx.image.getHeight(null)) / scaleFactor));
// Define buffers. These are of the few objects we're instantiating
// directly in this method.
final float[] floatBuff1;
// Define buffers. These are of the few objects we're instantiating
// directly in this method.
final float[] floatBuff2;
// Define buffers. These are of the few objects we're instantiating
// directly in this method.
final float[] floatBuff3;
// Define buffers. These are of the few objects we're instantiating
// directly in this method.
final float[] floatBuff4;
// Define buffers. These are of the few objects we're instantiating
// directly in this method.
final float[] floatBuff5;
final double[] doubleBuff1;
final double[] doubleBuff2;
final GeneralPath path2d;
floatBuff1 = new float[4];
floatBuff2 = new float[4];
floatBuff3 = new float[2];
floatBuff4 = new float[2];
floatBuff5 = new float[8];
doubleBuff1 = new double[4];
doubleBuff2 = new double[2];
path2d = new GeneralPath();
// Determine the number of nodes and edges that we are about to render.
final int renderNodeCount;
final int renderEdgeCount;
final byte renderEdges;
long start = System.currentTimeMillis();
{
final SpacialEntry2DEnumerator nodeHits = nodePositions.queryOverlap(xMin, yMin, xMax, yMax, null, 0, false);
final int visibleNodeCount = nodeHits.numRemaining();
final int totalNodeCount = graph.getNodeCount();
final int totalEdgeCount = graph.getEdgeCount();
renderEdges = lod.renderEdges(visibleNodeCount, totalNodeCount, totalEdgeCount);
if (renderEdges > 0) {
int runningNodeCount = 0;
for (int i = 0; i < visibleNodeCount; i++) {
nodeHits.nextExtents(floatBuff1, 0);
if ((floatBuff1[0] != floatBuff1[2]) && (floatBuff1[1] != floatBuff1[3]))
runningNodeCount++;
}
renderNodeCount = runningNodeCount;
renderEdgeCount = totalEdgeCount;
} else if (renderEdges < 0) {
int runningNodeCount = 0;
for (int i = 0; i < visibleNodeCount; i++) {
nodeHits.nextExtents(floatBuff1, 0);
if ((floatBuff1[0] != floatBuff1[2]) && (floatBuff1[1] != floatBuff1[3]))
runningNodeCount++;
}
renderNodeCount = runningNodeCount;
renderEdgeCount = 0;
} else {
int runningNodeCount = 0;
int runningEdgeCount = 0;
for (int i = 0; i < visibleNodeCount; i++) {
final long node = nodeHits.nextExtents(floatBuff1, 0);
if ((floatBuff1[0] != floatBuff1[2]) && (floatBuff1[1] != floatBuff1[3]))
runningNodeCount++;
final Iterable<CyEdge> touchingEdges = graph.getAdjacentEdgeIterable(graph.getNode(node), CyEdge.Type.ANY);
for (CyEdge e : touchingEdges) {
if (!edgeDetails.isVisible(e))
continue;
final long edge = e.getSUID();
final long otherNode = node ^ e.getSource().getSUID() ^ e.getTarget().getSUID();
if (nodeBuff.get(otherNode) < 0)
runningEdgeCount++;
}
nodeBuff.put(node);
}
renderNodeCount = runningNodeCount;
renderEdgeCount = runningEdgeCount;
nodeBuff.empty();
}
}
// System.out.println("renderEdgeCount: "+renderEdgeCount);
// System.out.println("time: "+(System.currentTimeMillis()-start)+"ms");
// Based on number of objects we are going to render, determine LOD.
final int lodBits;
{
int lodTemp = 0;
if (lod.detail(renderNodeCount, renderEdgeCount)) {
lodTemp |= LOD_HIGH_DETAIL;
if (lod.nodeBorders(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_NODE_BORDERS;
if (lod.nodeLabels(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_NODE_LABELS;
if (lod.edgeArrows(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_EDGE_ARROWS;
if (lod.dashedEdges(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_DASHED_EDGES;
if (lod.edgeAnchors(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_EDGE_ANCHORS;
if (lod.edgeLabels(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_EDGE_LABELS;
if ((((lodTemp & LOD_NODE_LABELS) != 0) || ((lodTemp & LOD_EDGE_LABELS) != 0)) && lod.textAsShape(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_TEXT_AS_SHAPE;
if (lod.customGraphics(renderNodeCount, renderEdgeCount))
lodTemp |= LOD_CUSTOM_GRAPHICS;
}
lodBits = lodTemp;
}
// Clear the background.
{
if (bgPaint != null)
grafx.clear(bgPaint, xCenter, yCenter, scaleFactor);
}
// on top of the edge it belongs to.
if (renderEdges >= 0) {
final SpacialEntry2DEnumerator nodeHits;
if (renderEdges > 0)
// We want to render edges in the same order (back to front) that
// we would use to render just edges on visible nodes; this is assuming
// that our spacial index has the subquery order-preserving property.
nodeHits = nodePositions.queryOverlap(Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, null, 0, false);
else
nodeHits = nodePositions.queryOverlap(xMin, yMin, xMax, yMax, null, 0, false);
if ((lodBits & LOD_HIGH_DETAIL) == 0) {
// Low detail.
final int nodeHitCount = nodeHits.numRemaining();
for (int i = 0; i < nodeHitCount; i++) {
final long node = nodeHits.nextExtents(floatBuff1, 0);
// Casting to double and then back we could achieve better accuracy
// at the expense of performance.
final float nodeX = (floatBuff1[0] + floatBuff1[2]) / 2;
final float nodeY = (floatBuff1[1] + floatBuff1[3]) / 2;
Iterable<CyEdge> touchingEdges = graph.getAdjacentEdgeIterable(graph.getNode(node), CyEdge.Type.ANY);
for (CyEdge edge : touchingEdges) {
if (!edgeDetails.isVisible(edge))
continue;
final long otherNode = node ^ edge.getSource().getSUID() ^ edge.getTarget().getSUID();
if (nodeBuff.get(otherNode) < 0) {
// Has not yet been rendered.
nodePositions.exists(otherNode, floatBuff2, 0);
grafx.drawEdgeLow(nodeX, nodeY, // accuracy and performance.
(floatBuff2[0] + floatBuff2[2]) / 2, (floatBuff2[1] + floatBuff2[3]) / 2, edgeDetails.getColorLowDetail(edge));
}
}
nodeBuff.put(node);
}
} else {
// High detail.
while (nodeHits.numRemaining() > 0) {
final long node = nodeHits.nextExtents(floatBuff1, 0);
final CyNode cyNode = graph.getNode(node);
final byte nodeShape = nodeDetails.getShape(cyNode);
Iterable<CyEdge> touchingEdges = graph.getAdjacentEdgeIterable(cyNode, CyEdge.Type.ANY);
for (final CyEdge edge : touchingEdges) {
if (!edgeDetails.isVisible(edge))
continue;
final long otherNode = node ^ edge.getSource().getSUID() ^ edge.getTarget().getSUID();
final CyNode otherCyNode = graph.getNode(otherNode);
if (nodeBuff.get(otherNode) < 0) {
if (!nodePositions.exists(otherNode, floatBuff2, 0))
continue;
// throw new IllegalStateException("nodePositions not recognizing node that exists in graph: "+otherCyNode.toString());
final byte otherNodeShape = nodeDetails.getShape(otherCyNode);
// Compute node shapes, center positions, and extents.
final byte srcShape;
// Compute node shapes, center positions, and extents.
final byte trgShape;
final float[] srcExtents;
final float[] trgExtents;
if (node == edge.getSource().getSUID()) {
srcShape = nodeShape;
trgShape = otherNodeShape;
srcExtents = floatBuff1;
trgExtents = floatBuff2;
} else {
// node == graph.edgeTarget(edge).
srcShape = otherNodeShape;
trgShape = nodeShape;
srcExtents = floatBuff2;
trgExtents = floatBuff1;
}
// Compute visual attributes that do not depend on LOD.
final float thickness = edgeDetails.getWidth(edge);
final Stroke edgeStroke = edgeDetails.getStroke(edge);
final Paint segPaint = edgeDetails.getPaint(edge);
// Compute arrows.
final ArrowShape srcArrow;
final ArrowShape trgArrow;
final float srcArrowSize;
final float trgArrowSize;
final Paint srcArrowPaint;
final Paint trgArrowPaint;
if ((lodBits & LOD_EDGE_ARROWS) == 0) {
// Not rendering arrows.
trgArrow = srcArrow = ArrowShapeVisualProperty.NONE;
trgArrowSize = srcArrowSize = 0.0f;
trgArrowPaint = srcArrowPaint = null;
} else {
// Rendering edge arrows.
srcArrow = edgeDetails.getSourceArrowShape(edge);
trgArrow = edgeDetails.getTargetArrowShape(edge);
srcArrowSize = ((srcArrow == ArrowShapeVisualProperty.NONE) ? 0.0f : edgeDetails.getSourceArrowSize(edge));
trgArrowSize = ((trgArrow == ArrowShapeVisualProperty.NONE) ? 0.0f : edgeDetails.getTargetArrowSize(edge));
srcArrowPaint = ((srcArrow == ArrowShapeVisualProperty.NONE) ? null : edgeDetails.getSourceArrowPaint(edge));
trgArrowPaint = ((trgArrow == ArrowShapeVisualProperty.NONE) ? null : edgeDetails.getTargetArrowPaint(edge));
}
// Compute the anchors to use when rendering edge.
final EdgeAnchors anchors = (((lodBits & LOD_EDGE_ANCHORS) == 0) ? null : edgeDetails.getAnchors(edge));
if (!computeEdgeEndpoints(grafx, srcExtents, srcShape, srcArrow, srcArrowSize, anchors, trgExtents, trgShape, trgArrow, trgArrowSize, floatBuff3, floatBuff4))
continue;
final float srcXAdj = floatBuff3[0];
final float srcYAdj = floatBuff3[1];
final float trgXAdj = floatBuff4[0];
final float trgYAdj = floatBuff4[1];
grafx.drawEdgeFull(srcArrow, srcArrowSize, srcArrowPaint, trgArrow, trgArrowSize, trgArrowPaint, srcXAdj, srcYAdj, anchors, trgXAdj, trgYAdj, thickness, edgeStroke, segPaint);
// Take care of edge anchor rendering.
if (anchors != null) {
for (int k = 0; k < anchors.numAnchors(); k++) {
final float anchorSize;
if ((anchorSize = edgeDetails.getAnchorSize(edge, k)) > 0.0f) {
anchors.getAnchor(k, floatBuff4, 0);
grafx.drawNodeFull(GraphGraphics.SHAPE_RECTANGLE, (float) (floatBuff4[0] - (anchorSize / 2.0d)), (float) (floatBuff4[1] - (anchorSize / 2.0d)), (float) (floatBuff4[0] + (anchorSize / 2.0d)), (float) (floatBuff4[1] + (anchorSize / 2.0d)), edgeDetails.getAnchorPaint(edge, k), 0.0f, null, null);
}
}
}
// Take care of label rendering.
if ((lodBits & LOD_EDGE_LABELS) != 0) {
final int labelCount = edgeDetails.getLabelCount(edge);
for (int labelInx = 0; labelInx < labelCount; labelInx++) {
final String text = edgeDetails.getLabelText(edge, labelInx);
final Font font = edgeDetails.getLabelFont(edge, labelInx);
final double fontScaleFactor = edgeDetails.getLabelScaleFactor(edge, labelInx);
final Paint paint = edgeDetails.getLabelPaint(edge, labelInx);
final Position textAnchor = edgeDetails.getLabelTextAnchor(edge, labelInx);
final Position edgeAnchor = edgeDetails.getLabelEdgeAnchor(edge, labelInx);
final float offsetVectorX = edgeDetails.getLabelOffsetVectorX(edge, labelInx);
final float offsetVectorY = edgeDetails.getLabelOffsetVectorY(edge, labelInx);
final Justification justify;
if (text.indexOf('\n') >= 0)
justify = edgeDetails.getLabelJustify(edge, labelInx);
else
justify = Justification.JUSTIFY_CENTER;
final double edgeAnchorPointX;
final double edgeAnchorPointY;
final double edgeLabelWidth = edgeDetails.getLabelWidth(edge);
// in any case.
if (edgeAnchor == Position.WEST) {
edgeAnchorPointX = srcXAdj;
edgeAnchorPointY = srcYAdj;
} else if (edgeAnchor == Position.EAST) {
edgeAnchorPointX = trgXAdj;
edgeAnchorPointY = trgYAdj;
} else if (edgeAnchor == Position.CENTER) {
if (!grafx.getEdgePath(srcArrow, srcArrowSize, trgArrow, trgArrowSize, srcXAdj, srcYAdj, anchors, trgXAdj, trgYAdj, path2d)) {
continue;
}
// Count the number of path segments. This count
// includes the initial SEG_MOVETO. So, for example, a
// path composed of 2 cubic curves would have a numPaths
// of 3. Note that numPaths will be at least 2 in all
// cases.
final int numPaths;
{
final PathIterator pathIter = path2d.getPathIterator(null);
int numPathsTemp = 0;
while (!pathIter.isDone()) {
// pathIter.currentSegment().
numPathsTemp++;
pathIter.next();
}
numPaths = numPathsTemp;
}
// Compute "midpoint" of edge.
if ((numPaths % 2) != 0) {
final PathIterator pathIter = path2d.getPathIterator(null);
for (int i = numPaths / 2; i > 0; i--) pathIter.next();
final int subPathType = pathIter.currentSegment(floatBuff5);
if (subPathType == PathIterator.SEG_LINETO) {
edgeAnchorPointX = floatBuff5[0];
edgeAnchorPointY = floatBuff5[1];
} else if (subPathType == PathIterator.SEG_QUADTO) {
edgeAnchorPointX = floatBuff5[2];
edgeAnchorPointY = floatBuff5[3];
} else if (subPathType == PathIterator.SEG_CUBICTO) {
edgeAnchorPointX = floatBuff5[4];
edgeAnchorPointY = floatBuff5[5];
} else
throw new IllegalStateException("got unexpected PathIterator segment type: " + subPathType);
} else {
// numPaths % 2 == 0.
final PathIterator pathIter = path2d.getPathIterator(null);
for (int i = numPaths / 2; i > 0; i--) {
if (i == 1) {
final int subPathType = pathIter.currentSegment(floatBuff5);
if ((subPathType == PathIterator.SEG_MOVETO) || (subPathType == PathIterator.SEG_LINETO)) {
floatBuff5[6] = floatBuff5[0];
floatBuff5[7] = floatBuff5[1];
} else if (subPathType == PathIterator.SEG_QUADTO) {
floatBuff5[6] = floatBuff5[2];
floatBuff5[7] = floatBuff5[3];
} else if (subPathType == PathIterator.SEG_CUBICTO) {
floatBuff5[6] = floatBuff5[4];
floatBuff5[7] = floatBuff5[5];
} else
throw new IllegalStateException("got unexpected PathIterator segment type: " + subPathType);
}
pathIter.next();
}
final int subPathType = pathIter.currentSegment(floatBuff5);
if (subPathType == PathIterator.SEG_LINETO) {
edgeAnchorPointX = (0.5d * floatBuff5[6]) + (0.5d * floatBuff5[0]);
edgeAnchorPointY = (0.5d * floatBuff5[7]) + (0.5d * floatBuff5[1]);
} else if (subPathType == PathIterator.SEG_QUADTO) {
edgeAnchorPointX = (0.25d * floatBuff5[6]) + (0.5d * floatBuff5[0]) + (0.25d * floatBuff5[2]);
edgeAnchorPointY = (0.25d * floatBuff5[7]) + (0.5d * floatBuff5[1]) + (0.25d * floatBuff5[3]);
} else if (subPathType == PathIterator.SEG_CUBICTO) {
edgeAnchorPointX = (0.125d * floatBuff5[6]) + (0.375d * floatBuff5[0]) + (0.375d * floatBuff5[2]) + (0.125d * floatBuff5[4]);
edgeAnchorPointY = (0.125d * floatBuff5[7]) + (0.375d * floatBuff5[1]) + (0.375d * floatBuff5[3]) + (0.125d * floatBuff5[5]);
} else
throw new IllegalStateException("got unexpected PathIterator segment type: " + subPathType);
}
} else
throw new IllegalStateException("encountered an invalid EDGE_ANCHOR_* constant: " + edgeAnchor);
final MeasuredLineCreator measuredText = new MeasuredLineCreator(text, font, grafx.getFontRenderContextFull(), fontScaleFactor, (lodBits & LOD_TEXT_AS_SHAPE) != 0, edgeLabelWidth);
doubleBuff1[0] = -0.5d * measuredText.getMaxLineWidth();
doubleBuff1[1] = -0.5d * measuredText.getTotalHeight();
doubleBuff1[2] = 0.5d * measuredText.getMaxLineWidth();
doubleBuff1[3] = 0.5d * measuredText.getTotalHeight();
lemma_computeAnchor(textAnchor, doubleBuff1, doubleBuff2);
final double textXCenter = edgeAnchorPointX - doubleBuff2[0] + offsetVectorX;
final double textYCenter = edgeAnchorPointY - doubleBuff2[1] + offsetVectorY;
TextRenderingUtils.renderHorizontalText(grafx, measuredText, font, fontScaleFactor, (float) textXCenter, (float) textYCenter, justify, paint, (lodBits & LOD_TEXT_AS_SHAPE) != 0);
}
}
}
}
nodeBuff.put(node);
}
}
}
// Render nodes and labels. A label is not necessarily on top of every
// node; it is only on top of the node it belongs to.
{
final SpacialEntry2DEnumerator nodeHits = nodePositions.queryOverlap(xMin, yMin, xMax, yMax, null, 0, false);
if ((lodBits & LOD_HIGH_DETAIL) == 0) {
// Low detail.
final int nodeHitCount = nodeHits.numRemaining();
for (int i = 0; i < nodeHitCount; i++) {
final CyNode node = graph.getNode(nodeHits.nextExtents(floatBuff1, 0));
if ((floatBuff1[0] != floatBuff1[2]) && (floatBuff1[1] != floatBuff1[3]))
grafx.drawNodeLow(floatBuff1[0], floatBuff1[1], floatBuff1[2], floatBuff1[3], nodeDetails.getColorLowDetail(node));
}
} else {
// High detail.
SpacialEntry2DEnumerator zHits = nodeHits;
if (haveZOrder) {
zHits = new SpacialEntry2DEnumeratorZSort(nodePositions, nodeHits);
}
while (zHits.numRemaining() > 0) {
final long node = zHits.nextExtents(floatBuff1, 0);
final CyNode cyNode = graph.getNode(node);
renderNodeHigh(netView, grafx, cyNode, floatBuff1, doubleBuff1, doubleBuff2, nodeDetails, lodBits, dependencies);
// Take care of label rendering.
if ((lodBits & LOD_NODE_LABELS) != 0) {
// Potential label rendering.
final int labelCount = nodeDetails.getLabelCount(cyNode);
for (int labelInx = 0; labelInx < labelCount; labelInx++) {
final String text = nodeDetails.getLabelText(cyNode, labelInx);
final Font font = nodeDetails.getLabelFont(cyNode, labelInx);
final double fontScaleFactor = nodeDetails.labelScaleFactor(cyNode, labelInx);
final Paint paint = nodeDetails.getLabelPaint(cyNode, labelInx);
final Position textAnchor = nodeDetails.getLabelTextAnchor(cyNode, labelInx);
final Position nodeAnchor = nodeDetails.getLabelNodeAnchor(cyNode, labelInx);
final float offsetVectorX = nodeDetails.getLabelOffsetVectorX(cyNode, labelInx);
final float offsetVectorY = nodeDetails.getLabelOffsetVectorY(cyNode, labelInx);
final Justification justify;
if (text.indexOf('\n') >= 0)
justify = nodeDetails.getLabelJustify(cyNode, labelInx);
else
justify = Justification.JUSTIFY_CENTER;
final double nodeLabelWidth = nodeDetails.getLabelWidth(cyNode);
doubleBuff1[0] = floatBuff1[0];
doubleBuff1[1] = floatBuff1[1];
doubleBuff1[2] = floatBuff1[2];
doubleBuff1[3] = floatBuff1[3];
lemma_computeAnchor(nodeAnchor, doubleBuff1, doubleBuff2);
final double nodeAnchorPointX = doubleBuff2[0];
final double nodeAnchorPointY = doubleBuff2[1];
final MeasuredLineCreator measuredText = new MeasuredLineCreator(text, font, grafx.getFontRenderContextFull(), fontScaleFactor, (lodBits & LOD_TEXT_AS_SHAPE) != 0, nodeLabelWidth);
doubleBuff1[0] = -0.5d * measuredText.getMaxLineWidth();
doubleBuff1[1] = -0.5d * measuredText.getTotalHeight();
doubleBuff1[2] = 0.5d * measuredText.getMaxLineWidth();
doubleBuff1[3] = 0.5d * measuredText.getTotalHeight();
lemma_computeAnchor(textAnchor, doubleBuff1, doubleBuff2);
final double textXCenter = nodeAnchorPointX - doubleBuff2[0] + offsetVectorX;
final double textYCenter = nodeAnchorPointY - doubleBuff2[1] + offsetVectorY;
TextRenderingUtils.renderHorizontalText(grafx, measuredText, font, fontScaleFactor, (float) textXCenter, (float) textYCenter, justify, paint, (lodBits & LOD_TEXT_AS_SHAPE) != 0);
}
}
}
}
}
// System.out.println("total time: "+(System.currentTimeMillis()-start)+"ms");
return lodBits;
}
Aggregations