/// <summary>Creates new MetaState</summary> public MetaState() { savedStates = new Stack <iText.Kernel.Pdf.Canvas.Wmf.MetaState>(); MetaObjects = new List <MetaObject>(); currentPoint = new Point(0, 0); currentPen = new MetaPen(); currentBrush = new MetaBrush(); currentFont = new MetaFont(); }
/// <summary>Sets every field of this MetaState to the values of the fields of the specified MetaState.</summary> /// <param name="state">state to copy</param> public virtual void SetMetaState(iText.Kernel.Pdf.Canvas.Wmf.MetaState state) { savedStates = state.savedStates; MetaObjects = state.MetaObjects; currentPoint = state.currentPoint; currentPen = state.currentPen; currentBrush = state.currentBrush; currentFont = state.currentFont; currentBackgroundColor = state.currentBackgroundColor; currentTextColor = state.currentTextColor; backgroundMode = state.backgroundMode; polyFillMode = state.polyFillMode; textAlign = state.textAlign; lineJoin = state.lineJoin; offsetWx = state.offsetWx; offsetWy = state.offsetWy; extentWx = state.extentWx; extentWy = state.extentWy; scalingX = state.scalingX; scalingY = state.scalingY; }
/// <summary>Stroke and fill the MetaPen and MetaBrush paths.</summary> public virtual void StrokeAndFill() { MetaPen pen = state.GetCurrentPen(); MetaBrush brush = state.GetCurrentBrush(); int penStyle = pen.GetStyle(); int brushStyle = brush.GetStyle(); if (penStyle == MetaPen.PS_NULL) { cb.ClosePath(); if (state.GetPolyFillMode() == MetaState.ALTERNATE) { cb.EoFill(); } else { cb.Fill(); } } else { bool isBrush = brushStyle == MetaBrush.BS_SOLID || brushStyle == MetaBrush.BS_HATCHED && state.GetBackgroundMode () == MetaState.OPAQUE; if (isBrush) { if (state.GetPolyFillMode() == MetaState.ALTERNATE) { cb.ClosePathEoFillStroke(); } else { cb.ClosePathFillStroke(); } } else { cb.ClosePathStroke(); } } }
/// <summary>Return true if the pen style is null and if it isn't a brush.</summary> /// <param name="isRectangle"> /// value to decide how to change the state. If true state.setLineJoinRectangle(cb) is called, /// if false state.setLineJoinPolygon(cb) is called. /// </param> /// <returns>true if the pen style is null and if it isn't a brush</returns> public virtual bool IsNullStrokeFill(bool isRectangle) { MetaPen pen = state.GetCurrentPen(); MetaBrush brush = state.GetCurrentBrush(); bool noPen = pen.GetStyle() == MetaPen.PS_NULL; int style = brush.GetStyle(); bool isBrush = style == MetaBrush.BS_SOLID || style == MetaBrush.BS_HATCHED && state.GetBackgroundMode() == MetaState.OPAQUE; bool result = noPen && !isBrush; if (!noPen) { if (isRectangle) { state.SetLineJoinRectangle(cb); } else { state.SetLineJoinPolygon(cb); } } return(result); }
/// <summary>Reads and processes all the data of the InputMeta.</summary> /// <exception cref="System.IO.IOException"/> public virtual void ReadAll() { if (@in.ReadInt() != unchecked ((int)(0x9AC6CDD7))) { throw new PdfException(PdfException.NotAPlaceableWindowsMetafile); } @in.ReadWord(); left = @in.ReadShort(); top = @in.ReadShort(); right = @in.ReadShort(); bottom = @in.ReadShort(); inch = @in.ReadWord(); state.SetScalingX((float)(right - left) / (float)inch * 72f); state.SetScalingY((float)(bottom - top) / (float)inch * 72f); state.SetOffsetWx(left); state.SetOffsetWy(top); state.SetExtentWx(right - left); state.SetExtentWy(bottom - top); @in.ReadInt(); @in.ReadWord(); @in.Skip(18); int tsize; int function; cb.SetLineCapStyle(PdfCanvasConstants.LineCapStyle.ROUND); cb.SetLineJoinStyle(PdfCanvasConstants.LineJoinStyle.ROUND); for (; ;) { int lenMarker = @in.GetLength(); tsize = @in.ReadInt(); if (tsize < 3) { break; } function = @in.ReadWord(); switch (function) { case 0: { break; } case META_CREATEPALETTE: case META_CREATEREGION: case META_DIBCREATEPATTERNBRUSH: { state.AddMetaObject(new MetaObject()); break; } case META_CREATEPENINDIRECT: { MetaPen pen = new MetaPen(); pen.Init(@in); state.AddMetaObject(pen); break; } case META_CREATEBRUSHINDIRECT: { MetaBrush brush = new MetaBrush(); brush.Init(@in); state.AddMetaObject(brush); break; } case META_CREATEFONTINDIRECT: { MetaFont font = new MetaFont(); font.Init(@in); state.AddMetaObject(font); break; } case META_SELECTOBJECT: { int idx = @in.ReadWord(); state.SelectMetaObject(idx, cb); break; } case META_DELETEOBJECT: { int idx = @in.ReadWord(); state.DeleteMetaObject(idx); break; } case META_SAVEDC: { state.SaveState(cb); break; } case META_RESTOREDC: { int idx = @in.ReadShort(); state.RestoreState(idx, cb); break; } case META_SETWINDOWORG: { state.SetOffsetWy(@in.ReadShort()); state.SetOffsetWx(@in.ReadShort()); break; } case META_SETWINDOWEXT: { state.SetExtentWy(@in.ReadShort()); state.SetExtentWx(@in.ReadShort()); break; } case META_MOVETO: { int y = @in.ReadShort(); Point p = new Point(@in.ReadShort(), y); state.SetCurrentPoint(p); break; } case META_LINETO: { int y = @in.ReadShort(); int x = @in.ReadShort(); Point p = state.GetCurrentPoint(); cb.MoveTo(state.TransformX((int)p.GetX()), state.TransformY((int)p.GetY())); cb.LineTo(state.TransformX(x), state.TransformY(y)); cb.Stroke(); state.SetCurrentPoint(new Point(x, y)); break; } case META_POLYLINE: { state.SetLineJoinPolygon(cb); int len = @in.ReadWord(); int x = @in.ReadShort(); int y = @in.ReadShort(); cb.MoveTo(state.TransformX(x), state.TransformY(y)); for (int k = 1; k < len; ++k) { x = @in.ReadShort(); y = @in.ReadShort(); cb.LineTo(state.TransformX(x), state.TransformY(y)); } cb.Stroke(); break; } case META_POLYGON: { if (IsNullStrokeFill(false)) { break; } int len = @in.ReadWord(); int sx = @in.ReadShort(); int sy = @in.ReadShort(); cb.MoveTo(state.TransformX(sx), state.TransformY(sy)); for (int k = 1; k < len; ++k) { int x = @in.ReadShort(); int y = @in.ReadShort(); cb.LineTo(state.TransformX(x), state.TransformY(y)); } cb.LineTo(state.TransformX(sx), state.TransformY(sy)); StrokeAndFill(); break; } case META_POLYPOLYGON: { if (IsNullStrokeFill(false)) { break; } int numPoly = @in.ReadWord(); int[] lens = new int[numPoly]; for (int k = 0; k < lens.Length; ++k) { lens[k] = @in.ReadWord(); } for (int j = 0; j < lens.Length; ++j) { int len = lens[j]; int sx = @in.ReadShort(); int sy = @in.ReadShort(); cb.MoveTo(state.TransformX(sx), state.TransformY(sy)); for (int k = 1; k < len; ++k) { int x = @in.ReadShort(); int y = @in.ReadShort(); cb.LineTo(state.TransformX(x), state.TransformY(y)); } cb.LineTo(state.TransformX(sx), state.TransformY(sy)); } StrokeAndFill(); break; } case META_ELLIPSE: { if (IsNullStrokeFill(state.GetLineNeutral())) { break; } int b = @in.ReadShort(); int r = @in.ReadShort(); int t = @in.ReadShort(); int l = @in.ReadShort(); cb.Arc(state.TransformX(l), state.TransformY(b), state.TransformX(r), state.TransformY(t), 0, 360); StrokeAndFill(); break; } case META_ARC: { if (IsNullStrokeFill(state.GetLineNeutral())) { break; } float yend = state.TransformY(@in.ReadShort()); float xend = state.TransformX(@in.ReadShort()); float ystart = state.TransformY(@in.ReadShort()); float xstart = state.TransformX(@in.ReadShort()); float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); float cx = (r + l) / 2; float cy = (t + b) / 2; float arc1 = GetArc(cx, cy, xstart, ystart); float arc2 = GetArc(cx, cy, xend, yend); arc2 -= arc1; if (arc2 <= 0) { arc2 += 360; } cb.Arc(l, b, r, t, arc1, arc2); cb.Stroke(); break; } case META_PIE: { if (IsNullStrokeFill(state.GetLineNeutral())) { break; } float yend = state.TransformY(@in.ReadShort()); float xend = state.TransformX(@in.ReadShort()); float ystart = state.TransformY(@in.ReadShort()); float xstart = state.TransformX(@in.ReadShort()); float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); float cx = (r + l) / 2; float cy = (t + b) / 2; float arc1 = GetArc(cx, cy, xstart, ystart); float arc2 = GetArc(cx, cy, xend, yend); arc2 -= arc1; if (arc2 <= 0) { arc2 += 360; } IList <double[]> ar = PdfCanvas.BezierArc(l, b, r, t, arc1, arc2); if (ar.Count == 0) { break; } double[] pt = ar[0]; cb.MoveTo(cx, cy); cb.LineTo(pt[0], pt[1]); for (int k = 0; k < ar.Count; ++k) { pt = ar[k]; cb.CurveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]); } cb.LineTo(cx, cy); StrokeAndFill(); break; } case META_CHORD: { if (IsNullStrokeFill(state.GetLineNeutral())) { break; } float yend = state.TransformY(@in.ReadShort()); float xend = state.TransformX(@in.ReadShort()); float ystart = state.TransformY(@in.ReadShort()); float xstart = state.TransformX(@in.ReadShort()); float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); float cx = (r + l) / 2; float cy = (t + b) / 2; float arc1 = GetArc(cx, cy, xstart, ystart); float arc2 = GetArc(cx, cy, xend, yend); arc2 -= arc1; if (arc2 <= 0) { arc2 += 360; } IList <double[]> ar = PdfCanvas.BezierArc(l, b, r, t, arc1, arc2); if (ar.Count == 0) { break; } double[] pt = ar[0]; cx = (float)pt[0]; cy = (float)pt[1]; cb.MoveTo(cx, cy); for (int k = 0; k < ar.Count; ++k) { pt = ar[k]; cb.CurveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]); } cb.LineTo(cx, cy); StrokeAndFill(); break; } case META_RECTANGLE: { if (IsNullStrokeFill(true)) { break; } float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); cb.Rectangle(l, b, r - l, t - b); StrokeAndFill(); break; } case META_ROUNDRECT: { if (IsNullStrokeFill(true)) { break; } float h = state.TransformY(0) - state.TransformY(@in.ReadShort()); float w = state.TransformX(@in.ReadShort()) - state.TransformX(0); float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); cb.RoundRectangle(l, b, r - l, t - b, (h + w) / 4); StrokeAndFill(); break; } case META_INTERSECTCLIPRECT: { float b = state.TransformY(@in.ReadShort()); float r = state.TransformX(@in.ReadShort()); float t = state.TransformY(@in.ReadShort()); float l = state.TransformX(@in.ReadShort()); cb.Rectangle(l, b, r - l, t - b); cb.EoClip(); cb.NewPath(); break; } case META_EXTTEXTOUT: { int y = @in.ReadShort(); int x = @in.ReadShort(); int count = @in.ReadWord(); int flag = @in.ReadWord(); int x1 = 0; int y1 = 0; int x2 = 0; int y2 = 0; if ((flag & (MetaFont.ETO_CLIPPED | MetaFont.ETO_OPAQUE)) != 0) { x1 = @in.ReadShort(); y1 = @in.ReadShort(); x2 = @in.ReadShort(); y2 = @in.ReadShort(); } byte[] text = new byte[count]; int k; for (k = 0; k < count; ++k) { byte c = (byte)@in.ReadByte(); if (c == 0) { break; } text[k] = c; } String s; try { s = iText.IO.Util.JavaUtil.GetStringForBytes(text, 0, k, "Cp1252"); } catch (ArgumentException) { s = iText.IO.Util.JavaUtil.GetStringForBytes(text, 0, k); } OutputText(x, y, flag, x1, y1, x2, y2, s); break; } case META_TEXTOUT: { int count = @in.ReadWord(); byte[] text = new byte[count]; int k; for (k = 0; k < count; ++k) { byte c = (byte)@in.ReadByte(); if (c == 0) { break; } text[k] = c; } String s; try { s = iText.IO.Util.JavaUtil.GetStringForBytes(text, 0, k, "Cp1252"); } catch (ArgumentException) { s = iText.IO.Util.JavaUtil.GetStringForBytes(text, 0, k); } count = count + 1 & 0xfffe; @in.Skip(count - k); int y = @in.ReadShort(); int x = @in.ReadShort(); OutputText(x, y, 0, 0, 0, 0, 0, s); break; } case META_SETBKCOLOR: { state.SetCurrentBackgroundColor(@in.ReadColor()); break; } case META_SETTEXTCOLOR: { state.SetCurrentTextColor(@in.ReadColor()); break; } case META_SETTEXTALIGN: { state.SetTextAlign(@in.ReadWord()); break; } case META_SETBKMODE: { state.SetBackgroundMode(@in.ReadWord()); break; } case META_SETPOLYFILLMODE: { state.SetPolyFillMode(@in.ReadWord()); break; } case META_SETPIXEL: { Color color = @in.ReadColor(); int y = @in.ReadShort(); int x = @in.ReadShort(); cb.SaveState(); cb.SetFillColor(color); cb.Rectangle(state.TransformX(x), state.TransformY(y), .2f, .2f); cb.Fill(); cb.RestoreState(); break; } case META_DIBSTRETCHBLT: case META_STRETCHDIB: { int rop = @in.ReadInt(); if (function == META_STRETCHDIB) { /*int usage = */ @in.ReadWord(); } int srcHeight = @in.ReadShort(); int srcWidth = @in.ReadShort(); int ySrc = @in.ReadShort(); int xSrc = @in.ReadShort(); float destHeight = state.TransformY(@in.ReadShort()) - state.TransformY(0); float destWidth = state.TransformX(@in.ReadShort()) - state.TransformX(0); float yDest = state.TransformY(@in.ReadShort()); float xDest = state.TransformX(@in.ReadShort()); byte[] b = new byte[tsize * 2 - (@in.GetLength() - lenMarker)]; for (int k = 0; k < b.Length; ++k) { b[k] = (byte)@in.ReadByte(); } try { cb.SaveState(); cb.Rectangle(xDest, yDest, destWidth, destHeight); cb.Clip(); cb.NewPath(); ImageData bmpImage = ImageDataFactory.CreateBmp(b, true, b.Length); PdfImageXObject imageXObject = new PdfImageXObject(bmpImage); float width = destWidth * bmpImage.GetWidth() / srcWidth; float height = -destHeight *bmpImage.GetHeight() / srcHeight; float x = xDest - destWidth * xSrc / srcWidth; float y = yDest + destHeight * ySrc / srcHeight - height; cb.AddXObject(imageXObject, new Rectangle(x, y, width, height)); cb.RestoreState(); } catch (Exception) { } // empty on purpose break; } } @in.Skip(tsize * 2 - (@in.GetLength() - lenMarker)); } state.Cleanup(cb); }
/// <summary>Select the MetaObject at the specified index and prepare the PdfCanvas.</summary> /// <param name="index">position of the MetaObject</param> /// <param name="cb">PdfCanvas to prepare</param> public virtual void SelectMetaObject(int index, PdfCanvas cb) { MetaObject obj = MetaObjects[index]; if (obj == null) { return; } int style; switch (obj.GetObjectType()) { case MetaObject.META_BRUSH: { currentBrush = (MetaBrush)obj; style = currentBrush.GetStyle(); if (style == MetaBrush.BS_SOLID) { Color color = currentBrush.GetColor(); cb.SetFillColor(color); } else { if (style == MetaBrush.BS_HATCHED) { Color color = currentBackgroundColor; cb.SetFillColor(color); } } break; } case MetaObject.META_PEN: { currentPen = (MetaPen)obj; style = currentPen.GetStyle(); if (style != MetaPen.PS_NULL) { Color color = currentPen.GetColor(); cb.SetStrokeColor(color); cb.SetLineWidth(Math.Abs(currentPen.GetPenWidth() * scalingX / extentWx)); switch (style) { case MetaPen.PS_DASH: { cb.SetLineDash(18, 6, 0); break; } case MetaPen.PS_DASHDOT: { cb.WriteLiteral("[9 6 3 6]0 d\n"); break; } case MetaPen.PS_DASHDOTDOT: { cb.WriteLiteral("[9 3 3 3 3 3]0 d\n"); break; } case MetaPen.PS_DOT: { cb.SetLineDash(3, 0); break; } default: { cb.SetLineDash(0); break; } } } break; } case MetaObject.META_FONT: { currentFont = (MetaFont)obj; break; } } }