The default size in pixels for a tab in a RichTextBox is apparently 48 pixels, regardless of font or font size. This is set as default by .NET without me touching the SelectionTabs array. I've checked in the RTF - there's no \tx control code or anything so where the heck is this elusive '48' number stored?
I don't want to use this as a hardcoded 'magic number' in case other systems use something other than 48 pixels for a tab.
My own purpose is to help me convert from tabs to spaces (at least for fixed width fonts). But finding an answer to this also might get us closer to controlling the tab size with a single value without setting up an 'infinite' array of tab stops as implied from this answer.
Related
I need to enter a text to existing pdf (in top or bottom of the page) in c#.
I need to make sure that I dont overwrite any visible text or image.
Is there any way I could check an area in pdf if it contains text, image, control etc? I understand it will not be 100% accurate
You're going to need a full PDF consumer at the very least, because the only way to find out where the marks are on the page is to parse (and possibly render) the PDF.
There are complications which you haven't covered (possibly they have not occurred to you); what do you consider to be the area of the PDF file ? The MediaBox ? CropBox, TrimBox, ArtBox, BleedBox ? What if the PDF file contains, for example, a rectangular fill with white which covers the page ? What about a /Separation space called /White ? is that white (it generally gets rendered that way on the output) or not ? And yes, this is a widely used ink in the T-shirt printing industry amongst others.
To me the simplest solution would seem to be to use a tool which will give you the BoundingBox of marks on the page. I know the Ghostscript bbox device can do this, I imagine there are other tools which can do so. But note (for Ghostscript at least); if there are any marks in white (whatever the colour space), these are considered as marking the page and will be counted into the bbox.
The same tool ought to be able to give the size of the various Boxes in the PDF file (you'd need the pdf_info.ps program for Ghostscript to get this, currently). You can then quickly calculate which areas are unmarked.
But 'unmarked' isn't the same things as 'white'. If you want to not count areas which are painted in 'white' then the problem becomes greater. You really need to render the content and then look at each image sample in the output to see if its white or not, recording the maxima and minima of the x and y co-ordinates to determine the 'non-white' area of the page.
This is because there are complications like transfer functions, transparency blending, colour management, and image masking, any or all of which might cause an area which is marked with a non-white colour to be rendered white (a transparency SMask for example) or an area marked with white to be rendered non-white (eg a transfer function).
Your question is unclear because you haven't defined whether any of these issues are important to you, and how you want to treat them.
I'm trying to print a pdf with Ghostscript using those settings :
var switches = new List<string>
{
#"-empty",
#"-dPrinted",
#"-dNOPAUSE",
#"-dNOSAFER",
#"-dQUIET",
#"-dPDFSETTINGS=/printer",
#"-dNumCopies=1",
#"-sDEVICE=mswinpr2",
#"-dCompatibilityLevel=1.4",
#"-sOutputFile=%printer%" + printerSettings.PrinterName,
#"-f",
pdfFileName
};
but either the pdf or Ghostscript have bad margins and while it's good when I print it to file it clips when I print it on my printer.
Is there any way to add those programatically with Ghostscript ? I tried many different solutions from first pages of google but none of them work and they seem to have no effect on the printed pdf.
When I try to print it out with Adobe or IE it magicaly adds margins as soon as I choose the printer and it prints fine.
How to achive the same with Ghostscript ?
OK well the first thing is that many of the switches you are setting have no effect:
-empty isn't a Ghostscript-understood switch, and I'm slightly surprised it doesn't cause an error.
-dPDFSETTINGS only affects the pdfwrite device, which is why it is documented in the vector devices section.
-dCompatabilityLevel only affects the output of the pdfwrite device.
-dNOSAFER doesn't have any effect, as that's the default setting.
-f is used to 'close' direct PostScript insertion begun with -c, if you don't use -c you don't need -f
Now almost certainly neither Ghostscript nor your PDF has 'bad margins', the most likely explanation for your problem is that the printer you are using cannot print to the boundaries of the page, the left/right edges, and potentially the top and bottom edges are used by the paper transport mechanism, and the printer cannot print there.
In order to deal with that, you will need to reduce the size of the image, which you can 'probably' do by setting -dDEVICEWIDTHPOINTS and -dDEVICEHEIGHTPOINTS and -dFIXEDMEDIA. Its going to be up to you to work out the correct values for width and height.
Added after the comments below
There are two parts to this problem, the first is to deduce the size of the actual available area to print on, and to scale the output to that size. The second is to then reposition the output on the media so that it is all printed. If as you say the content is significantly smaller than the media then you can ignore rescaling it, but the entire solution is presented here for completeness.
Now as previously mentioned, the first part of this is achieved primarily by creating a fixed size canvas; this is done with any of the media selection switches and the addition of -dFIXEDMEDIA.
NOTE if you alter the media size, then you must, obviously, also alter the scale of the contents, or it won't fit. So you also need to set PSFitPage, EPSFitPage or PDFFitPage depending on the type of input (very recent versions of Ghostscript can use -dFitPage no matter what the input type).
As an experiment I used the file /ghostpdl/examples/text_graphic_image.pdf and sent the output to a printer on FILE:
This command line:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -sDEVICE=mswinpr2 -sOutputFile=%printer%KensPrinter /ghostpdl/examples/text_graphic_image.pdf
produces output where 3/4 the image is clipped away (the content lies off the newly defined fixed canvas size). If I modify that to:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -dPDFFitPage -sDEVICE=mswinpr2 -sOutptuFile=%printer%KensPrinter /ghostpdl/examples/text_graphic_image.pdf
then the result is a perfect reproduction of the original, at 1/4 the size (half in each direction).
So, the first thing you need to do is establish the actual printable area of the media on your printer, then you can set the width and height correctly as fixed media, and tell Ghostscript to scale the page to fit.
However, this will still leave the printed image at the bottom left of the media. Since that's in an area that can't be printed, you need to shift the printed image until its centred on the page. As I suggested, you can do this with a BeginPage procedure. This:
gswin32 -dDEVICEHEIGHTPOINTS=391 -dDEVICEWIDTHPOINTS=306 -dFIXEDMEDIA -dPDFFitPage -sDEVICE=mswinpr2 -sOutptuFile=%printer%KensPrinter -c "<</BeginPage {100 100 translate}>> setpagedevice" -f /ghostpdl/examples/text_graphic_image.pdf
produces output where the printed image is shifted up and right by 100 points each.
I believe that a little investigation will allow you to figure out where exactly your printer is able to print, and to create appropriately sized unprintable margins.
Note that, for me, the %printer% syntax does not result in a printer selection dialog. I suspect that your code (whatever language that is) is expanding the %p, resulting in a corruption of the name. Or possibly whatever you use to fork a Ghostscritp process does it. In either event you probably need to double the % signs.
You should get this working from the command line first, then work on getting it into an application.
Calling TextRenderer.MeasureText as follows:
TextRenderer.MeasureText(myControl.Text, myControl.Font);
and comparing the result to the size of the control to check if text fits. The results are sometimes incorrect. Have observed the following two issues:
Often when a Label is set to AutoSize, TextRenderer will report a width that is 1 pixel wider than the auto-sized width of the Control.
False negative where TextRenderer reports a width smaller than the control's but the text is still cut off. This occurred with "EstaciĆ³n de trabajo" -- not sure if the accent could somehow affect the width calculation?
Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?
I know it's probably no actual anymore. Yet for future readers here is a simple yet accurate method of measuring text in a control:
Graphics g=Graphics.FromHwnd(YOUR CONTROL HERE.Handle);
SizeF s=g.MeasureString("YOUR STRING HERE", Font, NULL, NULL, STRING LENGTH HERE, 1)
Is there any way to improve the accuracy of the MeasureText method? Should I be calling one of the overrides that accepts a device context and/or format flags?
You have answered your question by yourself. Actually MeasureText based on Win32 DrawTextEx, and this function cannot work without valid device context. So when you call MeasureText override without hdc, it internally create desktop compatible hdc to do measurement.
Of course measurement depends on additional TextFormatFlags. Also keep in mind that Label painting (and measurement) depends on UseCompatibleTextRendering.
So general conclusion you should use MeasureText for your own code, for example when you then call DrawText with exactly same parameters, in all other cases size returned by MeasureText cannot be treated as precise.
If you need to get expected Label size, you should use GetPreferredSize method.
Check out the TextFormatFlags parameter to this function:
TextRenderer::MeasureText(String, Font, Size, TextFormatFlags)
http://msdn.microsoft.com/en-us/library/8wafk2kt.aspx
"The Size, in pixels, of text drawn on a single line with the specified font. You can manipulate how the text is drawn by using one of the DrawText overloads that takes a TextFormatFlags parameter. For example, the default behavior of the TextRenderer is to add padding to the bounding rectangle of the drawn text to accommodate overhanging glyphs. If you need to draw a line of text without these extra spaces you should use the versions of DrawText and MeasureText that take a Size and TextFormatFlags parameter. For an example, see MeasureText(IDeviceContext, String, Font, Size, TextFormatFlags)."
hth
I don't know if I have a perfect solution but I ran into this when I was doing WinForms a few years back. The way I ended up compensating was by adjusting the returned measurement by a percentage. I cannot recall what I used (maybe 5% or 105?), but I do recall that I ended up using a constant percentage across the app and always rounded up.
I haven't got enough points to comment yet, so I've had to put this as an answer:
Perhaps ClearType affects measurement accuracy, because although a character has a known width calculated from its glyph, its rendering and position are adjusted to place axial lines on whole pixels.
Just a thought.
I've got a really simple setup - I have a string, a font and a font size on the ready. I want to render this to a Silverlight WriteableBitmap.
There's one catch - I want to be able to tell apart the letters in the rendered text. Ideally, I'd like to have a System.Windows.Rect for every rendered letter.
The problem is Silverlight's API, which is missing all of the useful stuff like Graphics.MeasureString, which I could have used to measure the letters separately.
What adequate options do I have to get the letters' measures in codebehind?
I sort of figured this out on my own. The solution is slow and far from perfect, but hey, it works!
The idea is to render the text many times, adding one letter at a time, and finding the difference between the current and previous TextBlock widths.
So, for example, if the text is "ab", we first render "a" and get its length. Then we render "ab" and find the difference, which should be the size of the rendered "b".
I wanted to show some mathematical expressions in a winforms textbox. So I thought the "Cambria Math" font would be a good choice but the text looked strange due the high top and bottom margin of the font. First I thought I made a mistake but according to this question, it's the correct behavior of the font.
Why does Cambria Math have these big margin values and how can I display my string correctly in the textbox like Word 2010?
(Note that I know only a little bit about typography ;)
Edit: I had to make the textbox that tall otherwise the caret would be invisible. The font size of the textbox is set to 8.25pt
Cambria Math uses Microsoft's mathematical OpenType extensions.
Word 2007 and later understand these and display the text with reasonable spacing.
However, notepad and Word 2000 display the text with enormous spacing, just like winforms. I guess the font has this much space by default because some characters (like U+2320, top half integral) are much larger than the alphanumerics.
If you use Cambria Math with a font engine (such as the one used by winforms) that doesn't understand the math extensions, you're going to get the big spacing.
If you're displaying simple expressions you might as well use Cambria.