/* * Copyright (C) 2010-2016 JPEXS, All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.jpexs.decompiler.flash.types; import com.jpexs.decompiler.flash.tags.base.NeedsCharacters; import com.jpexs.decompiler.flash.types.annotations.Conditional; import com.jpexs.decompiler.flash.types.annotations.EnumValue; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.io.Serializable; import java.util.Set; /** * * @author JPEXS */ public class MORPHFILLSTYLE implements NeedsCharacters, Serializable { @SWFType(BasicType.UI8) @EnumValue(value = SOLID, text = "Solid") @EnumValue(value = LINEAR_GRADIENT, text = "Linear gradient") @EnumValue(value = RADIAL_GRADIENT, text = "Radial gradient") @EnumValue(value = FOCAL_RADIAL_GRADIENT, text = "Focal radial gradient", minSwfVersion = 8) @EnumValue(value = REPEATING_BITMAP, text = "Repeating bitmap") @EnumValue(value = CLIPPED_BITMAP, text = "Clipped bitmap") @EnumValue(value = NON_SMOOTHED_REPEATING_BITMAP, text = "Non smoothed repeating bitmap") @EnumValue(value = NON_SMOOTHED_CLIPPED_BITMAP, text = "Non smoothed clipped bitmap") public int fillStyleType; public static final int SOLID = 0x0; public static final int LINEAR_GRADIENT = 0x10; public static final int RADIAL_GRADIENT = 0x12; public static final int FOCAL_RADIAL_GRADIENT = 0x13; public static final int REPEATING_BITMAP = 0x40; public static final int CLIPPED_BITMAP = 0x41; public static final int NON_SMOOTHED_REPEATING_BITMAP = 0x42; public static final int NON_SMOOTHED_CLIPPED_BITMAP = 0x43; @Conditional(value = "fillStyleType", options = {SOLID}) public RGBA startColor; @Conditional(value = "fillStyleType", options = {SOLID}) public RGBA endColor; @Conditional(value = "fillStyleType", options = {LINEAR_GRADIENT, RADIAL_GRADIENT}) public MATRIX startGradientMatrix; @Conditional(value = "fillStyleType", options = {LINEAR_GRADIENT, RADIAL_GRADIENT}) public MATRIX endGradientMatrix; @Conditional(value = "fillStyleType", options = {LINEAR_GRADIENT, RADIAL_GRADIENT}) public MORPHGRADIENT gradient; @Conditional(value = "fillStyleType", options = {CLIPPED_BITMAP, NON_SMOOTHED_REPEATING_BITMAP, NON_SMOOTHED_CLIPPED_BITMAP}) public int bitmapId; @Conditional(value = "fillStyleType", options = {CLIPPED_BITMAP, NON_SMOOTHED_REPEATING_BITMAP, NON_SMOOTHED_CLIPPED_BITMAP}) public MATRIX startBitmapMatrix; @Conditional(value = "fillStyleType", options = {CLIPPED_BITMAP, NON_SMOOTHED_REPEATING_BITMAP, NON_SMOOTHED_CLIPPED_BITMAP}) public MATRIX endBitmapMatrix; @Override public void getNeededCharacters(Set<Integer> needed) { if ((fillStyleType == REPEATING_BITMAP) || (fillStyleType == CLIPPED_BITMAP) || (fillStyleType == NON_SMOOTHED_REPEATING_BITMAP) || (fillStyleType == NON_SMOOTHED_CLIPPED_BITMAP)) { needed.add(bitmapId); } } @Override public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { if (bitmapId == oldCharacterId) { bitmapId = newCharacterId; return true; } return false; } @Override public boolean removeCharacter(int characterId) { if (bitmapId == characterId) { if ((fillStyleType == REPEATING_BITMAP) || (fillStyleType == CLIPPED_BITMAP) || (fillStyleType == NON_SMOOTHED_REPEATING_BITMAP) || (fillStyleType == NON_SMOOTHED_CLIPPED_BITMAP)) { fillStyleType = SOLID; } bitmapId = 0; return true; } return false; } private MATRIX morphMatrix(MATRIX a, MATRIX b, int ratio) { if (a == null) { return null; } if (b == null) { return null; } MATRIX ret = new MATRIX(); double ratio_d = ratio / 65535.0; ret.scaleX = (int) Math.round(a.getScaleX() + (b.getScaleX() - a.getScaleX()) * ratio_d); ret.scaleY = (int) Math.round(a.getScaleY() + (b.getScaleY() - a.getScaleY()) * ratio_d); ret.rotateSkew0 = (int) Math.round(a.getRotateSkew0() + (b.getRotateSkew0() - a.getRotateSkew0()) * ratio_d); ret.rotateSkew1 = (int) Math.round(a.getRotateSkew1() + (b.getRotateSkew1() - a.getRotateSkew1()) * ratio_d); ret.translateX = (int) Math.round(a.translateX + (b.translateX - a.translateX) * ratio_d); ret.translateY = (int) Math.round(a.translateY + (b.translateY - a.translateY) * ratio_d); ret.hasRotate = true; ret.hasScale = true; return ret; } public FILLSTYLE getFillStyleAt(int ratio) { FILLSTYLE ret = new FILLSTYLE(); ret.bitmapId = bitmapId; if (startBitmapMatrix != null) { ret.bitmapMatrix = morphMatrix(startBitmapMatrix, endBitmapMatrix, ratio); } if (startColor != null) { ret.color = MORPHGRADIENT.morphColor(startColor, endColor, ratio); } ret.fillStyleType = fillStyleType; if (gradient != null) { ret.gradient = gradient.getGradientAt(ratio); } if (startGradientMatrix != null) { ret.gradientMatrix = morphMatrix(startGradientMatrix, endGradientMatrix, ratio); } return ret; } public FILLSTYLE getStartFillStyle() { FILLSTYLE ret = new FILLSTYLE(); ret.bitmapId = bitmapId; ret.bitmapMatrix = startBitmapMatrix; ret.color = startColor; ret.fillStyleType = fillStyleType; if (gradient != null) { ret.gradient = gradient.getStartGradient(); } ret.gradientMatrix = startGradientMatrix; return ret; } public FILLSTYLE getEndFillStyle() { FILLSTYLE ret = new FILLSTYLE(); ret.bitmapId = bitmapId; ret.bitmapMatrix = endBitmapMatrix; ret.color = endColor; ret.fillStyleType = fillStyleType; if (gradient != null) { ret.gradient = gradient.getEndGradient(); } ret.gradientMatrix = endGradientMatrix; return ret; } }