العمل مع مشغلات PDF في Java

مقدمة عن عوامل PDF واستخدامها

العامل هو كلمة مفتاح في PDF تحدد إجراءً يجب تنفيذّه، مثل رسم شكل رسومي على الصفحة. تُميز كلمة مفتاح العامل عن كائن مسمى بغياب حرف المائلة الأول (2Fh). تكون العوامل ذات معنى فقط داخل تدفق المحتوى.

تدفق المحتوى هو كائن تدفق PDF يتكون بياناته من تعليمات تصف العناصر الرسومية التي ستُرسم على الصفحة. يمكن العثور على مزيد من التفاصيل حول عوامل PDF في مواصفات PDF.

استخدم هذه الصفحة عندما تحتاج إلى التحكم المباشر في تدفق محتوى PDF في Java، مثل وضع صورة بحسابات مصفوفة صريحة، أو إعادة استخدام نفس الرسم عدة مرات عبر XForm، أو حذف تعليمات الرسم منخفضة المستوى من صفحة.

إضافة صورة باستخدام عوامل PDF

استخدم العوامل منخفضة المستوى عندما يجب التحكم بدقة في وضع الصورة على مستوى content-stream بدلاً من خلال APIs تخطيط عالية المستوى.

  1. افتح ملف PDF المصدر باستخدام Document واحصل على الهدف Page.
  2. أضف تدفق الصورة الإدخالية إلى موارد الصفحة واحتفظ باسم المورد المعاد.
  3. أنشئ كائنًا من الفئة Rectangle الذي يحدد المنطقة المستهدفة ويُنشئ Matrix من حدوده.
  4. استخدم GSave لحفظ حالة الرسومات الحالية، ConcatenateMatrix لوضع الصورة، Do لتلوينه، و GRestore لإعادة الحالة السابقة.
  5. احفظ مستند PDF المحدث.
public static void addImageUsingPdfOperators(Path inputFile, Path imageFile, Path outputFile) throws Exception {
    try (Document document = new Document(inputFile.toString());
         InputStream imageStream = Files.newInputStream(imageFile)) {
        Page page = document.getPages().get_Item(1);
        String imageName = page.getResources().getImages().add(imageStream);

        Rectangle rectangle = new Rectangle(100, 100, 200, 200, true);
        Matrix matrix = new Matrix(new double[]{
                rectangle.getURX() - rectangle.getLLX(),
                0,
                0,
                rectangle.getURY() - rectangle.getLLY(),
                rectangle.getLLX(),
                rectangle.getLLY()
        });

        page.getContents().add(new GSave());
        page.getContents().add(new ConcatenateMatrix(matrix));
        page.getContents().add(new Do(imageName));
        page.getContents().add(new GRestore());
        document.save(outputFile.toString());
    }
    System.out.println("Image added with PDF operators to " + outputFile);
}

رسم محتوى XForm القابل لإعادة الاستخدام على صفحة

استخدم هذا النهج عندما يجب عرض نفس الصورة أو الرسم البياني أكثر من مرة دون تكرار المورد في ملف PDF.

  1. افتح ملف PDF المصدر باستخدام Document، احصل على الهدف Page، والوصول إلى الخاص به OperatorCollection.
  2. غلف محتويات الصفحة الحالية بـ GSave و GRestore حتى لا تتسرب التحولات اللاحقة إلى تدفق المحتوى الأصلي.
  3. أنشئ كائنًا من الفئة XForm المورد، أضف الصورة إلى موارد النموذج، واستخدم ConcatenateMatrix زائد Do لرسم الصورة داخل النموذج.
  4. ضع النموذج نفسه عند إحداثيات صفحات متعددة عن طريق إضافة مصفوفة تحويل وتنفيذ اسم النموذج مع Do المشغل.
  5. استعد حالة الرسومات واحفظ ملف PDF الناتج.
public static void drawXFormOnPage(Path inputFile, Path imageFile, Path outputFile) throws Exception {
    try (Document document = new Document(inputFile.toString());
         InputStream imageStream = Files.newInputStream(imageFile)) {
        Page page = document.getPages().get_Item(1);
        OperatorCollection pageContents = page.getContents();

        pageContents.insert(1, new GSave());
        pageContents.add(new GRestore());
        pageContents.add(new GSave());

        XForm form = XForm.createNewForm(page, document);
        page.getResources().getForms().add(form);

        form.getContents().add(new GSave());
        form.getContents().add(new ConcatenateMatrix(200, 0, 0, 200, 0, 0));
        String imageName = form.getResources().getImages().add(imageStream);
        form.getContents().add(new Do(imageName));
        form.getContents().add(new GRestore());

        addFormAt(pageContents, form.getName(), 100, 500);
        addFormAt(pageContents, form.getName(), 100, 300);

        pageContents.add(new GRestore());
        document.save(outputFile.toString());
    }
    System.out.println("XForm drawn on page in " + outputFile);
}

private static void addFormAt(OperatorCollection pageContents, String formName, double x, double y) {
    pageContents.add(new GSave());
    pageContents.add(new ConcatenateMatrix(1, 0, 0, 1, x, y));
    pageContents.add(new Do(formName));
    pageContents.add(new GRestore());
}

إزالة عمليات الرسومات من صفحة

استخدم هذا المثال عندما تحتوي الصفحة على عوامل رسم متجهية يجب إزالتها مباشرةً من تدفق المحتوى.

  1. افتح ملف PDF المصدر باستخدام Document واحصل على الهدف Page.
  2. مرّ على مشغّلات محتوى الصفحة وجمع نماذج من Stroke, ClosePathStroke، و Fill.
  3. احذف المشغلين المجمّعين من محتويات الصفحة واحفظ ملف PDF المحدث.

تزيل هذه التقنية تعليمات الرسم المستهدفة فقط. إذا كانت الصفحة تحتوي أيضًا على تسميات نصية ذات صلة أو عمليات تشغيل غير رسومية أخرى، فإن تلك العناصر تظل في تدفق المحتوى وقد تحتاج إلى إجراء تنظيف منفصل.

public static void removeGraphicsObjects(Path inputFile, Path outputFile) {
    try (Document document = new Document(inputFile.toString())) {
        Page page = document.getPages().get_Item(1);
        List<Operator> operatorsToRemove = new ArrayList<>();
        for (Object item : page.getContents()) {
            Operator operator = (Operator) item;
            if (operator instanceof Stroke || operator instanceof ClosePathStroke || operator instanceof Fill) {
                operatorsToRemove.add(operator);
            }
        }
        page.getContents().delete(operatorsToRemove);
        document.save(outputFile.toString());
    }
    System.out.println("Graphics operators removed in " + outputFile);
}

المواضيع ذات الصلة