/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

package com.sun.rain.shapes;

import java.nio.*;

public class Shape
{
    static final public int MOVE_TO =  1;
    static final public int LINE_TO =  2;
    static final public int QUAD_TO =  3;
    static final public int CLOSE   =  4;
    
    static final private int BYTES_PER_ENTRY = 4;
    
    public ByteBuffer segments;
    
    private ByteBuffer createBuffer(int size)
    {
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        buffer.order(ByteOrder.nativeOrder());
        buffer.rewind();
        
        return buffer;
    }
    
    private ByteBuffer createBuffer(ByteBuffer src, int size)
    {
        ByteBuffer dst = createBuffer(src.capacity()+size);
        for (int i=0; i<src.capacity(); i++)
        {
            dst.put(src.get());
        }
        
        return dst;
    }
    
    private long ptr; // set by native code
    
    public Shape(float x, float y)
    {
        this.segments = createBuffer(3*BYTES_PER_ENTRY);
        this.segments.putInt(MOVE_TO);
        this.segments.putFloat(x);
        this.segments.putFloat(y);
        this.segments.rewind();
    }
    
    public ByteBuffer compile()
    {
        return this.segments;
    }
    
    public void addLineTo(float x, float y)
    {
        this.segments = createBuffer(this.segments, 3*BYTES_PER_ENTRY);
        this.segments.putInt(LINE_TO);
        this.segments.putFloat(x);
        this.segments.putFloat(y);
        this.segments.rewind();
    }
    
    public void addQuadTo(float cx, float cy, float x, float y)
    {
        this.segments = createBuffer(this.segments, 5*BYTES_PER_ENTRY);
        this.segments.putInt(QUAD_TO);
        this.segments.putFloat(cx);
        this.segments.putFloat(cy);
        this.segments.putFloat(x);
        this.segments.putFloat(y);
        this.segments.rewind();
    }

    static public Shape CreateRoundRect(float width, float height)
    {
        return CreateRoundRect(width, height, height/2.0f);
    }
    static public Shape CreateRoundRect(float width, float height, float arc)
    {
        return CreateRoundRect(width, height, arc, true, true, true, true);
    }
    static public Shape CreateRoundRect(float width, float height, boolean leftBottom, boolean rightBottom, boolean rightTop, boolean leftTop)
    {
        return CreateRoundRect(width, height, height/2.0f, leftBottom, rightBottom, rightTop, leftTop);
    }
    static public Shape CreateRoundRect(float width, float height, float arc, boolean leftBottom, boolean rightBottom, boolean rightTop, boolean leftTop)
    {
        Shape shape = new Shape(0.0f, arc);
        
        if (leftBottom == true)
        {
            shape.addQuadTo(0.0f, 0.0f, arc, 0.0f);
        }
        else
        {
            shape.addLineTo(0.0f, 0.0f);
            shape.addLineTo(arc, 0.0f);
        }
        
        shape.addLineTo(width-arc, 0.0f);
        
        if (rightBottom == true)
        {
            shape.addQuadTo(width, 0.0f, width, arc);
        }
        else
        {
            shape.addLineTo(width, 0.0f);
            shape.addLineTo(width, arc);
        }
        
        shape.addLineTo(width, height-arc);
        
        if (rightTop == true)
        {
            shape.addQuadTo(width, height, width-arc, height);
        }
        else
        {
            shape.addLineTo(width, height);
            shape.addLineTo(width-arc, height);
        }
        
        shape.addLineTo(arc, height);
        
        if (leftTop == true)
        {
            shape.addQuadTo(0.0f, height, 0.0f, height - arc);
        }
        else
        {
            shape.addLineTo(0.0f, height);
            shape.addLineTo(0.0f, height - arc);
        }
        
        shape.addLineTo(0.0f, arc);
        
        return shape;
    }
}
