//--------------------------------------------------------------------------------------- // Copyright (c) 2001-2020 by PDFTron Systems Inc. All Rights Reserved. // Consult legal.txt regarding legal and license information. //--------------------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include using namespace pdftron; using namespace std; using namespace SDF; using namespace PDF; using namespace Common; //--------------------------------------------------------------------------------------- // The sample code shows how to edit the page display list and how to modify graphics state // attributes on existing Elements. In particular the sample program strips all images from // the page, changes path fill color to red, and changes text fill color to blue. //--------------------------------------------------------------------------------------- // XObjects are guaranteed to have unique object numbers typedef set XObjSet; static void ProcessElements(ElementReader& reader, ElementWriter& writer, XObjSet& visited) { Element element; while (element = reader.Next()) // Read page contents { switch (element.GetType()) { case Element::e_text_begin: case Element::e_text_end: break; case Element::e_text: { Matrix2D ctm = element.GetCTM(); GState gs = element.GetGState(); double fontSize = gs.GetFontSize(); Font font = gs.GetFont(); double hscale = gs.GetHorizontalScale() / 100.0; Matrix2D textMtx = element.GetTextMatrix(); Matrix2D posMtx = Matrix2D(1, 0, 0, 1, 0, 0); Matrix2D fontMtx = Matrix2D(fontSize * hscale, 0, 0, fontSize, 0, 0); double unitsPerEm = font.GetUnitsPerEm(); Matrix2D unitsPerEmMtx = Matrix2D(1.0 / unitsPerEm, 0, 0, -1.0 / unitsPerEm, 0, 0); fontMtx = fontMtx * unitsPerEmMtx; for (CharIterator citr = element.GetCharIterator(); citr.HasNext(); citr.Next()) { CharData charData = citr.Current(); posMtx.m_h = charData.x; posMtx.m_v = charData.y; Matrix2D pathMtx = ctm * textMtx * posMtx * fontMtx; PathData pathData = font.GetGlyphPath(charData.char_code, true); if (pathData.GetOperators().size() > 0 && pathData.GetPoints().size() > 0) { vector points = pathData.GetPoints(); for (int i = 0; i < points.size(); i += 2) { double x = points[i]; double y = points[i + 1]; Point translatedPoint = pathMtx.Mult(Point(x, y)); points[i] = translatedPoint.x; points[i + 1] = translatedPoint.y; } pathData.SetPoints(points); ElementBuilder builder; Element pathElement = builder.CreatePath(pathData.GetPoints(), pathData.GetOperators()); pathElement.SetPathFill(true); pathElement.SetPathStroke(false); pathElement.GetGState().SetFillColorSpace(ColorSpace::CreateDeviceGray()); pathElement.GetGState().SetFillColor(ColorPt(0.5, 0.0, 0.0)); writer.WritePlacedElement(pathElement); } } break; } case Element::e_form: { writer.WriteElement(element); // write Form XObject reference to current stream Obj form_obj = element.GetXObject(); if (visited.find(form_obj.GetObjNum()) == visited.end()) // if this XObject has not been processed { // recursively process the Form XObject visited.insert(form_obj.GetObjNum()); ElementWriter new_writer; reader.FormBegin(); new_writer.Begin(form_obj); reader.ClearChangeList(); new_writer.SetDefaultGState(reader); ProcessElements(reader, new_writer, visited); new_writer.End(); reader.End(); } break; } default: writer.WriteElement(element); } } } int main(int argc, char* argv[]) { int ret = 0; PDFNet::Initialize(); // Relative path to the folder containing test files. string input_path = "../../TestFiles/"; string output_path = "../../TestFiles/Output/"; string input_filename = "newsletter.pdf"; string output_filename = "newsletter_edited.pdf"; try { cout << "Opening the input file..." << endl; PDFDoc doc(input_path + input_filename); doc.InitSecurityHandler(); ElementWriter writer; ElementReader reader; XObjSet visited; // Process each page in the document for (PageIterator itr = doc.GetPageIterator();itr.HasNext();itr.Next()) { try { Page page = itr.Current(); visited.insert(page.GetSDFObj().GetObjNum()); reader.Begin(page); writer.Begin(page, ElementWriter::e_replacement, false, true, page.GetResourceDict()); ProcessElements(reader, writer, visited); writer.End(); reader.End(); } catch (Common::Exception& e) { cout << e << endl; } } // Save modified document doc.Save(output_path + output_filename, SDFDoc::e_remove_unused, 0); cout << "Done. Result saved in " << output_filename << "..." << endl; } catch (std::exception& e) { cout << e.what() << endl; ret = 1; } catch (...) { cout << "Unknown Exception" << endl; ret = 1; } PDFNet::Terminate(); return ret; }