Line numbers for soft-wrapped styled text?
Alex Tweedly
alex at tweedly.net
Tue Mar 28 19:28:02 EDT 2017
On 28/03/2017 22:11, hh via use-livecode wrote:
> Hi Alex,
> below you will find a tested binary search for the visible lines which
> uses item 4 of the formattedRect for the topLine and item 2 of the
> formattedRect for the bottomLine.
That's great - thank you.
However, I do have a couple of questions :
1. this uses a linear-interpolation for its initial guess for the
topline (i.e. the percentage, set to vs / formattedheight). This is good.
But it then uses that same value of percentage for the initial guess of
the bottomline - which seems totally wrong. Should it not use a
different percentage
(specifically, the height of the field / (formattedheight - vs) with
maybe a minor tweak for margins) for starting on the bottomline calculation?
2. After the initial percentage calculation, all the recursive calls
just revert to simple binary search (i.e. percentage = 0.5).
Since the initial one is just an estimate, and can be thrown off by
variable line heights, this initial guess could be on the "wrong" side
of the actual answer - and hence all the rest of the recursive
iterations are done this "slow" way.
Why not recalculate the percentage for each recursive call ?
3. not so much a question as a bit of philosophical question ....
is a line "visible" if it occupies screen real-estate but has no
visible pixels on the screen ?
i.e. the formattedRect has the same problem (if it is a problem) with
spacebelow as I mentioned earlier for formattedheight, so if the top
line within the visible field consists solely of the spacebelow a line,
then that line will not be included in the visibleTextLines().
Like I said, that's probably a philosophical question - but it does have
implications for how one could then set up the lineNumbers field; I
think you have to start it on the line before the "topline" form this
calculation, and then set the vscroll of the linenumbers field to match
the formattedrect of the next line of the original field (because you
can't set a negative vscroll value, so this is needed to push the first
visible line number downwards).
> TMHO your method is so fast for visible lines of a field on usual
> screensizes only that you could do that for each single of these lines.
>
> The spaceBelow issue you describe has probably the (inavoidable) reason
> of LC's ignoring a last linedelimiter in nearly all cases.
>
> ## The script is part of the result of a thread BerndN and I had once
> ## in the forum about the visible text of a styled field.
> -- Determining the visible text lines of a field (may be styled).
> -- pT = the short name of the field
> function visibleTextLines pT
> lock screen; lock messages
> put the vscroll of fld pT into vs
> put the scrollbarWidth of fld pT into sw
> put the margins of fld pT into m
> put (m,m,m,m) into m -- now we have always at least 4 items
> -- 5 is the minimum textsize
> put 4 + (item 2 of m) + (the top of fld pT) into t
> put -4 - (item 4 of m) + (the bottom of fld pT) into b
> if the hscrollbar of fld pT then subtract sw from b
> put the num of lines of fld pT into n
> put vs/(the formattedHeight of fld pT) into pct
> put findTopLine(pT,pct,t-5,1,n) into L1
> put findBottomLine(pT,pct,b+5,max(1,L1-1),n) into L2
> return (L1,L2)
> end visibleTextLines
>
> -- percentage p% is a percentage of 1, for example p=0.5 (for 50%)
>
> -- p=%, x=bott of fld pT, n1=start, n=max
> function findTopLine pT,p,x,n1,n
> put n1+trunc((n-n1)*p) into m
> if item 4 of the formattedRect of line (m+1) of fld pT >= x then
> if item 4 of the formattedRect of line m of fld pT < x then
> return m+1
> else
> if m <= n1 then return n1
> else return findTopLine(pT,0.5,x,n1,m-1)
> end if
> else
> if m>=n then return n
> else return findTopLine(pT,0.5,x,m+1,n)
> end if
> end findTopLine
>
> -- p=%, x=bott of fld pT, n1=start, n=max
> function findBottomLine pT,p,x,n1,n
> put n1+trunc((n-n1)*p) into m
> if m<n1 then return n1; else if m >n then return n
> if item 2 of the formattedRect of line (m+1) of fld pT > x then
> if item 2 of the formattedRect of line m of fld pT <= x then
> return m
> else return findBottomLine(pT,0.5,x,n1,m-1)
> else return findBottomLine(pT,0.5,x,m+1,n)
> end findBottomLine
>
> There is a bit of a problem I encountered trying to code this up.
>
> I'm not 100% sure yet if it's a bug, though I think it must be. Comments
> anyone ?
>
>
>> Alex T. wrote:
>> If I set the 'spacebelow' of the last (Nth) line of a field, and get the
>> formattedheight of the field, that includes the spacebelow value just set.
>>
>> However, none of
>> the formattedheight of line N of fld ...
>> the formattedheight of line 1 to N of fld ...
>> the formattedheight of line 1 to -1 of fld ...
>> include it. The same is true of 'internal' lines - it's not just the
>> last one in the field - the formattedheight of a chunk doesn't include
>> any spacebelow set on the last line of the chunk.
>>
>> This makes it near impossible to use a binary search accurately (or
>> indeed to reliably use "the formattedheight of chunk xx of fld yy").
>>
>> So now that I've describe it like that, I'm pretty sure it is a bug ....
>> but comments welcome before I report it.
>>
>> -- Alex.
> _______________________________________________
> use-livecode mailing list
> use-livecode at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
More information about the use-livecode
mailing list