public RecordArray(IShapeData parent) : base(-1) { this.Parent = parent; }
public FillPath(FillStyle fillStyle, IShapeData segment) { this.FillStyle = fillStyle; this.Segment = segment; }
public void WritePaths(IShapeData[][] ips) { WriteStartArray(); WriteBits((int)DVex.PathDefinition, 8); WriteBits(ips.Length, 11); // number of path defs for(int i = 0; i < ips.Length; i++) { WritePathBody(ips[i]); } FlushBits(); WriteEndArray(); }
public StrokePath(StrokeStyle strokeStyle, IShapeData segment) { this.StrokeStyle = strokeStyle; this.Segment = segment; }
public void WritePathBody(IShapeData[] ips) { if(ips.Length < 1) return; // write header int count = 0; List<int> alVals = new List<int>(); List<string> alTypes = new List<string>(); Point prevPoint = Point.Empty; for(int i = 0; i < ips.Length; i++) { // figure out if it is a line, curve, or (needs a) move record // moveTo if(ips[i].StartPoint != prevPoint) { alTypes.Add("M"); alVals.Add((int)(ips[i].StartPoint.X * 20)); alVals.Add((int)(ips[i].StartPoint.Y * 20)); count += 2; } // lineTo if(ips[i] is Line) { alTypes.Add("L"); alVals.Add((int)(ips[i].StartPoint.X * 20)); alVals.Add((int)(ips[i].StartPoint.Y * 20)); count += 2; } // curveTo if(ips[i] is QuadBezier) { alTypes.Add("C"); QuadBezier qb = (QuadBezier)ips[i]; alVals.Add((int)(qb.Control.X*20)); alVals.Add((int)(qb.Control.Y*20)); alVals.Add((int)(qb.Anchor1.X*20)); alVals.Add((int)(qb.Anchor1.Y*20)); count += 4; } prevPoint = ips[i].EndPoint; } int[] vals = new int[alVals.Count]; for(int i = 0; i < alVals.Count; i++) { vals[i] = (int)alVals[i]; } int maxBits = MinBits(vals) + 1; // sign // nBits WriteBits(2-2, 5); // data count WriteBits(alTypes.Count, 11); // write out all type data first as it is even (line/curve/move) for(int i = 0; i < alTypes.Count; i++) { // L:0 C:1 M:2 string st = (string)alTypes[i]; int type = (st == "M") ? 2 : (st == "C") ? 0 : 1; WriteBits(type, 2); } // nBits WriteBits(maxBits-2, 5); // data count WriteBits(alVals.Count, 11); // write out int data nBits * (L2, C4, M2) for data) for(int i = 0; i < vals.Length; i++) { WriteBits(vals[i], maxBits); } }
private static void ConsolidatePaths(Symbol symbol, DVexWriter writer) { List<FillStyle> fills = new List<FillStyle>(); List<StrokeStyle> strokes = new List<StrokeStyle>(); fills.Add( new SolidFill(Color.Transparent) ); strokes.Add( new SolidStroke(0.0F, Color.Transparent) ); ArrayList allPaths = new ArrayList(); ArrayList allSrs = new ArrayList(); // Find all used colors/strokes, and the F0,F1,S info for each seg foreach(Shape sh in symbol.Shapes) { foreach(IShapeData s in sh.ShapeData) { int fill = 0; int stroke = 0; if (!fills.Contains(shape.Fills[s.FillIndex])) { fill = fills.Add(shape.Fills[s.FillIndex]); } else { fill = fills.IndexOf(shape.Fills[s.FillIndex]); } if( !strokes.Contains(shape.Strokes[s.StrokeIndex]) ) { stroke = strokes.Add(shape.Strokes[s.StrokeIndex]); } else { stroke = strokes.IndexOf(shape.Strokes[s.StrokeIndex]); } // break path into shape records foreach(IPathPrimitive ipp in s.Path) { if(ipp is IShapeData) { IShapeData ip = (IShapeData)ipp; if(allPaths.Contains(ip)) { // this must be a fill1 if it is a dup int index = allPaths.IndexOf(ip); Shrec sr = (Shrec)allSrs[index]; Shrec newShrec = new Shrec(0, 0); newShrec.F0 = (sr.F0 == 0) ? fill : sr.F0 ; newShrec.F1 = (sr.F1 == 0) ? fill : sr.F1 ; newShrec.S = (sr.S == 0) ? stroke : sr.S ; allSrs[index] = newShrec; } else { allSrs.Add(new Shrec(fill, stroke)); allPaths.Add(ip); } } } } // end groups } // end shapes // ok, now write out colors // sort fills by rgb, argb, and gradients ArrayList orderedFills = new ArrayList(); ArrayList rgbas = new ArrayList(); ArrayList gfs = new ArrayList(); foreach(Fill sf in fills) { if(sf is SolidFill) { if( ((SolidFill)sf).Color.A == 255 || (SolidFill)sf == fills[0]) // 'no fill' { orderedFills.Add(sf); } else { rgbas.Add(sf); } } else if(sf is GradientFill) { gfs.Add(sf); } else { // bitmap fills orderedFills.Add(new SolidFill(Color.Gray)); }; } SolidFill[] wrgbs = new SolidFill[orderedFills.Count]; wrgbs[0] = new SolidFill(Color.FromArgb(255,0,0,0)); int fRgb = 1; foreach(Fill f in orderedFills) { if(f != fills[0]) { wrgbs[fRgb++] = (SolidFill)f; } } int fRgba = 0; SolidFill[] wrgbas = new SolidFill[rgbas.Count]; foreach(Fill f in rgbas) { orderedFills.Add(f); wrgbas[fRgba++] = (SolidFill)f; } int fGr = 0; GradientFill[] wgfs = new GradientFill[gfs.Count]; foreach(Fill f in gfs) { orderedFills.Add(f); wgfs[fGr++] = (GradientFill)(f); } writer.WriteNbitColorDefs(wrgbs); writer.WriteNbitColorDefs(wrgbas); writer.WriteNbitGradientDefs(wgfs); //writer.WriteRgbColorDefs(wrgbs); //writer.WriteRgbaColorDefs(wrgbas); //writer.WriteGradientColorDefs(wgfs); // ok, colors written, now strokes // write out all the stroke defs second // get counts int wrgbCount = 0; int wrgbaCount = 0; foreach(Stroke st in strokes) { if(st.Color.A == 255 || st == strokes[0]) {wrgbCount++;} else{wrgbaCount++;} } // create stroke arrays Stroke[] wsrgbs = new Stroke[wrgbCount]; Stroke[] wsrgbas = new Stroke[wrgbaCount]; int sRgb = 0; int sRgba = 0; foreach(Stroke st in strokes) { if( st.Color.A == 255 || st == strokes[0]) { wsrgbs[sRgb++] = st; } else { wsrgbas[sRgba++] = st; } } // now write the stroke data writer.WriteNbitStrokeDefs(wsrgbs); writer.WriteNbitStrokeDefs(wsrgbas); //writer.WriteRgbStrokeDefs(wsrgbs); //writer.WriteRgbaStrokeDefs(wsrgbas); // and now paths // valid pathsegs must have the same F0, F1, and S ArrayList tempPaths = new ArrayList(); ArrayList tempSrsAl = new ArrayList(); PathCollection pc = new PathCollection(); Shrec curShrec = Shrec.Empty; for(int i = 0; i < allSrs.Count; i++) //Shrec sr in srsAl) { Shrec sr = (Shrec)allSrs[i]; if(sr.Equals(curShrec) || curShrec.Equals(Shrec.Empty)) { //add to path pc.Add((IShapeData)allPaths[i]); } else { // write to hash tempPaths.Add(pc); tempSrsAl.Add(curShrec); pc = new PathCollection(); pc.Add((IShapeData)allPaths[i]); } curShrec = sr; } if(!tempSrsAl.Contains(curShrec)) { tempPaths.Add(pc); tempSrsAl.Add(curShrec); } // split non contig paths ArrayList paths = new ArrayList(); ArrayList srsAl = new ArrayList(); foreach(PathCollection pcoll in tempPaths) { //pcoll.ReorderPath(); PathCollection[] pcolls = pcoll.SplitPath(); foreach(PathCollection splitP in pcolls) { paths.Add(splitP); srsAl.Add(tempSrsAl[tempPaths.IndexOf(pcoll)] ); //writer.WritePath(splitP.PointSegments); } } IShapeData[][] ips = new IShapeData[paths.Count][]; for(int i = 0; i < paths.Count; i++) { ips[i] = ((PathCollection)paths[i]).PointSegments; } writer.WritePaths(ips); // convert to array Shrec[] srs = new Shrec[srsAl.Count]; for(int i = 0; i < srsAl.Count; i++) { srs[i] = (Shrec)srsAl[i]; } // and finally, uses - must be sorted by fill color // use order Fill1 (no strokes), fill0[stroke], stroke only's // for each fill index{..}, then dangling strokes ArrayList shapeRecords = new ArrayList(); // start at 1 to avoid empty fills foreach(Fill f in orderedFills) { int curFill = fills.IndexOf(f); if(curFill != 0) { // all F1's of this color first ArrayList Fs = new ArrayList(); for(int i = 0; i < srs.Length; i++) { if(srs[i].F0 == curFill) { // add use for F0 ShapeRecord curSr = new ShapeRecord(); curSr.Fill = orderedFills.IndexOf(f); curSr.Stroke = srs[i].S; curSr.Path = i; Fs.Add(curSr); } if(srs[i].F1 == curFill ) { // add use for F1 ShapeRecord curSr = new ShapeRecord(); curSr.Fill = orderedFills.IndexOf(f); curSr.Stroke = 0; curSr.Path = i; Fs.Add(curSr); } } //now sort the F1s from tip to tail if(Fs.Count > 0) { ArrayList finalFs = new ArrayList(); finalFs.Add(Fs[0]); PointF end = ((PathCollection)paths[((ShapeRecord)Fs[0]).Path]).LastPoint; Fs.RemoveAt(0); while(Fs.Count > 0) { bool found = false; foreach(ShapeRecord sr in Fs) { PathCollection srp = (PathCollection)paths[sr.Path]; if(srp.FirstPoint == end) { end = srp.LastPoint; finalFs.Add(sr); Fs.Remove(sr); found = true; break; } } if(found == false) { finalFs.Add(Fs[0]); end = ( (PathCollection)paths[ ((ShapeRecord)Fs[0]).Path] ).LastPoint; Fs.RemoveAt(0); } } // and write them foreach(ShapeRecord sr in finalFs) { shapeRecords.Add(sr); } } } } for(int i = 0; i < srs.Length; i++) { if(srs[i].F0 == 0 && srs[i].F1 == 0) { // must be stroke ShapeRecord curSr = new ShapeRecord(); curSr.Fill = 0; curSr.Stroke = srs[i].S; curSr.Path = i; shapeRecords.Add(curSr); } } // convert to array ShapeRecord[] srecs = new ShapeRecord[shapeRecords.Count]; for(int i = 0; i < shapeRecords.Count; i++) { srecs[i] = (ShapeRecord)shapeRecords[i]; } writer.WriteUses(srecs); }
public FillStyleArray(IShapeData shape) { this.Parent = shape; }
public void WriteGradientDefinition(Shape shape) { GradientFill gf = (GradientFill)shape.Fill; gf.TagId = gradientCounter++; List <IShapeData> shapeData = shape.ShapeData; float minX = float.PositiveInfinity; float minY = float.PositiveInfinity; float maxX = float.NegativeInfinity; float maxY = float.NegativeInfinity; Point lastPoint = shapeData[0].StartPoint; for (int i = 0; i < shapeData.Count; i++) { IShapeData sd = shapeData[i]; switch (sd.SegmentType) { case SegmentType.Line: lastPoint = sd.EndPoint; break; case SegmentType.CubicBezier: CubicBezier cb = (CubicBezier)sd; lastPoint = cb.EndPoint; minX = Math.Min(minX, cb.Control0.X); maxX = Math.Max(maxX, cb.Control0.X); minY = Math.Min(minY, cb.Control0.Y); maxY = Math.Max(maxY, cb.Control0.Y); minX = Math.Min(minX, cb.Control1.X); maxX = Math.Max(maxX, cb.Control1.X); minY = Math.Min(minY, cb.Control1.Y); maxY = Math.Max(maxY, cb.Control1.Y); break; case SegmentType.QuadraticBezier: QuadBezier qb = (QuadBezier)sd; lastPoint = qb.EndPoint; minX = Math.Min(minX, qb.Control.X); maxX = Math.Max(maxX, qb.Control.X); minY = Math.Min(minY, qb.Control.Y); maxY = Math.Max(maxY, qb.Control.Y); break; } minX = Math.Min(minX, sd.StartPoint.X); maxX = Math.Max(maxX, sd.StartPoint.X); minY = Math.Min(minY, sd.StartPoint.Y); maxY = Math.Max(maxY, sd.StartPoint.Y); minX = Math.Min(minX, sd.EndPoint.X); maxX = Math.Max(maxX, sd.EndPoint.X); minY = Math.Min(minY, sd.EndPoint.Y); maxY = Math.Max(maxY, sd.EndPoint.Y); } if (gf.FillType == FillType.Linear) { //<linearGradient id = "g1" x1 = "50%" y1 = "50%" x2 = "60%" y2 = "60%"> // <stop stop-color = "green" offset = "0%"/> // <stop stop-color = "pink" offset = "100%"/> //</linearGradient> xw.WriteStartElement("linearGradient"); xw.WriteStartAttribute("id"); xw.WriteValue("gf_" + gf.TagId); xw.WriteEndAttribute(); Matrix m = gf.Transform; Rectangle r = GradientFill.GradientVexRect; sysDraw2D.Matrix m2 = new sysDraw2D.Matrix(m.ScaleX, m.Rotate0, m.Rotate1, m.ScaleY, m.TranslateX, m.TranslateY); float midY = r.Point.Y + (r.Size.Height / 2); sysDraw.PointF pt0 = new sysDraw.PointF(r.Point.X, midY); sysDraw.PointF pt1 = new sysDraw.PointF(r.Point.X + r.Size.Width, midY); sysDraw.PointF[] pts = new sysDraw.PointF[] { pt0, pt1 }; m2.TransformPoints(pts); float ratX = 1 / (maxX - minX); float ratY = 1 / (maxY - minY); float d0x = (pts[0].X - minX) * ratX; float d0y = (pts[0].Y - minY) * ratY; float d1x = (pts[1].X - minX) * ratX; float d1y = (pts[1].Y - minY) * ratY; xw.WriteStartAttribute("x1"); xw.WriteFloat(d0x); xw.WriteEndAttribute(); xw.WriteStartAttribute("y1"); xw.WriteFloat(d0y); xw.WriteEndAttribute(); xw.WriteStartAttribute("x2"); xw.WriteFloat(d1x); xw.WriteEndAttribute(); xw.WriteStartAttribute("y2"); xw.WriteFloat(d1y); xw.WriteEndAttribute(); xw.WriteStartAttribute("spreadMethod"); xw.WriteValue("pad"); xw.WriteEndAttribute(); for (int i = 0; i < gf.Stops.Count; i++) { xw.WriteStartElement("stop"); xw.WriteStartAttribute("stop-color"); xw.WriteValue("#" + gf.Fills[i].RGB.ToString("X6")); xw.WriteEndAttribute(); if (gf.Fills[i].A < 255) { xw.WriteStartAttribute("stop-opacity"); xw.WriteValue((gf.Fills[i].A / 255f).ToString("f3")); xw.WriteEndAttribute(); } xw.WriteStartAttribute("offset"); xw.WriteFloat(gf.Stops[i] * 100); xw.WriteValue("%"); xw.WriteEndAttribute(); xw.WriteEndElement(); // stop } xw.WriteEndElement(); // linearGradient } else if (gf.FillType == FillType.Radial) { //<radialGradient id = "g2" cx = "100" cy = "100" r = "50"> // <stop stop-color = "green" offset = "0%"/> // <stop stop-color = "pink" offset = "100%"/> //</radialGradient> xw.WriteStartElement("radialGradient"); xw.WriteStartAttribute("id"); xw.WriteValue("gf_" + gf.TagId); xw.WriteEndAttribute(); xw.WriteAttributeString("gradientUnits", "userSpaceOnUse"); xw.WriteAttributeString("cx", "0"); xw.WriteAttributeString("cy", "0"); xw.WriteAttributeString("r", GradientFill.GradientVexRect.Right.ToString()); Matrix m = gf.Transform; xw.WriteStartAttribute("gradientTransform"); xw.WriteValue("matrix(" + m.ScaleX + "," + m.Rotate0 + "," + m.Rotate1 + "," + m.ScaleY + "," + m.TranslateX + "," + m.TranslateY + ")"); xw.WriteEndAttribute(); xw.WriteStartAttribute("spreadMethod"); xw.WriteValue("pad"); xw.WriteEndAttribute(); for (int i = gf.Stops.Count - 1; i >= 0; i--) { xw.WriteStartElement("stop"); xw.WriteStartAttribute("stop-color"); xw.WriteValue("#" + gf.Fills[i].RGB.ToString("X6")); xw.WriteEndAttribute(); if (gf.Fills[i].A < 255) { xw.WriteStartAttribute("stop-opacity"); xw.WriteValue((gf.Fills[i].A / 255f).ToString("f3")); xw.WriteEndAttribute(); } xw.WriteStartAttribute("offset"); xw.WriteFloat((1 - gf.Stops[i]) * 100); // xaml fill is reversed from gdi xw.WriteValue("%"); xw.WriteEndAttribute(); xw.WriteEndElement(); // stop } xw.WriteEndElement(); // radialGradient } }