fastest way to "fill" a RichViewEdit

General TRichView support forum. Please post your questions here
Post Reply
David.Brenner
Posts: 12
Joined: Sat Nov 05, 2011 6:24 pm

fastest way to "fill" a RichViewEdit

Post by David.Brenner »

Hi.
I want to "fill" a RichViewEdit with text from another RichViewEdit until it has maximum height but without exceeding the height of the window (of the first RichViewEdit).

I do this:

Code: Select all

var Stream: TStream;
i: Integer;
begin
   Rve1.BeginUpdate;
   Rve1.UndoLimit := 0;
   Rve2.BeginUpdate;
   while True do
   begin
      Stream.Clear;
      //copy the text from the second RichViewEdit
      Rve2.SetSelectionBounds(Item1, Offs1, Item2, Offs2);  
      Rve2.SaveRVFToStream(Stream, True);
      //load the text in the first RichViewEdit
      Stream.Position := 0;
      Rve1.Clear;
      Rve1.DeleteUnusedStyles(True, True, True);
      Rve1.LoadRVFFromStream(Stream);
      //I increase the size of the text
      for i := 0 to Rve1.Style.TextStyles.Count - 1 do
         Rev1.Style.TextStyles[i].Size := Round(1.5 * Rve1.Style.TextStyles[i].Size);
      Rve1.Format;
      if (Rve1.DocumentHeight >= Rve1.Height) or (//no more text to add) then
         Break;
      //here I decrease Item1/Offs1 and I increase Item2/Offs2 (with the same "step")
      ...
   end;
   Rve1.EndUpdate;
   Rve1.UndoLimit := -1;
   Rve2.EndUpdate;
end;
The problem is that is kind of slow (15..20 sec in average on fast computers). But I need to be as fast as possible (under 1 sec on slow computers).
One way is to increase the size of the "step" (how much I decrease Item1/Offs1 and increase Item2/Offs2). But I can't increase it much because the result will not be so "accurate".
Another way is to use a method called "double and/or half of the interval": first I double the "step" until Rve1.DocumentHeight > Rve1.Height. Then I use the interval between the previous value and the current value: I "chop" it into 2 until I found the best value possible.
It helped, but just a little.

Maybe someone knows a better way...
Thank you in advance for your help.

Best regards, David Brenner
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Unfortunately, it's impossible to predict how a text size affects size of arbitrary document.
I can suggest to move the document loading outside the cycle, store the original values text sizes in some list or a dynamic array.
In the cycle, call only a text size changing and Format.
But I am afraid that Format is the slowest part here...
David.Brenner
Posts: 12
Joined: Sat Nov 05, 2011 6:24 pm

Post by David.Brenner »

Thank you for your suggestion but the document is from the user's computer so I can't generate them and store them without making him wait a very long time.
Or do you talk about something else...?

I just noticed something: if I use CopyRVF and PasteRVF instead of SaveRVFToStream and LoadRVFFromStream it works 27% faster.
I wonder why...
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

May be you use TMemoryStream?
Use TRVMemoryStream instead (RVClasses.pas). It's faster.
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

As I understand, you save and load the same document inside cycle. It will be faster if you do it one time before the cycle.
David.Brenner
Posts: 12
Joined: Sat Nov 05, 2011 6:24 pm

Post by David.Brenner »

With TRVMemoryStream is only 13% faster.
And I don't load and save the same document in Rve1 because Item1, Offs1, Item2, Offs2 are changing inside the cycle so it's a different text every time. More, they are changing when another document is loaded or when the user is choosing another "portion" of the document.
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Do RVE2 and RVE1 have the same width?
If yes, you can use item coordinates in RVE2.
David.Brenner
Posts: 12
Joined: Sat Nov 05, 2011 6:24 pm

Post by David.Brenner »

Unfortunately they don't.
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Well, you can format Rve1 with a large part of a document, more than Rve1.Height.
Then you can use item coordinates to calculate the necessary part, see http://www.trichview.com/help/idh_trich ... rdsex.html
David.Brenner
Posts: 12
Joined: Sat Nov 05, 2011 6:24 pm

Post by David.Brenner »

Yes, this could work faster :)
Thank you.
I will test.

PS: I just noticed that Format is not the slowest but SaveRVFToStream and LoadRVFFromStream are (over 90%). How did I noticed: in editor I erased half of the text and tried the function. Same time. With the previous text size I erased again half, saved the file, reloaded; this time the function was about a few times faster. So I checked and indeed SaveRVFToStream and LoadRVFFromStream are very slow on big texts.
On a 360 pages text I selected a few items, I used SaveRVFToStream and then I saved the content of the stream directly in a file: 808 096 bytes.
I erased half of it (not the part where these items are), saved and reloaded; I selected exactly the same items, used SaveRVFToStream and saved again the content in a file: 104 769 bytes.
Why this difference, since when I look directly at the text in a RichViewEdit I don't see any difference?
With SaveRTFToStream and LoadRTFFromStream I get 2047 and 2048 bytes. The files are basically the same.
But with these functions something isn't working well and I get less text in Rve1.
Sergey Tkachenko
Site Admin
Posts: 17569
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Probably, document contains too many unused styles, and they are removed by DeleteUnusedStyles.
Post Reply