Package flash.swf.builder.types

Source Code of flash.swf.builder.types.FillStyleBuilder

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package flash.swf.builder.types;

import flash.swf.types.FillStyle;
import flash.swf.types.GradRecord;
import flash.swf.types.Matrix;
import flash.swf.types.Gradient;
import flash.swf.tags.DefineBitsLossless;
import flash.swf.builder.tags.DefineBitsLosslessBuilder;
import flash.swf.SwfConstants;
import flash.swf.SwfUtils;
import flash.graphics.images.LosslessImage;

import java.awt.Paint;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.TexturePaint;
import java.awt.Image;
import java.awt.geom.Point2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

import org.apache.flex.forks.batik.ext.awt.LinearGradientPaint;
import org.apache.flex.forks.batik.ext.awt.RadialGradientPaint;

/**
* This class is used to construct a FillStyle from a Paint,
* Rectangle2D, and AffineTransform object.
*
* @author Peter Farland
*/
public final class FillStyleBuilder
{
  private FillStyleBuilder()
  {
  }

  /**
   * Utility method to create an appropriate <code>FillStyle</code> from a <code>Paint</code>.
   * @param paint an AWT <code>Paint</code> instance
   * @param bounds - required for gradient ratio calculation
   * @return a new <code>FillStyle</code> representing the given paint
   */
  public static FillStyle build(Paint paint, Rectangle2D bounds, AffineTransform transform)
  {
    FillStyle fs = null;

    if (paint != null)
    {
      double width = bounds.getWidth();
      double height = bounds.getHeight();

      if (paint instanceof Color)
      {
        fs = new FillStyle(SwfUtils.colorToInt((Color)paint));
      }
      else if (paint instanceof GradientPaint)
      {
        GradientPaint gp = (GradientPaint)paint;
        AffineTransform gt = objectBoundingBoxTransform(transform.transform(gp.getPoint1(), null),
            transform.transform(gp.getPoint2(), null),
            width,
            height,
            width,
            height);
        fs = new FillStyle();
        fs.matrix = MatrixBuilder.build(gt);

        fs.type = FillStyle.FILL_LINEAR_GRADIENT;

                fs.gradient = new Gradient();
                fs.gradient.records = new GradRecord[2];
        fs.gradient.records[0] = new GradRecord(0, SwfUtils.colorToInt(gp.getColor1())); //from left
        fs.gradient.records[1] = new GradRecord(255,  SwfUtils.colorToInt(gp.getColor2())); //to right
      }
      else if (paint instanceof LinearGradientPaint)
      {
        LinearGradientPaint lgp = (LinearGradientPaint)paint;
                Point2D start = lgp.getStartPoint();
        Point2D end = lgp.getEndPoint();

        AffineTransform gt = objectBoundingBoxTransform(start, end, width, height, width, height);

        fs = new FillStyle();
        fs.matrix = MatrixBuilder.build(gt);

        Color[] colors = lgp.getColors();
        float[] ratios = lgp.getFractions();

        if (colors.length == 0 || colors.length != ratios.length) //Invalid fill so we skip
        {
          return null;
        }
        else if (colors.length == 1) //Solid fill
        {
          return new FillStyle(SwfUtils.colorToInt(colors[0]));
        }
        else
        {
          fs.type = FillStyle.FILL_LINEAR_GRADIENT;

          //Maximum of 8 gradient control points records
          int len = ratios.length;
          if (len > 8)
            len = 8;
                    fs.gradient = new Gradient();
                    fs.gradient.records = new GradRecord[len];

          for (int i = 0; i < len; i++)
          {
            fs.gradient.records[i] = new GradRecord((int)Math.rint(255 * ratios[i]), SwfUtils.colorToInt(colors[i]));
          }

        }
      }
      else if (paint instanceof RadialGradientPaint)
      {
        RadialGradientPaint rgp = (RadialGradientPaint)paint;

        //Note: Flash doesn't support the focal point of a radial gradient
        //Point2D cp = rgp.getCenterPoint();
        //Point2D fp = rgp.getFocusPoint();
        double diameter = rgp.getRadius() * 2.0;
        double outerX = diameter * rgp.getTransform().getScaleX();
        double outerY = diameter * rgp.getTransform().getScaleY();

        AffineTransform gt = objectBoundingBoxTransform(null, null, width, height, outerX, outerY);
        fs = new FillStyle();
        fs.matrix = MatrixBuilder.build(gt);

        fs.type = FillStyle.FILL_RADIAL_GRADIENT;

        Color[] colors = rgp.getColors();
        float[] ratios = rgp.getFractions();

                fs.gradient = new Gradient();
                fs.gradient.records = new GradRecord[ratios.length <= 8 ? ratios.length : 8];
        for (int i = 0; i < ratios.length && i < 8; i++)
        {
          fs.gradient.records[i] = new GradRecord((int)Math.rint(255 * ratios[i]), SwfUtils.colorToInt(colors[i]));
        }

      }
      else if (paint instanceof TexturePaint)
      {
        TexturePaint tp = (TexturePaint)paint;
        Image image = tp.getImage();

              LosslessImage losslessImage = new LosslessImage(image);
              int imageWidth = losslessImage.getWidth();
              int imageHeight = losslessImage.getHeight();
              DefineBitsLossless tag = DefineBitsLosslessBuilder.build(losslessImage.getPixels(), imageWidth, imageHeight);

        //Apply Twips Scale of 20 x 20
        AffineTransform at = new AffineTransform();
        at.setToScale(SwfConstants.TWIPS_PER_PIXEL, SwfConstants.TWIPS_PER_PIXEL);
        Matrix matrix = MatrixBuilder.build(at);

        fs = new FillStyle(FillStyle.FILL_BITS, matrix, tag);
      }

    }

    return fs;
  }


