Suggestion: RenderWidth / RenderHeight function

Knowledge exchange related to the VPE Report Engine and PDF Library

Moderator: IDEAL Software Support

Suggestion: RenderWidth / RenderHeight function

Postby Brent Rose » Mon Dec 17, 2012 12:43 am

The Problem: eg If I wish to determine the width of a string to see if it will fit on a single line, I can calculate the line height and use RenderWrite with Right = VFREE something like this:

Code: Select all
   RenderWrite(0.0, 0.0, PageWidth, VFREE, 'X');

   RenderWrite(0.0, 0.0, VFREE, nRenderHeight, MyString);

   WidthOfMyString := nRenderWidth;


However, RenderWrite will honour the defined page width and return a result reflecting only what text fits within the page width. Effectively, ALL strings will thus return an answer suggesting they will fit on one line. To get an accurate result, I need to specify a negative LEFT value to guarantee sufficient overall "virtual page width" to accommodate more than the actual page width...

Suggestion: Add a "RenderWidth" function (with implied Right = VFREE), say, that returns an "actual" width using the current font WITHOUT the page width constraint. Similarly, a RenderHeight function (with implied Bottom = VFREE) WITHOUT the page height constraint. Both would otherwise work the same as the existing RenderWrite.

Another approach might be to use, say, a "VPAGEFREE" constant instead - meaning it is free of the page constraint as well.
Brent Rose
 
Posts: 50
Joined: Wed Mar 21, 2012 8:13 pm

Re: Suggestion: RenderWidth / RenderHeight function

Postby IDEAL Software Support » Mon Dec 17, 2012 1:09 pm

If I understand correctly, you wish to compute the total width of a given text, when the text is formatted on a single line - and regardless of the current page width.

Whilst I do not understand what this is good for - because at the end you will have to layout your text within an existing page, and therefore within existing page boundaries - you could workaround this problem by using a temporary second document. For this document, specify the page width up to the numerical limit, which is 2147 centimeters (or 21.47 meters). You can then render the width of your text on a single line in the second document. Maybe this helps.
IDEAL Software Support
 
Posts: 1633
Joined: Thu Nov 18, 2004 4:03 pm

Re: Suggestion: RenderWidth / RenderHeight function

Postby Brent Rose » Mon Dec 17, 2012 10:13 pm

If you want to print as much of a string as you can on a single line WITHOUT wrapping, you need to measure the string word-by-word until it EXCEEDS the required width...

...if this required width = full page width, then you will hit the issue described. As mentioned, a negative LEFT value resolves the issue, rather than using a second document, but this does not seem an "ideal" way to get the result. Hence the "suggestion".

Be that as it may, a width function that measures the string width unconditionally (rather than truncating at page width) is what I am referring to. Ditto height. In other words, an absolute width and absolute height function.

What is this good for?

Well, an absolute width is fundamental to gaining full text wrapping control (viz where you need to be able to print part of a string or print line-by-line and still have full reference to any "remaining text" for output on another page or some other location - like wrapping around another object etc).

If you wanted to know whether a block of text was going to take another page to output or not, an absolute height measurement is required - otherwise, if it was a big enough text block, you would get a false answer from the existing Render functions (because the answer is not strictly the text height, but rather the height of the text-that-will-fit on the page).

I encountered this issue as a bug in my code - text wrapping worked most of the time, but sometimes VPE was telling me a string would fit when it really didn't!
Brent Rose
 
Posts: 50
Joined: Wed Mar 21, 2012 8:13 pm

Re: Suggestion: RenderWidth / RenderHeight function

Postby IDEAL Software Support » Tue Dec 18, 2012 11:29 am

I have some difficulties to follow your complex use-case, but let me try to figure it out. You want to compute what amount of text, i.e. the number of characters, that fit into a given width without causing a line break. Is that correct?

If so, you can simply do the following:

- First, compute the height of a single line of text for the currently selected font:
Doc.RenderPrint(0, 0, "X");
double SingleLineHeight = Doc.nRenderHeight;

- For any given text, call:
double max_allowed_width = <any width you wish, can be done in a second document to overcome page boundaries>
Doc.RenderWrite(0, 0, - max_allowed_width, Doc.nFree, your_text);

This instruction computes the height of your_text within max_allowed_width.
(Please note the "-" minus sign in front of max_allowed_width, which denotes a width, instead of an absolute coordinate.)

To test whether the given text causes a line break:
if (Doc.nRenderHeight > SingleLineHeight)
yes, here we go

In an iterative loop you can then shorten your_text, until no line break is caused. For better performance, you could break your text into an array of words first, and use some kind of binary search algorithm to find the point in your text where the line break occurs (assuming you wish to break your text at word boundaries).
IDEAL Software Support
 
Posts: 1633
Joined: Thu Nov 18, 2004 4:03 pm

Re: Suggestion: RenderWidth / RenderHeight function

Postby Brent Rose » Tue Dec 18, 2012 8:46 pm

Thanks for your response :-) Yes, I am "line breaking by word" to obtain a single line of text.

My procedure just iterates through the words in a line, testing the width until it exceeds the desired target width.

Your suggestion of arbitrarily specifying an extended print width using a negative RIGHT is another way to ensure the answer is not distorted by a page limit - I hadn't thought of that. However, I suspect it is not really any different, in effect, from specifying a negative LEFT as I am doing now - the principle is the same.

This leaves two approaches to "getting a single line of text" (leaving aside the idea of optimising either procedure with a binary word-break search for now):

1. Iterate the word breaks testing the output width as you go until it exceeds the required width (then accept the previous word break)

2. Iterate the word breaks until the rendered height for the given width exceeds 1 line (then accept the previous word break)

Aside from option 2 not being affected by the "width truncation issue", I am not sure that either method would be significantly more efficient than the other.

Anyway, this post was not so much about a solution to the issue of identifying lines-of-text as such, but rather about the usefulness of functions that returned a "true" width or height value WITHOUT page margin truncation. eg If a string is 1 metre wide, I want to know that it is 1 metre wide - not 21 cm wide because that is my page size.

Here's another example to illustrate the point:

A report includes output of a "description" or memo field of plain text. Generally, I want to keep the description together on 1 page rather than wrap it (so I'll force a new page before outputing this record if necessary), but, if the field is exceptionally long, I may wrap it rather than leave too much blank space on the current page... There would be an arbitrary algorithm to decide how to handle the text in any given case.

To achieve this, I must know the absolute height of the memo text - I cannot have the answer complicated by the possibility of truncation by a page boundary.

Yes, certainly, I can achieve this reasonably safely by "tricking the page bouandaries" as above - but it would be a lot simpler not to have to worry about this at all, and just obtain an absolute height directly...
Brent Rose
 
Posts: 50
Joined: Wed Mar 21, 2012 8:13 pm

Re: Suggestion: RenderWidth / RenderHeight function

Postby IDEAL Software Support » Wed Dec 19, 2012 9:21 am

Just to make things clear for other readers of this thread:

The API of Virtual Print Engine allows to compute:

- the height of text for a given width
- the width of text for a given height
- the width and height of text

This is done within the current page boundaries, and this is what 99.9% of all users require.

The computations can also be performed within a second temporary document - as suggested here - where you specify very large page dimensions up to the numerical limit. This option covers your special use-case.

We are not going to change anything of the Rendering-API in the forseeable future.
IDEAL Software Support
 
Posts: 1633
Joined: Thu Nov 18, 2004 4:03 pm


Return to VPE Open Forum

Who is online

Users browsing this forum: No registered users and 4 guests

cron