UNPKG

@awayjs/graphics

Version:
205 lines (189 loc) 6.11 kB
import { IMaterial, IMaterialFactory } from '@awayjs/renderer'; import { BitmapImage2D, Image2D } from '@awayjs/stage'; import { FillType } from '../data/FillType'; import { SegmentedPath } from '../data/SegmentedPath'; import { ShapeMatrix } from '../data/ShapeData'; import { ShapeStyle } from './ShapeStyle'; const IDENTITY_MATRIX: ShapeMatrix = { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }; export class StyleUtils { public static processStyle(style: any, isLineStyle: boolean, isMorph: boolean, factory: IMaterialFactory): ShapeStyle { const shapeStyle: ShapeStyle = style; if (isMorph) { shapeStyle.morph = this.processMorphStyle(style, isLineStyle); } if (isLineStyle) { shapeStyle.miterLimit = (style.miterLimitFactor || 1.5) * 2; if (!style.color && style.hasFill) { const fillStyle = this.processStyle(style.fillStyle, false, false, factory); shapeStyle.type = fillStyle.type; shapeStyle.transform = fillStyle.transform; shapeStyle.colors = fillStyle.colors; shapeStyle.ratios = fillStyle.ratios; shapeStyle.focalPoint = fillStyle.focalPoint; shapeStyle.bitmapId = fillStyle.bitmapId; shapeStyle.material = fillStyle.material; shapeStyle.repeat = fillStyle.repeat; style.fillStyle = null; return shapeStyle; } else { shapeStyle.type = FillType.Solid; return shapeStyle; } } if (style.type === undefined || style.type === FillType.Solid) { return shapeStyle; } let scale: number = 1; switch (style.type) { case FillType.LinearGradient: case FillType.RadialGradient: case FillType.FocalRadialGradient: { const records = style.records; const colors = shapeStyle.colors = []; const ratios = shapeStyle.ratios = []; for (let i = 0; i < records.length; i++) { const record = records[i]; if (ratios.length == 0 || ratios[ratios.length - 1] != record.ratio) { colors.push(record.color); ratios.push(record.ratio); } } scale = 1; break; } case FillType.RepeatingBitmap: case FillType.ClippedBitmap: case FillType.NonsmoothedRepeatingBitmap: case FillType.NonsmoothedClippedBitmap: shapeStyle.smooth = ( style.type !== FillType.NonsmoothedRepeatingBitmap && style.type !== FillType.NonsmoothedClippedBitmap ); shapeStyle.repeat = ( style.type !== FillType.ClippedBitmap && style.type !== FillType.NonsmoothedClippedBitmap ); /*var index = dependencies.indexOf(style.bitmapId); if (index === -1) { index = dependencies.length; dependencies.push(style.bitmapId); }*/ shapeStyle.material = this.getMaterial(style.bitmapId, factory); scale = 1 / 20; break; default: console.log('shape parser encountered invalid fill style ' + style.type); } if (!style.matrix) { shapeStyle.transform = IDENTITY_MATRIX; return shapeStyle; } const matrix = style.matrix; shapeStyle.transform = { a: matrix.a * scale, b: matrix.b * scale, c: matrix.c * scale, d: matrix.d * scale, tx: matrix.tx / 20, ty: matrix.ty / 20 }; // null data that's unused from here on out style.matrix = null; return shapeStyle; } private static getMaterial(bitmapIndex: number, factory: IMaterialFactory): IMaterial { let material: IMaterial = factory.mapMatsForBitmaps[bitmapIndex]; if (!material) { let myImage: Image2D = <Image2D> factory.awaySymbols[bitmapIndex]; if (!myImage) myImage = new BitmapImage2D(512, 512, true, 0xff0000ff, true); material = factory.createMaterial(myImage); material.alphaBlending = true; material.useColorTransform = true; material.bothSides = true; factory.mapMatsForBitmaps[bitmapIndex] = material; } return material; } public static processMorphStyle(style: any, isLineStyle: boolean): ShapeStyle { const morphStyle: ShapeStyle = Object.create(style); if (isLineStyle) { morphStyle.width = style.widthMorph; if (!style.color && style.hasFill) { const fillStyle = this.processMorphStyle(style.fillStyle, false); morphStyle.transform = fillStyle.transform; morphStyle.colors = fillStyle.colors; morphStyle.ratios = fillStyle.ratios; return morphStyle; } else { morphStyle.color = style.colorMorph; return morphStyle; } } if (style.type === undefined) { return morphStyle; } if (style.type === FillType.Solid) { morphStyle.color = style.colorMorph; return morphStyle; } let scale = 1; switch (style.type) { case FillType.LinearGradient: case FillType.RadialGradient: case FillType.FocalRadialGradient: { const records = style.records; const colors = morphStyle.colors = []; const ratios = morphStyle.ratios = []; for (let i = 0; i < records.length; i++) { const record = records[i]; colors.push(record.colorMorph); ratios.push(record.ratioMorph); } scale = 1; break; } case FillType.RepeatingBitmap: case FillType.ClippedBitmap: case FillType.NonsmoothedRepeatingBitmap: case FillType.NonsmoothedClippedBitmap: scale = 1 / 20; break; default: console.log('shape parser encountered invalid fill style'); } if (!style.matrix) { morphStyle.transform = IDENTITY_MATRIX; return morphStyle; } const matrix = style.matrixMorph; morphStyle.transform = { a: (matrix.a * scale), b: (matrix.b * scale), c: (matrix.c * scale), d: (matrix.d * scale), tx: matrix.tx / 20, ty: matrix.ty / 20 }; return morphStyle; } /* * Paths are stored in 2-dimensional arrays. Each of the inner arrays contains * all the paths for a certain fill or line style. */ public static createPathsList(styles: any[], isLineStyle: boolean, isMorph: boolean, factory: IMaterialFactory): SegmentedPath[] { const paths: SegmentedPath[] = []; for (let i = 0; i < styles.length; i++) { const style = this.processStyle(styles[i], isLineStyle, isMorph, factory); if (!isLineStyle) { paths[i] = new SegmentedPath(style, null); } else { paths[i] = new SegmentedPath(null, style); } } return paths; } }