Software Defining Maximum Matching in a Text Box (WP7)

I am currently writing a book for Windows Phone Seven, and I am trying to style it as a Kindle reader. To do this, I need to break the books into pages, and it will be much more difficult when adding font sizes.

To do this at the moment, I just add the word at a time in the text block until it gets above its container. As you can imagine, with a document of more than 120,000 words, this takes an unacceptable period of time.

Is there a way to find out when the text will exceed the borders (logically dividing it into pages) without actually having to render it? That way, I could run it in the background thread so that the user can continue to read at the same time.

So far, the only idea that has arisen with me is to find out how the text block accepts its estimates (in a measure call?), But I have no idea how to find this code, because the reflector did not show anything.

Thanks in advance!

+5
source share
4 answers

I am doing something similar to adjust the font size for individual text fields (so that they all fit). Basically, I create a TextBlock in the code, set all my properties and check the ActualWidth and ActualHeight properties. Here are some pseudo codes to help solve your problem:

public static String PageText(TextBlock txtPage, String BookText) { TextBlock t = new TextBlock(); t.FontFamily = txtPage.FontFamily; t.FontStyle = txtPage.FontStyle; t.FontWeight = txtPage.FontWeight; t.FontSize = txtPage.FontSize; t.Text = BookText; Size Actual = new Size(); Actual.Width = t.ActualWidth; Actual.Height = t.ActualHeight; if(Actual.Height <= txtPage.ActualHeight) return BookText; Double hRatio = txtPage.ActualHeight / Actual.Height; return s.Substring((int)((s.Length - 1) * hRatio)); } 

The above is untested code, but hopefully you can get started. Basically, he sees if the text can fit in the box, if that's good for you. If not, he will find out what percentage of the text can fit and return it. This does not take into account word breaks and may not be a perfect match, but should close you.

You can modify this code to return the length, not the actual substring, and use it as the size of your page. Creating a text block in code (without display) actually does pretty well (I do this in some table views without noticeable lag). I would not send all 120,000 words to this function, but a reasonable subset of some kind.

Once you reach your ideal length, you can use RegEx to split your book into pages. There are examples on this RegEx site that break word boundaries after a certain length.


Another option is to calculate the page size in advance for each potential fontsize (and hard code using the switch statement). This can easily go crazy if you allow any fonts and any combination of sizes, and it would be awful if you allowed mixed fonts / sizes, but you did very well. Most likely, you have a certain range of readable sizes and just a few fonts. Creating a test application to calculate the page text length for each of these combinations would not be so difficult and, possibly, would make your life easier - even if it is not "correctly" perceived as a programmer :)

+3
source

From what I see, the Kindle app seems to use a similar algorithm for the one you offer. Note:

  • it usually shows the% position through the book - it does not show the total number of pages.

  • if you change the font size, the first word on the page will remain the same (so that where% appears) - so the Kindle application just makes one page the cost of the retransmission, assuming the first word the page remains the same.

  • if you change the font size and then go to the first page, then there really is a gap - they again pull the contents forward to fill the first page.

Based on this, I suggest you not to index the entire book. Instead, just focus on the current page based on β€œany position” (for example, the number of characters is displayed as a percentage). If you need to do something in the background thread, just look at the next page (and possibly the previous page) so that scrolling can be more responsive.

Further, to optimize your experience, there are several changes that you could make to your current algorithm, which you could try:

  • try using a different starting point and a search step for your algorithm - no need to start with one word and then add only one word at a time.

  • Assuming most of your books are ASCII, try caching the width of the common characters, and then work out the width of the text blocks yourself.

In addition, I would also really like to try using <Run> blocks in your TextBlock - it may be possible to get the relative position of each Run in a TextBlock, although I still haven't succeeded.

+4
source

I did not find a link to this example from Microsoft: "Pagination Principles."

Windows Phone has an interesting code example.

http://msdn.microsoft.com/en-us/magazine/hh205757.aspx

You can also watch this article on Page Transitions in Windows Phone , as well as the final touches in the E-Book project .

The code is available for download: http://archive.msdn.microsoft.com/mag201111UIFrontiers/Release/ProjectReleases.aspx?ReleaseId=5776

+1
source

You can request the FormattedText class, which is used by AFAIK inside a textBlock. since this is the class used to format text in preparation for rendering, it is the most accessible class of the lower level and should be fast.

0
source

Source: https://habr.com/ru/post/894347/