FileDocCategorySizeDatePackage
GlyphLayout.javaAPI DocphoneME MR2 API (J2ME)12257Wed May 02 18:00:36 BST 2007com.sun.perseus.model

GlyphLayout

public class GlyphLayout extends Object
GlyphLayout is used to represent successing text 'chunks' in a Text layout of glyphs. The notion of 'chunk' is that of the SVG specification.
version
$Id: GlyphLayout.java,v 1.4 2006/06/29 10:47:31 ln156897 Exp $

Fields Summary
protected float
advance
The overally layout's advance
protected float
x
The chunk's x-axis position
protected float
y
The chunk's y-axis position
protected GlyphProxy
firstChild
The first child
protected GlyphProxy
lastChild
The last child
protected GlyphLayout
prevSibling
Previous sibling.
protected GlyphLayout
nextSibling
Next sibling
protected DocumentNode
ownerDocument
Owner Document, to get cache objects.
protected float[]
helperDashArray
Used to scale dash array values.
Constructors Summary
GlyphLayout(DocumentNode doc)

param
doc the DocumentNode scope.

        this.ownerDocument = doc;
    
Methods Summary
public voidadd(GlyphProxy proxy)
Appends an element at the end of the list

param
proxy the proxy to add to this GlyphLayout
throws
NullPointerException if the input argument is null.

        if (proxy == null) {
            throw new NullPointerException();
        }
            
        if (firstChild == null) {
            firstChild = proxy;
            lastChild = proxy;
            proxy.nextSibling = null;
            proxy.prevSibling = null;
        } else {
            lastChild.nextSibling = proxy;
            proxy.nextSibling = null;
            proxy.prevSibling = lastChild;
            lastChild = proxy;                
        }
    
com.sun.perseus.j2d.BoxaddBBox(com.sun.perseus.j2d.Box bbox, com.sun.perseus.j2d.Transform t)

param
bbox the bounding box to which this node's bounding box should be appended. That bounding box is in the target coordinate space. It may be null, in which case this node should create a new one.
param
t the transform from the node coordinate system to the coordinate system into which the bounds should be computed.
return
the bounding box of this node, in the target coordinate space,

        GlyphProxy gp = firstChild;
        while (gp != null) {
            ownerDocument.bboxGlyphTxf.setTransform(t);
            gp.applyTransform(ownerDocument.bboxGlyphTxf);
            bbox = gp.addNodeBBox(bbox, ownerDocument.bboxGlyphTxf);
            gp = gp.nextSibling;
        }
        return bbox;
    
protected final com.sun.perseus.j2d.TileaddRenderingTile(com.sun.perseus.j2d.Tile tile, com.sun.perseus.j2d.TextRenderingProperties trp, com.sun.perseus.j2d.Transform t)
Add this GlyphLayout rendering tile to the input Tile.

param
tile the Tile instance whose bounds should be expanded. May be null.
param
trp the TextRenderingProperties describing the nodes rendering characteristics.
param
t the Transform to the requested tile space, from this node's user space.
return
the expanded tile.

        if (trp.getStroke() != null) {
            GlyphProxy gp = firstChild;
            while (gp != null) {
                ownerDocument.bboxGlyphTxf.setTransform(t);
                gp.applyTransform(ownerDocument.bboxGlyphTxf);
                tile = gp.addRenderingTile(tile, trp, t);
                gp = (GlyphProxy) gp.nextSibling;
            }
        } else {
            GlyphProxy gp = firstChild;
            float strokeWidth = trp.getStrokeWidth();
            while (gp != null) {
                ownerDocument.bboxGlyphTxf.setTransform(t);
                gp.applyTransform(ownerDocument.bboxGlyphTxf);
                trp.setStrokeWidth(strokeWidth / gp.proxied.emSquareScale);
                tile = gp.addRenderingTile(tile, trp, t);
                gp = (GlyphProxy) gp.nextSibling;
            }
        }
        return tile;
    
protected voidapplyInverseTransform(com.sun.perseus.j2d.TextRenderingProperties trp, com.sun.perseus.j2d.Transform tx)
Applies the inverse of the chunk's position adjustment due to the text anchor's value.

param
trp the TextRenderingProperties on which the font-size property is defined.
param
tx the Transform to apply the inverse transform to.

        // Account for the text-anchor translation
        switch (trp.getTextAnchor()) {
        default:
            break;
        case TextNode.TEXT_ANCHOR_MIDDLE:
            tx.mTranslate(advance / 2f, 0);
            break;
        case TextNode.TEXT_ANCHOR_END:
            tx.mTranslate(advance, 0);
            break;
        }

        // Scale according to the fontSize
        float fontSize = trp.getFontSize();
        if (fontSize > 0) {
            tx.mScale(1 / fontSize);
        }

        // Position the text chunk on the current 
        // text position.
        tx.mTranslate(-x, -y);
    
protected voidapplyTransform(com.sun.perseus.j2d.TextRenderingProperties trp, com.sun.perseus.j2d.Transform tx)
Applies the chunk's position adjustment due to the text anchor's value.

