/// <summary>Reads and processes all the data of the InputMeta.</summary> 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.EndPath(); 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.EndPath(); ImageData bmpImage = ImageDataFactory.CreateBmp(b, true); 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>Output Text at a certain x and y coordinate.</summary> /// <remarks>Output Text at a certain x and y coordinate. Clipped or opaque text isn't supported as of yet.</remarks> /// <param name="x">x-coordinate</param> /// <param name="y">y-coordinate</param> /// <param name="flag">flag indicating clipped or opaque</param> /// <param name="x1">x1-coordinate of the rectangle if clipped or opaque</param> /// <param name="y1">y1-coordinate of the rectangle if clipped or opaque</param> /// <param name="x2">x2-coordinate of the rectangle if clipped or opaque</param> /// <param name="y2">y1-coordinate of the rectangle if clipped or opaque</param> /// <param name="text">text to output</param> public virtual void OutputText(int x, int y, int flag, int x1, int y1, int x2, int y2, String text) { MetaFont font = state.GetCurrentFont(); float refX = state.TransformX(x); float refY = state.TransformY(y); float angle = state.TransformAngle(font.GetAngle()); float sin = (float)Math.Sin(angle); float cos = (float)Math.Cos(angle); float fontSize = font.GetFontSize(state); FontProgram fp = font.GetFont(); int align = state.GetTextAlign(); // NOTE, MetaFont always creates with CP1252 encoding. int normalizedWidth = 0; byte[] bytes = font.encoding.ConvertToBytes(text); foreach (byte b in bytes) { normalizedWidth += fp.GetWidth(0xff & b); } float textWidth = fontSize / FontProgram.UNITS_NORMALIZATION * normalizedWidth; float tx = 0; float ty = 0; float descender = fp.GetFontMetrics().GetTypoDescender(); float ury = fp.GetFontMetrics().GetBbox()[3]; cb.SaveState(); cb.ConcatMatrix(cos, sin, -sin, cos, refX, refY); if ((align & MetaState.TA_CENTER) == MetaState.TA_CENTER) { tx = -textWidth / 2; } else { if ((align & MetaState.TA_RIGHT) == MetaState.TA_RIGHT) { tx = -textWidth; } } if ((align & MetaState.TA_BASELINE) == MetaState.TA_BASELINE) { ty = 0; } else { if ((align & MetaState.TA_BOTTOM) == MetaState.TA_BOTTOM) { ty = -descender; } else { ty = -ury; } } Color textColor; if (state.GetBackgroundMode() == MetaState.OPAQUE) { textColor = state.GetCurrentBackgroundColor(); cb.SetFillColor(textColor); cb.Rectangle(tx, ty + descender, textWidth, ury - descender); cb.Fill(); } textColor = state.GetCurrentTextColor(); cb.SetFillColor(textColor); cb.BeginText(); cb.SetFontAndSize(PdfFontFactory.CreateFont(state.GetCurrentFont().GetFont(), PdfEncodings.CP1252, true), fontSize); cb.SetTextMatrix(tx, ty); cb.ShowText(text); cb.EndText(); if (font.IsUnderline()) { cb.Rectangle(tx, ty - fontSize / 4, textWidth, fontSize / 15); cb.Fill(); } if (font.IsStrikeout()) { cb.Rectangle(tx, ty + fontSize / 3, textWidth, fontSize / 15); cb.Fill(); } cb.RestoreState(); }
/// <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; } } }