I ran into this same problem yesterday. After much research, I found:
1) PDF v1.7 has been "superseded" by ISO 32000-1:2008
2) Using the PDFSharp option of ViewerPreferences.Elements.SetString("/PrintScaling", "None") would generate the following ASCII text within the PDF
Code:
/PrintScaling(None)
3) The new version of PDF expects ASCII text like the following:
Code:
/Enforce(PrintScaling)/PrintScaling/None
As a result, I devised that if I use a little trickery, I can use the PDFSharp option to my advantage in order to create an ASCII string close to my desired output. Then, after capturing the bytes of the PDF document, I can replace them with the desired ASCII string. My generic approach was the following:
Code:
PdfDocument doc = new PdfDocument();
//Make PDF to have a setting to force paper printing to use "Actual Size"
//as scaling default when printing to paper. <PRINT_SCALING/>
//
//In order to force Acrobat to use "Actual Size" when printing,
//we need to set "PrintScaling" to "None". As of PDF version 1.7 (Acrobat 8+),
//this setting is ignored unless it is associated with a "Enforce" setting.
//
//PDFSharp supports creating these "ViewerPreferences" settings. When you pass it
//a setting string key (must be prefixed with a "/"), it creates a setting string with
//the key followed by the value within parentheses. Such as:
// /PrintScaling(None)
//
//However, with PDF 1.7, it must use the /Enforce setting. By using Acrobat's
//document "Properties | Advanced" option, you can change the setting to find out that
//the correct format is:
// /Enforce(PrintScaling)/PrintScaling/None
//
//Therefore, we will have PDFSharp create a string that is virtually identical
//to the one we need. The "virtually identical" setting string will be:
// /Enforce(PrintScaling/PrintScaling/None)
//Then, when all is done (save the doc stream to a byte array), we will replace
//the "virtually identical" setting string with a setting string that is what we want.
doc.Version = 17;
doc.ViewerPreferences.Elements.SetString("/Enforce", "PrintScaling/PrintScaling/None");
...generate PDF content...
//Convert doc to stream array
byte[] documentBytes;
using (MemoryStream stream = new MemoryStream())
{
doc.Save(stream, false);
stream.Seek(0, SeekOrigin.Begin);
documentBytes= stream.ToArray();
}
//Make PDF to have a setting to force paper printing to use "Actual Size"
//as scaling default when printing to paper. <PRINT_SCALING/>
//
//We have /Enforce(PrintScaling/PrintScaling/None)
//We want /Enforce(PrintScaling)/PrintScaling/None
documentBytes= ReplaceBytes(documentBytes, GetASCIIBytes("PrintScaling/PrintScaling/None)"), GetASCIIBytes("PrintScaling)/PrintScaling/None"));
This relies on the following methods for replacing bytes in a byte array:
Code:
public static byte[] GetASCIIBytes(string str)
{
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
return bytes;
}
public static int FindBytes(byte[] src, byte[] find)
{
int index = -1;
int matchIndex = 0;
// handle the complete source array
for (int i = 0; i < src.Length; i++)
{
if (src[i] == find[matchIndex])
{
if (matchIndex == (find.Length - 1))
{
index = i - matchIndex;
break;
}
matchIndex++;
}
else
{
matchIndex = 0;
}
}
return index;
}
public static byte[] ReplaceBytes(byte[] src, byte[] search, byte[] repl)
{
byte[] dst = null;
int index = FindBytes(src, search);
if (index >= 0)
{
dst = new byte[src.Length - search.Length + repl.Length];
// before found array
Buffer.BlockCopy(src, 0, dst, 0, index);
// repl copy
Buffer.BlockCopy(repl, 0, dst, index, repl.Length);
// rest of src array
Buffer.BlockCopy(
src,
index + search.Length,
dst,
index + repl.Length,
src.Length - (index + search.Length));
}
else
{
dst = src;
}
return dst;
}
Hope this helps someone.
-Arizona