Copy styles from old element to new element

Hello.

I am trying to develop one prototype where user can modify pdf contents. The interface where user can select area and is shown what kind of text was in selected area, works fine. But now the creating does not. For some reason, i can't seem to understand why creating new element fails silently nor how to place new element correctly in the location of old element or elements.

The code i have for creating new element is this:

style = elements[0].GetStyle()
font = Font(style.GetFont())
fontsize = style.GetFontSize()
eb = ElementBuilder()
element = eb.CreateTextBegin(font, 10.0)
writer.WriteElement(element)
element = eb.CreateTextRun('My Name')
element.SetTextMatrix(10, 0, 0, 10, 100, 100)
gstate = element.GetGState()
gstate.SetTextRenderMode(GState.e_fill_text)
gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB())
gstate.SetStrokeColor(ColorPt(1, 1, 1))
element.UpdateTextMetrics()
writer.WriteElement(element)
writer.WriteElement(eb.CreateTextEnd())
writer.End()
from core.helpers import ensure_dir
ensure_dir(output_filename)
doc.Save(output_filename, SDFDoc.e_linearized)
doc.Close()

But when i save the element then nothing appears to have changed in .pdf file. I also created stack-overflow question for this same thing, so if anyone who can help me here, can just aswell earn some stackoverflow points:P

http://stackoverflow.com/questions/22732289/pdftron-creating-new-element-with-same-styles-as-existing-element

Hello Alan,

Thank you for posting this question, and for evaluating the PDFNet SDK.

It’s not entirely clear where things are going wrong in your code without the full sample (i.e., showing how elements is populated) — if you could post a more complete sample, that might help to explain the behaviour.

If I change the ElementBuilder sample (Samples/ElementBuilderTest/PYTHON/ElementBuilderTest.py) to run your code snippet only for the first page, but using this line instead of copying font data:

element = eb.CreateTextBegin(Font.Create(doc.GetSDFDoc(), Font.e_times_roman), 10.0)

Then I get the attached PDF document as output (with “My Name” visible along the bottom of the page). So your code seems correct except for its font copying.

[Note: Rather than posting your code here, you might instead want to email it to support@pdftron.com.]

element_builder.pdf (1.12 KB)

What are your high-level requirements? It would be useful to understand this because there may be simpler way to accomplish what you need (e.g. use ContentReplacer - http://www.pdftron.com/pdfnet/samplecode.html#ContentReplacer or Stamper?)

Based on the code below it looks like you want to append some extra text to an existing page based on the font style (font name + color) used by the first word on the page. One thing to consider are optional parameters in ElementWriter.Begin(). At the same time it looks like default params should work fine.

One thing I see in your code is that you are setting the stroke color rather than fill

gstate.SetTextRenderMode(GState.e_fill_text)

gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB());

gstate.SetStrokeColor(ColorPt(1, 1, 1))

try

gstate.SetTextRenderMode(GState.e_fill_text)

gstate.SetFillColorSpace(ColorSpace.CreateDeviceRGB());

gstate.SetFillColor(ColorPt(1, 0, 0)) // hardcode to red … for testing purposes only

Another problem may be with the font. You are hijacking an existing font and are assuming that this font is using ‘standard encoding’. However this font is likely not using standard encoding. Furthermore, fonts in existing PDFs are usually subsetted (this means that the font does not contain a full list of glyphs, but only character references that are present in the document). As a result, you may see notdef or whitespace instead of the expected text. This and some other issues are covered here:

https://groups.google.com/d/msg/pdfnet-sdk/RBTuJG2uILk/pGkrKnqZ_YIJ

https://groups.google.com/d/msg/pdfnet-sdk/2y8s5aehq-c/xyknr9W5r-cJ

https://groups.google.com/d/msg/pdfnet-sdk/4yJNs0_Ne38/DftXPVWakLoJ

https://groups.google.com/d/msg/pdfnet-sdk/zidmrsPEj10/3zXNHuKWkuoJ

As an solution you can use the embedded font to find a matching system font (e.g. based on font name and other properties) and create a new font. PDFNet offers a utility method Font.Create(doc, font) , or Font.Create(doc, “Font name”)

http://www.pdftron.com/pdfnet/docs/PDFNetC/d4/d4a/classpdftron_1_1_p_d_f_1_1_font.html#ad00849598168e97c2b3f1937b1d3f11f

This methods will create a Unicode font so you should use eb.CreateUnicodeTextRun() rather than eb.CreateTextRun

The code example is below. It is part of Django project. This code is beeing run from django shell not within a view. So you can exclude web-server related problems from the list, i guess.

from pdfprint.pdffile.models import FileTemplate, EditableArea

f = FileTemplate.objects.get(id = 1)

from PDFNetPython2 import *

a = EditableArea.objects.filter(template = f)[0]

PDFNet.Initialize()

doc = PDFDoc(f.file.file.path)

from django.conf import settings

output_path = settings.MEDIA_ROOT+ “files/output/”

output_filename = output_path + f.file.file.path.split(’/’)[-1].split(’.’)[0] + ‘_edit.pdf’

doc.InitSecurityHandler()

reader = ElementReader()

element = Element()

itr = doc.GetPageIterator()

page = itr.Current()

reader.Begin(page)

rect = Rect(float(a.x1), float(a.y1), float(a.x2), float(a.y2))

page_crop = page.GetCropBox()

page_media = page.GetMediaBox()

page_bounding = page.GetVisibleContentBox()

element = reader.Next()

elements = []

text = u’’

extractor = TextExtractor()

extractor.Begin(page)

line = extractor.GetFirstLine()

elements = []

while line.IsValid():

word = line.GetFirstWord()

while word.IsValid():

elRect = word.GetBBox()

elRect.Normalize()

if elRect.IntersectRect(elRect, rect):

text += word.GetString()

elements.append(word)

word = word.GetNextWord()

line = line.GetNextLine()

writer = ElementWriter()

writer.Begin(page)

style = elements[0].GetStyle()

font = Font(style.GetFont())

fontsize = style.GetFontSize()

eb = ElementBuilder()

element = eb.CreateTextBegin(font, 10.0)

writer.WriteElement(element)

element = eb.CreateTextRun(‘My Name’)

element.SetTextMatrix(10, 0, 0, 10, 100, 100)

gstate = element.GetGState()

gstate.SetTextRenderMode(GState.e_fill_text)

gstate.SetStrokeColorSpace(ColorSpace.CreateDeviceRGB());

gstate.SetStrokeColor(ColorPt(1, 1, 1))

element.UpdateTextMetrics()

writer.WriteElement(element)

writer.WriteElement(eb.CreateTextEnd())

writer.End()

from core.helpers import ensure_dir

ensure_dir(output_filename)

doc.Save(output_filename, SDFDoc.e_linearized)

doc.Close()