Is there a way to make this faster by writing in Java and making a library?

NFOBoy

Active Member
Licensed User
Longtime User
So I discovered (thanks to Margret's CToast Class) that I can use a reflector on a view and use getWidth and getHeight to much, much more accurately figure out desired fontsize for views at run time over a canvas MeasureStringWidth or measurestringheight property.

(especially for other languages besides English, such as Thai)

However, the only way I can see to use those properties in a loop (to zero in on the correct size), is to call DoEvents after each run thru the loop, which involves resizing and drawing the View (I do it offscreen, so the user doesn't see it)

This results, (with my binary sort approach), in about a 250 millisecond time for each view that needs to be calculated. Whereas I could do 6 at once with the Canvas method in under 100 milliseconds

Anybody know a way to cut this down, and I think that really means to get rid of the DoEvents, but I don't know how to pull that off with b4a, and not sure if it could be done in a library call in java, but hopefully someone with a bit more savvy can point me down the right path.

Here's the code I'm using

B4X:
Sub newSetFontSizeLabel(theLabel As Label, someText As String, desiredFont As Typeface, someActivity As Activity, dummyLabel As Label) As Float


dummyLabel.Text = someText
dummyLabel.Typeface = desiredFont

Dim r As Reflector
r.Target = dummyLabel
Dim newWidth, newHeight As Float

newWidth = r.RunMethod("getWidth")
newHeight = r.RunMethod("getHeight")


'want to try a binary tree here
Dim LowNumber, HighNumber As Float
Dim middleSize As Float
LowNumber = 1
HighNumber = 200
middleSize = (HighNumber + LowNumber)/2




dummyLabel.Width = -2
dummyLabel.Height = -2
dummyLabel.TextSize = HighNumber
DoEvents

newWidth = r.RunMethod("getWidth")
newHeight = r.RunMethod("getHeight")

'First Find High Number


Do While newWidth/theLabel.Width < 1 AND newHeight/theLabel.Height < 1
   LowNumber = (middleSize + LowNumber)/2
   HighNumber = HighNumber * 2
   middleSize = (LowNumber + HighNumber)/2
   dummyLabel.Width = -2
   dummyLabel.Height = -2
   dummyLabel.TextSize = HighNumber
   DoEvents

   newWidth = r.RunMethod("getWidth")
   newHeight = r.RunMethod("getHeight")
Loop
   
   dummyLabel.Width = -2
   dummyLabel.Height = -2
   dummyLabel.TextSize = middleSize
   DoEvents

   newWidth = r.RunMethod("getWidth")
   newHeight = r.RunMethod("getHeight")

'look at the size of the textbox against the height and width of the requirement
'if within and below some percentage, should be good enough


Do While newWidth/theLabel.Width >= 1 OR newHeight/theLabel.Height >= 1 OR (newWidth/theLabel.Width < .98 AND newHeight/theLabel.Height < .98)
   If newWidth/theLabel.Width >= 1 OR newHeight/theLabel.Height >= 1 Then
       'this means the middlesize is now the new highnumber
      HighNumber = middleSize
   Else
      LowNumber = middleSize
   End If
   
   If LowNumber/HighNumber > .98 Then 'this catches case where it misses sometimes
      Return LowNumber
   End If
   'Log("ratio: " & (LowNumber/HighNumber))

   
   middleSize = (HighNumber + LowNumber)/2
   dummyLabel.Width = -2
   dummyLabel.Height = -2
   dummyLabel.TextSize = middleSize
   DoEvents

   newWidth = r.RunMethod("getWidth")
   newHeight = r.RunMethod("getHeight")
   
Loop
   
Return dummyLabel.TextSize

End Sub
 

NFOBoy

Active Member
Licensed User
Longtime User
Hrmm,

Ok, before I rack my brain with the java/library building thing, in looking at the documentation, it appears that getwidth/getheight do cause the OS to size the view.

If I do similar to this in a library in Java, does the view have to be resized using a similar call as DoEvents (during the sizing loops)? Or when the view is sent a resize, then I would just be able to execute the getwidth/getheight commands?

If it does have to have a DoEvents type of command, then I would think there is not much to gain (not like cutting it down to under 50-75 milliseconds per view, which is what I would like to get it to)

Ross

(unfortunately, after having tried this, it is just SO much better at getting to a very nice size for variable length String's, especially when the View's can have different languages going to them, so if I can figure out how to do this quickly enough... I would be very happy)
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
There is no equivalent DoEvents method in Java. You will need to build this algorithm differently in Java. My guess that it will not be faster. The reflection calls overhead is insignificant in this case (assuming that the number of iterations is not too high).

Setting the text size causes most of the views to remeasure and relayout themselves.
 
Upvote 0

NFOBoy

Active Member
Licensed User
Longtime User
Erel,

that answers that! Since it is a binary sort, it gets the job done each time in about 7-8 loops. Maybe I can narrow down the scope with canvas measureHeight/Width first, then hopefully get it to 3 or 4 with the Reflector calls.

This might get it to under 150....
 
Upvote 0
Top