private StreamObject UncachedCopyOnWrite(StreamObject so, Page page) { // this function must always be called from a function which caches the results if (_identity) { return(so); } Dictionary <Page, int> entry1 = null; _pages.TryGetValue(so, out entry1); if (entry1 != null) { int index = entry1[page]; StreamObject copy = (StreamObject)so.Clone(); _doc.ObjectSoup.Add(copy); ArrayAtom array = page.Resolve(Atom.GetItem(page.Atom, "Contents")) as ArrayAtom; if (array != null) { Debug.Assert(array.Count > index); array[index] = new RefAtom(copy); } else { Debug.Assert(index == 0); Atom.SetItem(page.Atom, "Contents", new RefAtom(copy)); } entry1.Remove(page); if (entry1.Count <= 1) { _pages.Remove(so); } return(copy); } Dictionary <Page, Tuple <DictAtom, string> > entry2 = null; _xobjs.TryGetValue(so, out entry2); if (entry2 != null) { Tuple <DictAtom, string> index = entry2[page]; Debug.Assert(so is FormXObject); StreamObject copy = (StreamObject)so.Clone(); _doc.ObjectSoup.Add(copy); index.Item1[index.Item2] = new RefAtom(copy); entry2.Remove(page); return(copy); } return(so); }
private static void KeepFonts(HashSet <string> fontsToKeep, Atom atomDA) { string da = Atom.GetText(atomDA); ArrayAtom array = ArrayAtom.FromContentStream(ASCIIEncoding.ASCII.GetBytes(da)); var items = OpAtom.Find(array, new string[] { "Tf" }); foreach (var pair in items) { Atom[] args = OpAtom.GetParameters(array, pair.Item2); Debug.Assert(args != null); // shouldn't really happen if (args != null) { fontsToKeep.Add(Atom.GetName(args[0])); } } }
private void createButton3_Click(object sender, EventArgs e) { Doc doc = new Doc(); Properties props = Properties.FromDoc(doc, true); List <Group> groups = new List <Group>(); for (int i = 1; i < 4; i++) { groups.Add(props.AddGroup("Layer " + i.ToString(), null)); } // membership policies are simple to use but limited in scope MembershipGroup alloff = props.AddMembershipGroup(); alloff.Policy = MembershipGroup.PolicyEnum.AllOff; alloff.PolicyGroups = groups; // membership visibility expressions are more complex but more powerful MembershipGroup mgve = props.AddMembershipGroup(); ArrayAtom ve = mgve.MakeVisibilityExpression(MembershipGroup.LogicEnum.Or, groups); mgve.EntryVE = mgve.MakeVisibilityExpression(MembershipGroup.LogicEnum.Not, new ArrayAtom[] { ve }); doc.FontSize = 36; doc.Rect.Inset(20, 20); for (int i = 0; i < 3; i++) { doc.Page = doc.AddPage(); Page page = (Page)doc.ObjectSoup[doc.Page]; Writer writer = new Writer(props, page); OptionalContent.Layer layer1 = writer.AddGroup(alloff); doc.AddText("The next line uses a Policy so that it is only visible if all layers are turned off...\r\n"); writer.StartLayer(layer1); doc.AddText("I am normally invisible\r\n\r\n"); writer.EndLayer(); OptionalContent.Layer layer2 = writer.AddGroup(mgve); doc.AddText("The next line uses a Visibility Expression so that it is only visible if all layers are turned off...\r\n"); writer.StartLayer(layer2); doc.AddText("I am normally invisible\r\n"); writer.EndLayer(); doc.Flatten(); } LoadPDF(doc); }
public ArrayAtom GetTextOperator() { Debug.Assert(_text != null); // get data and widths byte[] section = new byte[_text.StreamLength]; Array.Copy(_data, _text.StreamOffset, section, 0, _text.StreamLength); IDictionary <char, int> widths = _text.Font.Widths; // convert to atoms ArrayAtom textOp = ArrayAtom.FromContentStream(section); string srcOp = ((OpAtom)textOp[1]).Text; int numParams = srcOp == "\"" ? 4 : 2; Debug.Assert(textOp.Count == numParams); ArrayAtom srcParams = textOp[numParams == 4 ? 2 : 0] as ArrayAtom; if (srcParams == null) { Debug.Assert(srcOp != "TJ"); srcParams = new ArrayAtom(); srcParams.Add(textOp[0]); } ArrayAtom dstParams = new ArrayAtom(); // copy items int textSpanIndex = 0; for (int i = 0; i < srcParams.Count; i++) { Atom item = srcParams[i]; if (item is StringAtom) { StringAtom str = (StringAtom)item; Tuple <string, bool[]> redaction = null; _redactions.TryGetValue(textSpanIndex++, out redaction); if (redaction == null) { dstParams.Add(item.Clone()); } else { string encoded = str.Text; string whole = redaction.Item1; bool[] redacted = redaction.Item2; Debug.Assert((encoded.Length == whole.Length) || (encoded.Length == whole.Length * 2)); int bytesPerChar = encoded.Length / whole.Length; int p1 = 0; while (p1 < redacted.Length) { bool hidden = redacted[p1]; int width1000ths = 0; int p2; for (p2 = p1; p2 < redacted.Length; p2++) { if (hidden != redacted[p2]) { break; } if (hidden) { width1000ths += widths[whole[p2]]; } } if (hidden) { dstParams.Add(new NumAtom(-width1000ths)); } else { string sub1 = encoded.Substring(p1 * bytesPerChar, (p2 - p1) * bytesPerChar); if (sub1.Length > 0) { dstParams.Add(new StringAtom(sub1)); } } p1 = p2; } } } else if (item is NumAtom) { NumAtom num = (NumAtom)item; dstParams.Add(item.Clone()); } else { Debug.Assert(false); } } // make new operators ArrayAtom newTextOp = new ArrayAtom(); if (srcOp == "\'") { newTextOp.Add(new OpAtom("T*")); } else if (srcOp == "\"") { newTextOp.Add(textOp[0].Clone()); newTextOp.Add(new OpAtom("Tw")); newTextOp.Add(textOp[1].Clone()); newTextOp.Add(new OpAtom("Tc")); newTextOp.Add(new OpAtom("T*")); } newTextOp.Add(dstParams); newTextOp.Add(new OpAtom("TJ")); return(newTextOp); }