param
trp the TextRenderingProperties on which the font-size property is defined.
param
tx the Transform to apply additional node transforms to. This is guaranteed to no be null.

        // Position the text chunk on the current 
        // text position.
        tx.mTranslate(x, y);

        // Scale according to the fontSize
        float fontSize = trp.getFontSize();
        if (fontSize > 0) {
            tx.mScale(fontSize);
        }

        // Account for the text-anchor translation
        switch (trp.getTextAnchor()) {
        default:
            break;
        case TextNode.TEXT_ANCHOR_MIDDLE:
            tx.mTranslate(-advance / 2f, 0);
            break;
        case TextNode.TEXT_ANCHOR_END:
            tx.mTranslate(-advance, 0);
            break;
        }
    
voiddrawText(com.sun.perseus.j2d.RenderGraphics rg, com.sun.perseus.j2d.Transform tx)
Draws text.

param
rg the RenderGraphics where the node should paint itself.
param
tx the rendering transform.

        GlyphProxy c = firstChild;
        float strokeWidth = rg.getStrokeWidth();
        float dashOffset = rg.getStrokeDashOffset();
        float[] dashArray = rg.getStrokeDashArray();
        if ((dashArray != null) && 
                ((helperDashArray == null) || 
                 (helperDashArray.length != dashArray.length))) {
            helperDashArray = new float[dashArray.length];
        }
        float lastEMSquareScale = 0;
        while (c != null) {
            ownerDocument.paintGlyphTxf.setTransform(tx);
            c.applyTransform(ownerDocument.paintGlyphTxf);
            rg.setTransform(ownerDocument.paintGlyphTxf);
            if (lastEMSquareScale != c.proxied.emSquareScale) {
                rg.setStrokeWidth(strokeWidth / c.proxied.emSquareScale);
                if (dashArray != null) {
                    float emSquareScale = c.proxied.emSquareScale;
                    float lengthSum = 0;
                    for (int i = 0; i < dashArray.length; ++i) {
                        helperDashArray[i] = dashArray[i] / emSquareScale;
                        lengthSum += dashArray[i];
                    }
                    float reducedDashOffset = dashOffset;
                    if (lengthSum > 0) {
                        int r = (int)(dashOffset / lengthSum);
                        reducedDashOffset -= r * lengthSum;
                    }
                    rg.setStrokeDashArray(helperDashArray);
                    rg.setStrokeDashOffset(reducedDashOffset / emSquareScale);
                }
                lastEMSquareScale = c.proxied.emSquareScale;
            }
            
            if (c.proxied.d != null) {
                rg.draw(c.proxied.d);
            }
            c = c.nextSibling;
        }
            
        // Restore stroke-width property.
        rg.setStrokeWidth(strokeWidth);
        
        if (dashArray != null) {
            // Restore dash array & offset
            rg.setStrokeDashArray(dashArray);
            rg.setStrokeDashOffset(dashOffset);
        }
    
voidfillText(com.sun.perseus.j2d.RenderGraphics rg, com.sun.perseus.j2d.Transform tx)
Fills text.

param
rg the RenderGraphics where the node should paint itself.
param
tx the rendering transform.

        GlyphProxy c = firstChild;            
        while (c != null) {
            ownerDocument.paintGlyphTxf.setTransform(tx);
            c.applyTransform(ownerDocument.paintGlyphTxf);
            rg.setTransform(ownerDocument.paintGlyphTxf);
            if (c.proxied.d != null) {
                rg.fill(c.proxied.d);
            }
            c = c.nextSibling;
        }
    
protected booleanisHitVP(float[] pt, com.sun.perseus.j2d.TextRenderingProperties trp, com.sun.perseus.j2d.Transform chunkTxf)
Returns true if this node is hit by the input point. The input point is in viewport space. By default, a node is not hit, not matter what the input coordinate is.

param
pt the x/y coordinate. Should never be null and be of size two. If not, the behavior is unspecified. The x/y coordinate is in the node's user space.
param
trp the TextRenderingProperties containing the properties applicable to the hit detection operation. This is used because the same node may be referenced multiple times by different proxies.
return
true if the node is hit by the input point.
see
#nodeHitAt

        GlyphProxy c = lastChild;            
        while (c != null) {
            ownerDocument.hitGlyphTxf.setTransform(1, 0, 0, 1, 0, 0);
            c.applyInverseTransform(ownerDocument.hitGlyphTxf);
            ownerDocument.hitGlyphTxf.mMultiply(chunkTxf);
            ownerDocument.hitGlyphTxf.transformPoint(pt, ownerDocument.upt);
            if (c.isHit(ownerDocument.upt, trp)) {
                return true;
            }
            c = c.prevSibling;
        }

        return false;
    
public java.lang.StringtoString()

return
the string description of this layout.

        return "GlyphLayout[x=" + x + ", y=" + y 
            + " advance=" + advance + "]";