I'm using TuesPechkin (the C# wrapper of wkhtmltopdf) and have it generating PDF files from HTML.
However, I would like to set the --disable-smart-shrinking option, which is listed in the wkhtmltopdf documentation as a PageOption
How can I do that?
public sealed class PdfConverter
{
static readonly PdfConverter instance = new PdfConverter();
private IConverter converter;
static PdfConverter()
{
}
PdfConverter()
{
// Keep the converter somewhere static, or as a singleton instance! Do NOT run this code more than once in the application lifecycle!
this.converter = new ThreadSafeConverter( new RemotingToolset<PdfToolset>( new Win32EmbeddedDeployment( new TempFolderDeployment())));
}
public static PdfConverter Instance
{
get { return instance; }
}
public byte[] ConvertHtmlToPdf(string html)
{
var document = new HtmlToPdfDocument
{
Objects = { new ObjectSettings { HtmlText = html } }
// Where are PageOptions? Thats where --disable-smart-shrinking is
};
return converter.Convert(document);
}
}
The --disable-smart-shrinking option does not exist in the API -- well, it kind of does, but in the form of it's opposite sibling: --enable-smart-shrinking.
That property is available in the TuesPechkin API as WebSettings.EnableIntelligentShrinking as seen in the TuesPechkin source code. It was named that way in TuesPechkin because that is how it is named in wkhtmltopdf's API as seen in the wkhtmltopdf source code.
You can also see there that the default value is true (from wkhtmltopdf), so if you set WebSettings.EnableIntelligentShrinking to false you should get the result you're aiming for.
It seems this functionality hasn't been implemented in Tuespechkin. I can't find it here, where most of the page options are located.
I guess he forgot to implement the option, so probably best to request the feature here. Or you can also add the feature yourself. :)
Related
My Visual Studio extension (VSIX) is derived from the Ook Language Example (found here). Basically, I have the following ClassificationFormatDefinition with a function loadSavedColor that loads the color the user has configured. Everything works fine.
[Name("some_unique_name")]
internal sealed class OokE : ClassificationFormatDefinition
{
public OokE()
{
DisplayName = "ook!"; //human readable version of the name
ForegroundColor = loadSavedColor();
}
}
Question: After the user has configured a new color, I like to invalidate the existing instance of class OokE or change the existing instances and set ForegroundColor. But whatever I do the syntax color is not updated.
I've tried:
Get a reference to class OokE and update ForegroundColor.
Invalidate the corresponding ClassificationTypeDefinition:
[Export(typeof(ClassificationTypeDefinition))]
[Name("ook!")]
internal static ClassificationTypeDefinition ookExclamation = null;
After hours of sifting through code I could create something that works. The following method UpdateFont called with colorKeyName equal to "some_unique_name" does the trick. I hope it is useful for someone.
private void UpdateFont(string colorKeyName, Color c)
{
var guid2 = Guid.Parse("{A27B4E24-A735-4d1d-B8E7-9716E1E3D8E0}");
var flags = __FCSTORAGEFLAGS.FCSF_LOADDEFAULTS | __FCSTORAGEFLAGS.FCSF_PROPAGATECHANGES;
var store = GetService(typeof(SVsFontAndColorStorage)) as IVsFontAndColorStorage;
if (store.OpenCategory(ref guid2, (uint)flags) != VSConstants.S_OK) return;
store.SetItem(colorKeyName, new[]{ new ColorableItemInfo
{
bForegroundValid = 1,
crForeground = (uint)ColorTranslator.ToWin32(c)
}});
store.CloseCategory();
}
After setting the new color, you will need to clear the cache with the following code:
IVsFontAndColorCacheManager cacheManager = this.GetService(typeof(SVsFontAndColorCacheManager)) as IVsFontAndColorCacheManager;
cacheManager.ClearAllCaches();
var guid = new Guid("00000000-0000-0000-0000-000000000000");
cacheManager.RefreshCache(ref guid);
guid = new Guid("{A27B4E24-A735-4d1d-B8E7-9716E1E3D8E0}"); // Text editor category
I am trying to serve some JavaScript from embedded resources in a class library. I managed to find out about the IFileProvider and created my own which is now working well. However, the problem I have now is that physical static files (from wwwroot) are no longer found.
I have the following in my Startup.cs file:
app.UseStaticFiles(
new StaticFileOptions()
{
// Override file provider to allow embedded resources
FileProvider = new CompositeFileProvider(
HostingEnvironment.ContentRootFileProvider,
new EmbeddedScriptFileProvider()),
//etc
});
I would have assumed using the CompositeFileProvider would mean that if the file is not found in one of the file providers, then it will try the other. I am also assuming that the default file provider is the one I specified as HostingEnvironment.ContentRootFileProvider. Is this incorrect?
The only other thing I can think of is that the problem is coming from inside my provider itself in the GetFileInfo() method. The definition of which is as follows:
public IFileInfo GetFileInfo(string subpath)
{
if (string.IsNullOrEmpty(subpath))
{
return new NotFoundFileInfo(subpath);
}
if (subpath.StartsWith("/", StringComparison.Ordinal))
{
subpath = subpath.Substring(1);
}
var metadata = EmbeddedScripts.FindEmbeddedResource(subpath);
if (metadata == null)
{
return new NotFoundFileInfo(subpath);
}
return new EmbeddedResourceFileInfo(metadata);
}
Could it be that returning NotFoundFileInfo(subpath) is causing my problems for physical css, js and other static files? If so, what should I be returning here instead so that the system knows to use the other file provider?
OK after a little digging in the source code (isn't it great that .NET is now open source?!), I managed to find the following links were very helpful indeed:
CompositeFileProvider.cs
- Based on the implementation in GetFileInfo(), I can see that I should pass back null instead of NotFoundFileInfo(subpath) if I want the other providers to try resolve it.
StaticFileMiddleware.cs
- This file shows that if the FileProvider is not specified (null) when setting up static file configuration with app.UseStaticFiles, then it will resolve one with the following line of code:
_fileProvider = _options.FileProvider ?? Helpers.ResolveFileProvider(hostingEnv);
And looking at Helpers.cs shows the following code:
internal static IFileProvider ResolveFileProvider(IHostingEnvironment hostingEnv)
{
if (hostingEnv.WebRootFileProvider == null)
{
throw new InvalidOperationException("Missing FileProvider.");
}
return hostingEnv.WebRootFileProvider;
}
Therefore, my assumption of using HostingEnvironment.ContentRootFileProvider was incorrect. I should be using HostingEnvironment.WebRootFileProvider instead.
Everything now works as it should.
I am trying to convert RTF to plain text in a c# program. I figured out how to do it but it isn't very clean. It uses RichTextBox which I'm not a huge fan of:
using (System.Windows.Forms.RichTextBox rtfBox = new System.Windows.Forms.RichTextBox())
{
rtfBox.Rtf = cTrans.NoteDescription;
tItem.ProcedureShortDescription = rtfBox.Text;
}
I was wondering if there is a better way to go about accomplishing this. Perhaps using RichEditDocumentServer? I could not find a ton of info on it though and was wondering if I could get some help on it. My thought was:
var documentServer = new RichEditDocumentServer();
documentServer.Document.RtfText = cTrans.NoteDescription;
tItem.ProcedureShortDescription = documentServer.Document.Text;
I did some more digging and this works. I figured I'd just post this as I couldn't see it answered anywhere on the site. I'm not sure if that is proper protocol.
I ended up putting it in a helper class so it can be called if needed again:
namespace ABELSoft.Dental.Interface.Helper
{
public class RtfToText
{
public static string convert(string rtfText)
{
string _text;
var documentServer = new RichEditDocumentServer();
documentServer.Document.RtfText = rtfText;
_text = documentServer.Document.Text;
return _text;
}
}
}
This is how I called it:
tItem.ProcedureShortDescription = RtfToText.convert(cTrans.NoteDescription);
I am currently developing an Excel macro which allows creating Bugs in a Bugzilla instance.
After some trial and error this now turns out to work fine.
I wanted to enhance the client so that it's also possible to add screenshots to the newly created bug.
The environment I'm using is a little bit tricky:
I have to use MS Excel for my task.
As Excel does not understand XML-RPC, I downloaded an interface DLL (CookComputing.XmlRpcV2.dll from xml-rpc.net) which makes the XML-RPC interface accessible from .NET.
Then I created an additional DLL which can be called from Excel macros (using COM interop).
As already mentioned, this is working fine for tasks like browsing or adding new bugs.
But when adding an attachment to the bug, the image must be converted into a base64 data type. Although this seems to work fine and although the creation of the screenshot seems to succeed, the image seems to be corrupted and cannot be displayed.
Here's what I do to add the image:
The Bugzilla add_attachment method accepts a struct as input:
http://www.bugzilla.org/docs/4.0/en/html/api/Bugzilla/WebService/Bug.html#add_attachment.
This type was defined in C# and is visible also in VBA.
This is the struct definition:
[ClassInterface(ClassInterfaceType.AutoDual)]
public class TAttachmentInputData
{
public string[] ids;
public string data; // base64-encoded data
public string file_name;
public string summary;
public string content_type;
public string comment;
public bool is_patch;
public bool is_private;
public void addId(int id)
{
ids = new string[1];
ids[0] = id.ToString();
}
public void addData(string strData)
{
try
{
byte[] encData_byte = new byte[strData.Length];
encData_byte = System.Text.Encoding.ASCII.GetBytes(strData);
string encodedData = Convert.ToBase64String(encData_byte);
data = new Byte[System.Text.Encoding.ASCII.GetBytes(encodedData).Length];
data = System.Text.Encoding.ASCII.GetBytes(encodedData);
}
catch (Exception e)
{
throw new Exception("Error in base64Encode" + e.Message);
}
}
This is the part in my macro where I would like to add the attachment:
Dim attachmentsStruct As New TAttachmentInputData
fname = attachmentFileName
attachmentsStruct.file_name = GetFilenameFromPath(fname)
attachmentsStruct.is_patch = False
attachmentsStruct.is_private = False
'multiple other definitions
Open fname For Binary As #1
attachmentsStruct.addData (Input(LOF(1), #1))
Close #1
attachmentsStruct.file_name = GetFilenameFromPath(fname)
Call BugzillaClass.add_attachment(attachmentsStruct)
Where BugzillaClass it the interface exposed from my DLL to Excel VBA.
The method add_attachment refers to the XML-RPC method add_attachment.
I assume that my problem is the conversion from the binary file into base64.
This is done using the addData method in my C# DLL.
Is the conversion done correctly there?
Any idea why the images are corrupted?
I think the issue is that you are reading in binary data in the macro, but the addData method is expecting a string. Try declaring the parameter in addData as byte[].
I have a load of UserControl objects (ascx files) in their own little project. I then reference this project in two projects: The REST API (which is a class library project) and the main website.
I'm sure this would be easy in the website, simply use Controls.Add in any Panel or ASP.NET control would work.
However, what about the API? Is there any way I can render the HTML of this control, simply by knowing the type of the control? The RenderControl method doesn't write any HTML to the writer as the control's life cycle hasn't even started.
Please bare in mind that I don't have the controls in the web project, so I don't have a virtual path to the ascx file. So the LoadControl method won't work here.
All the controls actually derive from the same base control. Is there anything I can do from within this base class that will allow me to load the control from a completely new instance?
This is what I have done recently, works well, but understand postbacks will not work if you use it inside your ASP.NET app.
[WebMethod]
public static string GetMyUserControlHtml()
{
return RenderUserControl("Com.YourNameSpace.UI", "YourControlName");
}
public static string RenderUserControl(string assembly,
string controlName)
{
FormlessPage pageHolder =
new FormlessPage() { AppRelativeTemplateSourceDirectory = HttpRuntime.AppDomainAppVirtualPath }; //allow for "~/" paths to resolve
dynamic control = null;
//assembly = "Com.YourNameSpace.UI"; //example
//controlName = "YourCustomControl"
string fullyQaulifiedAssemblyPath = string.Format("{0}.{1},{0}", assembly, controlName);
Type type = Type.GetType(fullyQaulifiedAssemblyPath);
if (type != null)
{
control = pageHolder.LoadControl(type, null);
control.Bla1 = "test"; //bypass compile time checks on property setters if needed
control.Blas2 = true;
}
pageHolder.Controls.Add(control);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
public class FormlessPage : Page
{
public override void VerifyRenderingInServerForm(Control control)
{
}
}