Skip to content

Commit

Permalink
Merge pull request deegree#219 from IDgis/3.4-line-placement
Browse files Browse the repository at this point in the history
LinePlacement: 'center' and 'wordWise' extension
  • Loading branch information
MrSnyder committed Apr 25, 2014
2 parents 89cd1c2 + 83babfc commit de2dbb0
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 13 deletions.
Expand Up @@ -125,7 +125,7 @@ public TextStroke( String text, Font font, LinePlacement linePlacement ) {
// I had none that was practical.
// the method returns (true, path) if rendering word wise is possible
// and (false, null) if not
private GeneralPath tryWordWise( Shape shape ) {
private GeneralPath tryWordWise( Shape shape, double initialGap ) {
// two steps: first a list is prepared that describes what to render where
// second the list is rendered

Expand All @@ -146,7 +146,7 @@ private GeneralPath tryWordWise( Shape shape ) {
// end of line tag. Then, the next segment is considered. If repeat is on, the words list will never be empty
// and the loop will run until the segment lengths list is empty.
// TODO: Optimization: do not add Strings, add the GlyphVectors
if ( !prepareWordsToRender( words, wordsToRender, shape, wordsCopy ) ) {
if ( !prepareWordsToRender( words, wordsToRender, shape, wordsCopy, initialGap ) ) {
return null;
}

Expand Down Expand Up @@ -251,10 +251,10 @@ private LinkedList<String> extractWords() {
}

private boolean prepareWordsToRender( LinkedList<String> words, LinkedList<StringOrGap> wordsToRender, Shape shape,
LinkedList<String> wordsCopy ) {
LinkedList<String> wordsCopy, double initialGap ) {
LinkedList<Double> lengths = measurePathLengths( shape );

double currentGap = isZero( linePlacement.initialGap ) ? 0 : linePlacement.initialGap;
double currentGap = isZero( initialGap ) ? 0 : initialGap;
if ( !isZero( currentGap ) ) {
StringOrGap sog = new StringOrGap();
sog.gap = currentGap;
Expand Down Expand Up @@ -441,23 +441,43 @@ private double getShapeLength( Shape shape ) {

public Shape createStrokedShape( Shape shape ) {
GlyphVector glyphVector = font.createGlyphVector( frc, text );
if ( glyphVector.getLogicalBounds().getWidth() > getShapeLength( shape ) ) {

double textWidth = glyphVector.getLogicalBounds().getWidth();
double shapeLength = getShapeLength( shape );

if ( !linePlacement.center ) {
textWidth += linePlacement.initialGap;
}

if ( textWidth > shapeLength ) {
return new GeneralPath();
}

shape = handleUpsideDown( shape );

GeneralPath path = tryWordWise( shape );
if ( path != null ) {
if ( LOG.isDebugEnabled() ) {
LOG.debug( "Rendered text '" + text + "' word wise." );
double initialGap;
if ( linePlacement.center && !linePlacement.repeat ) {
initialGap = shapeLength / 2 - textWidth / 2;
if ( initialGap < linePlacement.initialGap ) {
initialGap = linePlacement.initialGap;
}
} else {
initialGap = linePlacement.initialGap;
}

if ( linePlacement.wordWise ) {
GeneralPath path = tryWordWise( shape, initialGap );
if ( path != null ) {
if ( LOG.isDebugEnabled() ) {
LOG.debug( "Rendered text '" + text + "' word wise." );
}
return path;
}
return path;
}
return renderCharacterWise( shape, glyphVector );
return renderCharacterWise( shape, glyphVector, initialGap );
}

private Shape renderCharacterWise( Shape shape, GlyphVector glyphVector ) {
private Shape renderCharacterWise( Shape shape, GlyphVector glyphVector, double initialGap ) {
GeneralPath result = new GeneralPath();
PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
double points[] = new double[6];
Expand All @@ -480,7 +500,7 @@ private Shape renderCharacterWise( Shape shape, GlyphVector glyphVector ) {
moveY = lastY = points[1];
result.moveTo( moveX, moveY );
state.nextAdvance = glyphVector.getGlyphMetrics( state.currentChar ).getAdvance() * 0.5f;
state.next = state.nextAdvance + linePlacement.initialGap;
state.next = state.nextAdvance + initialGap;
break;

case PathIterator.SEG_CLOSE:
Expand Down
Expand Up @@ -1131,6 +1131,24 @@ public void update( LinePlacement obj, String val ) {
}
}, contn ).second;
}
if ( in.getLocalName().equals( "Center" ) ) {
contn = updateOrContinue( in, "Center", baseOrEvaluated, new Updater<LinePlacement>() {
@Override
public void update( LinePlacement obj, String val ) {
obj.center = Boolean.parseBoolean( val );

}
}, contn ).second;
}
if ( in.getLocalName().equals( "WordWise" ) ) {
contn = updateOrContinue( in, "WordWise", baseOrEvaluated, new Updater<LinePlacement>() {
@Override
public void update( LinePlacement obj, String val ) {
obj.wordWise = Boolean.parseBoolean( val );

}
}, contn ).second;
}
}

return new Pair<LinePlacement, Continuation<LinePlacement>>( baseOrEvaluated, contn );
Expand Down
Expand Up @@ -87,6 +87,16 @@ public class LinePlacement implements Copyable<LinePlacement> {
* Default is false. deegree specific extension.
*/
public boolean preventUpsideDown = false;

/**
* Default is false. deegree specific extension.
*/
public boolean center = false;

/**
* Default is true. deegree specific extension.
*/
public boolean wordWise = true;

@Override
public LinePlacement copy() {
Expand Down
Expand Up @@ -26,6 +26,8 @@
<xsd:extension base="LinePlacementType">
<xsd:sequence>
<xsd:element name="PreventUpsideDown" minOccurs="0" type="xsd:boolean" />
<xsd:element name="Center" minOccurs="0" type="xsd:boolean" />
<xsd:element name="WordWise" minOccurs="0" type="xsd:boolean" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
Expand Down
Expand Up @@ -646,6 +646,37 @@ To enable AutoPlacement, you can simply set the "auto" attribute to "true".
.. tip::
AutoPlacement for labels only works for PointPlacement. AutoPlacement for LinePlacement is not implemented yet.

------------------------
LinePlacement extensions
------------------------

There are additional deegree specific LinePlacement parameters available to enable more sophisticated
text rendering along lines:

+-----------------------+------------+---------+-----------------------------------------------------------------+
| Option | Value | Default | Description |
+=======================+============+=========+=================================================================+
| PreventUpsideDown | Boolean | false | Avoids upside down placement of text |
+-----------------------+------------+---------+-----------------------------------------------------------------+
| Center | Boolean | false | Places the text in the center of the line |
+-----------------------+----------- +---------+-----------------------------------------------------------------+
| WordWise | Boolean | true | Tries to place individual words instead of individual characters|
+-----------------------+------------+---------+-----------------------------------------------------------------+

^^^^^^^
Example
^^^^^^^

.. code-block:: xml
<LinePlacement>
<IsRepeated>false</IsRepeated>
<InitialGap>10</InitialGap>
<PreventUpsideDown>true</PreventUpsideDown>
<Center>true</Center>
<WordWise>false</WordWise>
</LinePlacement>
__________________________
SE & FE Functions
Expand Down

0 comments on commit de2dbb0

Please sign in to comment.