/// <summary> /// Gets the image entries to be written to the file /// </summary> /// <returns></returns> internal byte[] GetImageDict(long filePos, out int size) { MemoryStream ms = new MemoryStream(); int s; byte[] ba; foreach (PdfImageEntry ie in images.Values) { ObjectList objList = new ObjectList(ie.objectNum, filePos); ba = PdfUtility.GetUTF8Bytes(ie.imgDict, out s); ms.Write(ba, 0, ba.Length); filePos += s; ms.Write(ie.ba, 0, ie.ba.Length); // write out the image filePos += ie.ba.Length; ba = PdfUtility.GetUTF8Bytes("endstream\r\nendobj\r\n", out s); ms.Write(ba, 0, ba.Length); filePos += s; ie.xref.offsets.Add(objList); } ba = ms.ToArray(); size = ba.Length; return(ba); }
public void Start() { // Create the anchor for all pdf objects CompressionConfig cc = RdlEngineConfig.GetCompression(); anchor = new PdfAnchor(cc != null); //Create a PdfCatalog string lang; if (r.ReportDefinition.Language != null) { lang = r.ReportDefinition.Language.EvaluateString(this.r, null); } else { lang = null; } catalog = new PdfCatalog(anchor, lang); //Create a Page Tree Dictionary pageTree = new PdfPageTree(anchor); //Create a Font Dictionary fonts = new PdfFonts(anchor); //Create a Pattern Dictionary patterns = new PdfPattern(anchor); //Create an Image Dictionary images = new PdfImages(anchor); //Create an Outline Dictionary outline = new PdfOutline(anchor); //Create the info Dictionary info = new PdfInfo(anchor); //Set the info Dictionary. info.SetInfo(r.Name, r.Author, r.Description, ""); // title, author, subject, company //Create a utility object pdfUtility = new PdfUtility(anchor); //write out the header int size = 0; tw.Write(pdfUtility.GetHeader("1.5", out size), 0, size); // filesize = size; }
/// <summary> /// Page Text element at the X Y position; multiple lines handled /// </summary> /// <returns></returns> internal void AddText(float x, float y, float height, float width, string[] sa, StyleInfo si, PdfFonts fonts, float[] tw, bool bWrap, string url, bool bNoClip, string tooltip) { // Calculate the RGB colors e.g. RGB(255, 0, 0) = red = 1 0 0 rg double r = si.Color.R; double g = si.Color.G; double b = si.Color.B; r = Math.Round((r / 255), 3); g = Math.Round((g / 255), 3); b = Math.Round((b / 255), 3); string pdfFont = fonts.GetPdfFont(si); // get the pdf font resource name // Loop thru the lines of text for (int i = 0; i < sa.Length; i++) { string text = sa[i]; float textwidth = tw[i]; // Calculate the x position float startX = x + si.PaddingLeft; // TODO: handle tb_rl float startY = y + si.PaddingTop + (i * si.FontSize); // TODO: handle tb_rl if (si.WritingMode == WritingModeEnum.lr_tb) { // TODO: not sure what alignment means with tb_lr so I'll leave it out for now switch (si.TextAlign) { case TextAlignEnum.Center: if (width > 0) { startX = x + si.PaddingLeft + (width - si.PaddingLeft - si.PaddingRight) / 2 - textwidth / 2; } break; case TextAlignEnum.Right: if (width > 0) { startX = x + width - textwidth - si.PaddingRight; } break; case TextAlignEnum.Left: default: break; } // Calculate the y position switch (si.VerticalAlign) { case VerticalAlignEnum.Middle: if (height <= 0) { break; } // calculate the middle of the region startY = y + si.PaddingTop + (height - si.PaddingTop - si.PaddingBottom) / 2 - si.FontSize / 2; // now go up or down depending on which line if (sa.Length == 1) { break; } if (sa.Length % 2 == 0) // even number { startY = startY - ((sa.Length / 2 - i) * si.FontSize) + si.FontSize / 2; } else { startY = startY - ((sa.Length / 2 - i) * si.FontSize); } break; case VerticalAlignEnum.Bottom: if (height <= 0) { break; } startY = y + height - si.PaddingBottom - (si.FontSize * (sa.Length - i)); break; case VerticalAlignEnum.Top: default: break; } } else { //25072008 GJL - Move x in a little - it draws to close to the edge of the rectangle (25% of the font size seems to work!) and Center or right align vertical text startX += si.FontSize / 4; switch (si.TextAlign) { case TextAlignEnum.Center: if (height > 0) { startY = y + si.PaddingLeft + (height - si.PaddingLeft - si.PaddingRight) / 2 - textwidth / 2; } break; case TextAlignEnum.Right: if (width > 0) { startY = y + height - textwidth - si.PaddingRight; } break; case TextAlignEnum.Left: default: break; } } // Draw background rectangle if needed (only put out on the first line, since we do whole rectangle) if (!si.BackgroundColor.IsEmpty && height > 0 && width > 0 && i == 0) { // background color, height and width are specified AddFillRect(x, y, width, height, si.BackgroundColor); } // Set the clipping path if (height > 0 && width > 0) { if (bNoClip) // no clipping but we still want URL checking { elements.Append("\r\nq\t"); } else { elements.AppendFormat(NumberFormatInfo.InvariantInfo, "\r\nq\t{0} {1} {2} {3} re W n", x, pSize.yHeight - y - height, width, height); } if (url != null) { p.AddHyperlink(x, pSize.yHeight - y, height, width, url); } if (tooltip != null) { p.AddToolTip(x, pSize.yHeight - y, height, width, tooltip); } } else { elements.Append("\r\nq\t"); } // Escape the text string newtext = PdfUtility.UTF16StringQuoter(text); //string newtext = text.Replace("\\", "\\\\"); //newtext = newtext.Replace("(", "\\("); //newtext = newtext.Replace(")", "\\)"); if (si.WritingMode == WritingModeEnum.lr_tb) { elements.AppendFormat(NumberFormatInfo.InvariantInfo, "\r\nBT/{0} {1} Tf\t{5} {6} {7} rg\t{2} {3} Td \t({4}) Tj\tET\tQ\t", pdfFont, si.FontSize, startX, (pSize.yHeight - startY - si.FontSize), newtext, r, g, b); } else { // Rotate text -90 degrees=-.5 radians (this works for english don't know about true tb-rl language) // had to play with reader to find best approximation for this rotation; didn't do what I expected // see pdf spec section 4.2.2 pg 141 "Common Transformations" elements.AppendFormat(NumberFormatInfo.InvariantInfo, "\r\nBT/{0} {1} Tf\t{5} {6} {7} rg\t{8} {9} {10} {11} {2} {3} Tm \t({4}) Tj\tET\tQ\t", pdfFont, si.FontSize, startX, (pSize.yHeight - startY), newtext, r, g, b, radsCos, radsSin, -radsSin, radsCos); } // Handle underlining etc. float maxX; switch (si.TextDecoration) { case TextDecorationEnum.Underline: maxX = width > 0? Math.Min(x + width, startX + textwidth): startX + textwidth; AddLine(startX, startY + si.FontSize + 1, maxX, startY + si.FontSize + 1, 1, si.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.LineThrough: maxX = width > 0? Math.Min(x + width, startX + textwidth): startX + textwidth; AddLine(startX, startY + (si.FontSize / 2) + 1, maxX, startY + (si.FontSize / 2) + 1, 1, si.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.Overline: maxX = width > 0? Math.Min(x + width, startX + textwidth): startX + textwidth; AddLine(startX, startY + 1, maxX, startY + 1, 1, si.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.None: default: break; } } AddBorder(si, x, y, height, width); // add any required border return; }
/// <summary> /// Content object /// </summary> /// <summary> /// Get the Content Dictionary /// </summary> internal byte[] GetContentDict(long filePos, out int size) { // When no compression if (!CanCompress) { content = string.Format("\r\n{0} 0 obj<</Length {1}>>stream\r{2}\rendstream\rendobj\r", this.objectNum, contentStream.Length, contentStream); return(GetUTF8Bytes(content, filePos, out size)); } // Try to use compression; could still fail in which case fall back to uncompressed Stream strm = null; MemoryStream cs = null; try { CompressionConfig cc = RdlEngineConfig.GetCompression(); cs = new MemoryStream(); // this will contain the content stream if (cc != null) { strm = cc.GetStream(cs); } if (strm == null) { // can't compress string cs.Close(); content = string.Format("\r\n{0} 0 obj<</Length {1}>>stream\r{2}\rendstream\rendobj\r", this.objectNum, contentStream.Length, contentStream); return(GetUTF8Bytes(content, filePos, out size)); } // Compress the contents int cssize; byte[] ca = PdfUtility.GetUTF8Bytes(contentStream, out cssize); strm.Write(ca, 0, cssize); strm.Flush(); cc.CallStreamFinish(strm); // Now output the PDF command MemoryStream ms = new MemoryStream(); int s; byte[] ba; // get the compressed data; we need the lenght now byte[] cmpData = cc.GetArray(cs); // write the beginning portion of the PDF object string ws = string.Format("\r\n{0} 0 obj<< /Filter /FlateDecode /Length {1}>>stream\r", this.objectNum, cmpData.Length); ba = GetUTF8Bytes(ws, filePos, out s); // this will also register the object ms.Write(ba, 0, ba.Length); filePos += s; // write the Compressed data ms.Write(cmpData, 0, cmpData.Length); filePos += ba.Length; // write the end portion of the PDF object ba = PdfUtility.GetUTF8Bytes("\rendstream\rendobj\r", out s); ms.Write(ba, 0, ba.Length); filePos += s; // now the final output array ba = ms.ToArray(); size = ba.Length; return(ba); } finally { if (strm != null) { strm.Close(); } } }