  /**
   * TODO: These methods need to be called based on which of two gradient transform methods we're applying.
   * In SVG, these are known as:
   * - userSpaceOnUse - apply gradient transform and use gradient points directly
   * - objectBoundingBox - use the width/height from the target object then apply gradient transform
   */
  private static AffineTransform objectBoundingBoxTransform(Point2D gp1, Point2D gp2, double width, double height, double scaleWidth, double scaleHeight)
  {
    AffineTransform at = new AffineTransform();

    //Translate gradient to the center of the bounded geometry
    at.translate(width / 2, height / 2);

    //Scale to Gradient Square (in twips)
    at.scale((scaleWidth * SwfConstants.TWIPS_PER_PIXEL / SwfConstants.GRADIENT_SQUARE),
        (scaleHeight * SwfConstants.TWIPS_PER_PIXEL / SwfConstants.GRADIENT_SQUARE));

    //Rotate gradient to match geometry
    if (gp1 != null && gp2 != null && (gp2.getX() - gp1.getX()) != 0)
    {
      double mx = gp2.getX() - gp1.getX();
      double my = gp2.getY() - gp1.getY();
      double gradient = my / mx;
      double angle = Math.atan(gradient);

      /*
      Handle the "arctan" problem - get a standard angle so that it is positive within 360 degrees
      wrt the positive x-axis in a counter-clockwise direction
      */
      if (mx < 0)
        angle += Math.PI;
      else if (my < 0)
        angle += (Math.PI * 2.0);

      if (angle != 0)
        at.rotate(angle);
    }

    return at;
  }

  /**
   * TODO: These methods need to be called based on which of two gradient transform methods we're applying.
   * In SVG, these are known as:
   * - userSpaceOnUse - apply gradient transform and use gradient points directly
   * - objectBoundingBox - use the width/height from the target object then apply gradient transform
  private static AffineTransform userSpaceOnUseTransform(Point2D gp1, Point2D gp2, AffineTransform gt)
  {
    double angle = 0.0;

    if (gt != null)
    {
      gp1 = gt.transform(gp1, null);
      gp2 = gt.transform(gp2, null);
    }

    //Rotate gradient to match geometry
    if (gp1 != null && gp2 != null && gp2.getX() - gp1.getX() != 0)
    {
      double mx = gp2.getX() - gp1.getX();
      double my = gp2.getY() - gp1.getY();
      double gradient = my / mx;
      angle = StrictMath.atan(gradient);

      //Handle the "arctan" problem - get a standard angle so that it is a positive value less than
      //360 degrees with respect to the positive x-axis (in a counter-clockwise direction).
      if (mx < 0)
        angle += StrictMath.PI;
      else if (my < 0)
        angle += (StrictMath.PI * 2.0);
    }

    double width = StrictMath.abs(gp2.getX() - gp1.getX());
    double height = StrictMath.abs(gp2.getY() - gp1.getY());

    AffineTransform at = new AffineTransform();

    //Translate gradient to the center of the bounded geometry
    at.translate(width / 2, height / 2);

    //Scale to Gradient Square (in twips)
    at.scale((width * SwfUtils.TWIPS_PER_PIXEL / SwfUtils.GRADIENT_SQUARE),
        (height * SwfUtils.TWIPS_PER_PIXEL / SwfUtils.GRADIENT_SQUARE));

        //Rotate if we have a significant angle
    if (angle != 0.0)
      at.rotate(angle);

    return at;
  }
  */
}
 
TOP

Related Classes of flash.swf.builder.types.FillStyleBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.