blob: b75d068c28b9533bc7be2245b9dc27a737d15a49 [file] [log] [blame]
/*
*
* 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 org.apache.flex.swf.types;
import org.apache.flex.swf.tags.ICharacterReferrer;
import org.apache.flex.swf.tags.ICharacterTag;
import org.apache.flex.swf.tags.CharacterIterableFactory;
/**
* The style change record is also a non-edge record. It can be used to do the
* following:
* <ol>
* <li>Select a fill or line style for drawing.</li>
* <li>Move the current drawing position (without drawing).</li>
* <li>Replace the current fill and line style arrays with a new set of styles.</li>
* </ol>
* <p>
* Because fill and line styles often change at the start of a new path, it is
* useful to perform more than one action in a single record. For example, say a
* {@code DefineShape} tag defines a red circle and a blue square. After the
* circle is closed, it is necessary to move the drawing position, and replace
* the red fill with the blue fill. The style change record can achieve this
* with a single shape record.
* </p>
*/
public class StyleChangeRecord extends ShapeRecord implements ICharacterReferrer
{
public StyleChangeRecord()
{
super(ShapeRecordType.STYLE_CHANGE);
this.stateNewStyles = false;
this.stateLineStyle = false;
this.stateFillStyle0 = false;
this.stateFillStyle1 = false;
this.stateMoveTo = false;
}
private boolean stateNewStyles;
private boolean stateLineStyle;
private boolean stateFillStyle1;
private boolean stateFillStyle0;
private boolean stateMoveTo;
private int moveDeltaX;
private int moveDeltaY;
private IFillStyle fillStyle0;
private IFillStyle fillStyle1;
private ILineStyle lineStyle;
private int numFillBits;
private int numLineBits;
private Styles styles;
/**
* Move the current drawing position (without drawing).
*
* @param x delta x
* @param y delta y
*/
public void setMove(int x, int y)
{
stateMoveTo = true;
moveDeltaX = x;
moveDeltaY = y;
}
/**
* Select styles from parent {@code ShapeWithStyle} record. The
* {@code FillStyle} and {@code LineStyle} objects provided must be defined
* in the parent {@code ShapeWithStyle} record. Otherwise, exception will be
* thrown.
*
* @param fillStyle0 fill0 style
* @param fillStyle1 fill1 style
* @param lineStyle line style
* @throws IllegalArgumentException using styles not defined in the parent
* shape
*/
public void setDefinedStyles(
final IFillStyle fillStyle0,
final IFillStyle fillStyle1,
final ILineStyle lineStyle,
final Styles styleContext)
{
if (fillStyle0 != null && !styleContext.getFillStyles().contains(fillStyle0))
{
throw new IllegalArgumentException("FillStyle0 is not defined in parent shape.");
}
if (fillStyle1 != null && !styleContext.getFillStyles().contains(fillStyle1))
{
throw new IllegalArgumentException("FillStyle1 is not defined in parent shape.");
}
if (lineStyle != null && !styleContext.getLineStyles().contains(lineStyle))
{
throw new IllegalArgumentException("LineStyle is not defined in parent shape.");
}
this.fillStyle0 = fillStyle0;
this.fillStyle1 = fillStyle1;
this.lineStyle = lineStyle;
this.stateFillStyle0 = fillStyle0 != null;
this.stateFillStyle1 = fillStyle1 != null;
this.stateLineStyle = lineStyle != null;
}
/**
* Select styles from parent {@code ShapeWithStyle} record. The
* {@code FillStyle} and {@code LineStyle} objects provided must be defined
* in the parent {@code ShapeWithStyle} record. Otherwise, exception will be
* thrown.
*
* @param fillStyle0 fill0 style
* @param fillStyle1 fill1 style
* @param lineStyle line style
* @throws IllegalArgumentException using styles not defined in the parent
* shape
*/
public void setDefinedStyles(
final IFillStyle fillStyle0,
final IFillStyle fillStyle1,
final ILineStyle lineStyle,
final boolean stateFillStyle0,
final boolean stateFillStyle1,
final boolean stateLineStyle,
final Styles styleContext)
{
this.fillStyle0 = fillStyle0;
this.fillStyle1 = fillStyle1;
this.lineStyle = lineStyle;
this.stateFillStyle0 = stateFillStyle0;
this.stateFillStyle1 = stateFillStyle1;
this.stateLineStyle = stateLineStyle;
}
/**
* Select styles from parent {@code ShapeWithStyle} record. The
* {@code FillStyle} and {@code LineStyle} objects provided must be defined
* in the parent {@code ShapeWithStyle} record. Otherwise, exception will be
* thrown.
*
* @param fillStyle0Index fill0 style
* @param fillStyle1Index fill1 style
* @param lineStyleIndex line style
* @throws IllegalArgumentException using styles not defined in the parent
* shape
*/
public void setDefinedStyles(
final int fillStyle0Index,
final int fillStyle1Index,
final int lineStyleIndex,
final Styles styleContext)
{
if (fillStyle0Index >= 0)
{
if (fillStyle0Index > 0)
{
this.fillStyle0 = styleContext.getFillStyles().get(fillStyle0Index - 1);
}
else
{
this.fillStyle0 = null;
}
stateFillStyle0 = true;
}
if (fillStyle1Index >= 0)
{
if (fillStyle1Index > 0)
{
this.fillStyle1 = styleContext.getFillStyles().get(fillStyle1Index - 1);
}
else
{
this.fillStyle1 = null;
}
stateFillStyle1 = true;
}
if (lineStyleIndex >= 0)
{
if (lineStyleIndex > 0)
{
this.lineStyle = styleContext.getLineStyles().get(lineStyleIndex - 1);
}
else
{
this.lineStyle = null;
}
stateLineStyle = true;
}
}
/**
* Select styles from parent {@code Shape} record for a font. The
* {@code FillStyle} and {@code LineStyle} objects provided must be defined
* in the parent {@code ShapeWithStyle} record. Otherwise, exception will be
* thrown.
*
* @param fillStyle0Index fill0 style
* @param fillStyle1Index fill1 style
* @param lineStyleIndex line style
* @throws IllegalArgumentException using styles not defined in the parent
* shape
*/
public void setDefinedFontStyles(
final int fillStyle0Index,
final int fillStyle1Index,
final int lineStyleIndex,
final Styles styleContext)
{
// there shouldn't be any styles on a shape for fonts, as the
// tag is a Shape, not ShapeWithStyle, but the fillStyle0 can be 1 because
// of the following from the SWF spec:
// "The first STYLECHANGERECORD of each SHAPE in the GlyphShapeTable does not use
// the LineStyle and LineStyles fields. In addition, the first STYLECHANGERECORD of each
// shape must have both fields StateFillStyle0 and FillStyle0 set to 1."
if (fillStyle0Index >= 0)
{
fillStyle0 = null;
stateFillStyle0 = true;
}
if (fillStyle1Index >= 0)
{
fillStyle1 = null;
stateFillStyle1 = true;
}
if (lineStyleIndex >= 0)
{
lineStyle = null;
stateLineStyle = true;
}
}
/**
* clears the styles of this style change record if the respective boolean is set
*
* @param fill0 <code>true</code> to clear fill style 0
* @param fill1 <code>true</code> to clear file style 1
* @param line <code>true</code> to clear line style
*/
public void defaultStyles(boolean fill0, boolean fill1, boolean line)
{
if (fill0)
{
this.fillStyle0 = null;
stateFillStyle0 = true;
}
if (fill1)
{
this.fillStyle1 = null;
stateFillStyle1 = true;
}
if (line)
{
this.lineStyle = null;
stateLineStyle = true;
}
}
/**
* Define new styles and use the new styles.
*/
public void setNewStyles(final Styles value)
{
this.stateNewStyles = true;
this.styles = value;
}
/**
* If true, this {@code StyleChangeRecord} defines new styles, and its
* FillStyle0, FillStyle1, LineStyle points to the new styles.
*
* @return true if the StyleChangeRecord defines new styles.
*/
public boolean isStateNewStyles()
{
return stateNewStyles;
}
/**
* If true, this {@code StyleChangeReocrd} selects a line style.
*
* @return true if the StyleChangeRecord selects a line style.
*/
public boolean isStateLineStyle()
{
return stateLineStyle;
}
/**
* If true, this {@code StyleChangeReocrd} selects a fill style for
* {@code FillStyle1}.
*
* @return true if the StyleChangeRecord selects a fill style for
* {@code FillStyle1}.
*/
public boolean isStateFillStyle1()
{
return stateFillStyle1;
}
/**
* If true, this {@code StyleChangeReocrd} selects a fill style for
* {@code FillStyle0}.
*
* @return true if the StyleChangeRecord selects a fill style for
* {@code FillStyle0}.
*/
public boolean isStateFillStyle0()
{
return stateFillStyle0;
}
/**
* If true, this {@code StyleChangeReocrd} moves the draw position.
*
* @return true if the StyleChangeRecord moves the draw position.
*/
public boolean isStateMoveTo()
{
return stateMoveTo;
}
/**
* Get move delta on X-axis.
*
* @return move delta X.
*/
public int getMoveDeltaX()
{
return moveDeltaX;
}
/**
* Get move delta on Y-axis.
*
* @return move delta Y.
*/
public int getMoveDeltaY()
{
return moveDeltaY;
}
/**
* Get FillStyle0.
*
* @return fill0 style
*/
public IFillStyle getFillstyle0()
{
return fillStyle0;
}
/**
* Get FillStyle1
*
* @return fill1 style
*/
public IFillStyle getFillstyle1()
{
return fillStyle1;
}
/**
* Get LineStyle
*
* @return line style
*/
public ILineStyle getLinestyle()
{
return lineStyle;
}
public Styles getStyles()
{
return styles;
}
/**
* StyleChangeRecord refers to fill styles either from its parent
* ShapeWithStyle's fill styles or from its own private fill styles (when
* stateNewStyle is true).
*/
@Override
public Iterable<ICharacterTag> getReferences()
{
return CharacterIterableFactory.collect(
(stateFillStyle0 && fillStyle0 != null) ? fillStyle0.getReferences() : CharacterIterableFactory.empty(),
(stateFillStyle1 && fillStyle1 != null) ? fillStyle1.getReferences() : CharacterIterableFactory.empty());
}
/**
* Get the numFillBits field read from SWF.
*
* @return the numFillBits
*/
public int getNumFillBits()
{
return numFillBits;
}
/**
* Only SWFReader can set this field.
*
* @param value the numFillBits to set
*/
public void setNumFillBits(int value)
{
this.numFillBits = value;
}
/**
* Get the numLineBits field read from SWF.
*
* @return the numLineBits
*/
public int getNumLineBits()
{
return numLineBits;
}
/**
* Only SWFReader can set this field.
*
* @param value the numLineBits to set
*/
public void setNumLineBits(int value)
{
this.numLineBits = value;
}
}