Page 1 of 2

TRichView - Getting The Line Height

Posted: Thu Mar 21, 2013 4:19 pm
by Graham
Having got the text for a particular line, is there something I can call to get the height (in pixels) of the line as it is displayed on the screen.
If not, I can calculate it myself from the font sizes along the line, but is there any interline spacing between the rows of text?

Posted: Thu Mar 21, 2013 4:27 pm
by Sergey Tkachenko
Do you need line height when the document is formatted?
Do you need at the specified position of document?

Posted: Thu Mar 21, 2013 7:06 pm
by Graham
The document will have been formatted.

I will call the routine we discussed in an earlier message. So having got the text and a string containing the styles for each character, I now need the line height as it is displayed in the RichView component. I would like the full height of the line regardless of how much of the line is displayed. I can do a calculation myself base on GetTextMetric, but I need to know if you add any extra spacing between the lines over and above that returned by this.

Posted: Fri Mar 22, 2013 7:13 am
by Sergey Tkachenko
Ok, let's use the procedure from http://www.trichview.com/forums/viewtopic.php?t=5880
We need DNo1 and DNo2. They are indices in rve.RVData.DrawItems.
Top coordinates of drawing item (ditem = rve.RVData.DrawItems): ditem.Top-ditem.ExtraSpaceAbove
Bottom coordinates of drawing item: ditem.Top + ditem.Height + ditem.ExtraSpaceBelow
(ExtraSpaceBelow and ExtraSpaceAbove allow to take line spacing into account).

Additionally, there may be spacing between paragraphs, but since it is not belong to lines, it is not taken into account here.

Posted: Fri Mar 22, 2013 9:15 am
by Graham
I'll try this early next week. The ultimate goal of this particular task is to copy the text exactly as displayed in a RichView into a bitmap for subsequent processing. I have tried to use CopyRect from Canvas to Canvas and this works, but the resulting bitmap is not as per the original. I seem to be getting artifacts from the graphics. If I write the text directly to the bitmap its perfect.

Posted: Fri Mar 22, 2013 9:50 am
by Graham
Actually just tried it now. Looks OK. Under what circumstances does

ditem.ExtraSpaceBelow or ditem.ExtraSpaceAbove become > 0

The dItem.Height matches the TextMetric tmHeight. Do you ever account for tmExternalLeading or is this not applicable here.
In my test I have am using Arial, Size = 64 and the tmExternalLeading = 3

Posted: Fri Mar 22, 2013 1:53 pm
by Sergey Tkachenko
TRichView ignores font's external leading.
ExtraSpaceBelow and Above may be non-zero because of line spacing (for example, "double" line spacing increases ExtraSpaceBelow)

For your task, consider using TRVReportHelper to draw onto a bitmap. If you specify the same width as in TRichViewEdit, results must be identical.

Posted: Wed Mar 27, 2013 12:18 pm
by Graham
So now I am experimenting with TRVReportHelper.

I have created text of all sorts of sizes colours etc. in a RichView. I now want to use ReportHelper to format the data into pages that are 128 pixels high. It nearly works as I would like, but I may be doing something wrong.

Let's say a typical text line is 80 pixels high. What I would like in page 1 of ReportHelper is the first line and about half of the second line. Page 2 of the ReportHelper would contain the second half of line 1 and some of line 2 etc.

What I get is a single line in each page of the ReportHelper. So when I reconstruct that data into a large bitmap, the lines of text are separated by large gaps.

Is this a feature or am I doing something wrong?

Posted: Wed Mar 27, 2013 2:00 pm
by Graham
Basically I think the FormatNextPage routine is only working on whole lines. Is it possible to not have it do this, but just fit all it can into the specified height?

Posted: Thu Mar 28, 2013 8:25 am
by Sergey Tkachenko
Formatting up to the specified height is not supported yet, sorry.

Posted: Thu Mar 28, 2013 1:36 pm
by Graham
That's unfortunate because it would have been a perfect solution to my problem.

So I have to attempt to perfect my previous method of using:

rve.GetItemAt(X, currentScrollY, RVData, ItemNo, OffsetInItem, False);

tStr := GetSpecifiedLineText(rve, ItemNo, OffsetInItem, sStr, LineHeight);

As you will remember I am trying to get the text as it is displayed in RichView at a particular offset from the top of the display.

GetSpecifiedLineText is our new function to return the text, the line height and a string (sStr) containing the style numbers for each character.

The problem I now have is that this doesn't always work. Usually the value of X is set to 0, but sometimes I have to set it to the end of the line, 668 in my case. And sometimes I have to increment the OffsetInItem before calling GetSpecifiedLineText, otherwise the string returned is empty.

Any clues?

Posted: Thu Mar 28, 2013 2:04 pm
by Graham
Setting the final parameter of GetItemAt to TRUE, seems to help, but creates other issues which I am investigating.

Posted: Thu Mar 28, 2013 4:21 pm
by Graham
The problem I have now is that the new routine only returns the first word of the displayed line.

The start of the new routine is almost a copy of "GetCurrentLineText":

rve.RVData.Item2DrawItem(ItemNo, OffsetInItem, DNo1, DOffs, rvdpBetterBelow);
DNo2 := DNo1+1;
while not rve.RVData.DrawItems[DNo1].FromNewLine do
dec(DNo1);

while (DNo2<rve.ItemCount) and not rve.RVData.DrawItems[DNo2].FromNewLine do
inc(DNo2);

dec(DNo2);


The calculation of DNo2 does not seem to be correct. DNo2 and rve.ItemCount do not refer to the same things do they?
I am getting DNo2 values far greater than ItemCount.


This works, but now I have no limit detection for the end stop!

while (not rve.RVData.DrawItems[DNo2].FromNewLine) do
inc(DNo2);


What is the relationship between Items and DrawItems?

Posted: Fri Mar 29, 2013 11:38 am
by Sergey Tkachenko
You are right, this is a bug. It must be

Code: Select all

while (DNo2<rve.RVData.DrawItems.Count) and not rve.RVData.DrawItems[DNo2].FromNewLine do 
// is you set Strict=True for GetItemAt, the function would return the item only if it is exactly at the given location; if you "miss", it does not return any result. If Strict=False, it returns the closest item, so it never fails.

Posted: Thu Apr 04, 2013 2:21 pm
by Graham
OK, now how do I get the height of a Blank line. Rve.GetItemAt returns an item number of -1