librelogo/source/LibreLogo/LibreLogo.py |   20 ++++++++++++++++++++
 sw/qa/uitest/librelogo/run.py           |   22 +++++++++++++++-------
 2 files changed, 35 insertions(+), 7 deletions(-)

New commits:
commit e50f0f7342c5618196507771e5f4eb79147477b9
Author:     László Németh <[email protected]>
AuthorDate: Fri Dec 2 18:06:17 2022 +0100
Commit:     László Németh <[email protected]>
CommitDate: Mon Dec 5 16:15:20 2022 +0000

    tdf#105575 LibreLogo: speed up by lock (re)paint
    
    Speed up program execution by default partial
    locking of repaint and custom locking of paint,
    using UNO lockControllers().
    
    – Default: speed up LABEL and TEXT by locking their repaint
      during the various text operations, i.e. setting size and
      text portion formatting changes were visible, and slow.
      Locking while manipulating a shape was suggested by Noel Grandin.
    
    – Custom: SLEEP command with negative argument calls lockControllers(),
      SLEEP command with not negative argument (and program termination)
      call unlockControllers(), so it's possible to lock program parts to
      speed up program execution e.g. 3-4 times or more. For example:
    
      ; lock paint until program termination
      SLEEP -1
      program
    
      or
    
      ; lock until SLEEP 0
      SLEEP -1
      commands_without_paint
      SLEEP 0 ; unlock a single level and paint/repaint everything
    
    – Add __get_time__() command to get the elapsed time from
      program start for profiling.
    
    Add unit tests.
    
    Note: custom locking with SLEEP has known problems: not connected
    lines, bad position of arc/pie, non-working CLEARSCREEN.
    
    Note: The reported code is more than 32 times faster (4 sec vs 2.2 min)
    with custom locking, also using the commented line to show not only
    the result with 400 circle shapes, but the partial result with 100,
    200 and 300 shapes, too:
    
    SLEEP -1
    REPEAT 400 [ CIRCLE 10 + REPCOUNT/10 FORWARD 5 + REPCOUNT/10 LEFT 10 ]
    ; IF REPCOUNT % 100 == 0 [ SLEEP 0 SLEEP -1 ] ; to show partial result
    SLEEP 0
    PRINT __get_time__()
    
    Change-Id: I51f71b0143178e6d35ecced92a59525184392d17
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143640
    Tested-by: László Németh <[email protected]>
    Reviewed-by: László Németh <[email protected]>

diff --git a/librelogo/source/LibreLogo/LibreLogo.py 
b/librelogo/source/LibreLogo/LibreLogo.py
index 562095a15383..ccd504eba021 100644
--- a/librelogo/source/LibreLogo/LibreLogo.py
+++ b/librelogo/source/LibreLogo/LibreLogo.py
@@ -479,6 +479,9 @@ def __translate__(arg = None):
         selection.getStart().BreakType = 4
     __dispatcher__(".uno:ZoomPage")
 
+def __get_time__():
+    return __time__.process_time() - _.start_time
+
 class LogoProgram(threading.Thread):
     def __init__(self, code):
         self.code = code
@@ -535,7 +538,10 @@ class LogoProgram(threading.Thread):
                 parent = _.doc.CurrentController.Frame.ContainerWindow
                 MessageBox(parent, "Document objects with%s script events" % 
[" possible", ""][secid-1], "LibreLogo program can't start", "errorbox")
             else:
+                _.start_time = __time__.process_time()
                 exec(self.code)
+                while _.doc.hasControllersLocked():
+                    _.doc.unlockControllers()
             if _.origcursor[0] and _.origcursor[1]:
                 __dispatcher__(".uno:Escape")
                 try:
@@ -544,6 +550,8 @@ class LogoProgram(threading.Thread):
                     
_.doc.CurrentController.getViewCursor().gotoRange(_.origcursor[0].getStart(), 
False)
         except Exception as e:
             try:
+              while _.doc.hasControllersLocked():
+                  _.doc.unlockControllers()
               TRACEPATTERN = '"<string>", line '
               message = traceback.format_exc()
               l = re.findall(TRACEPATTERN + '[0-9]+', message)
@@ -834,6 +842,8 @@ def stop(arg=None):
     global __halt__
     with __lock__:
         __halt__ = True
+    while _.doc.hasControllersLocked():
+        _.doc.unlockControllers()
     return None
 
 def home(arg=None):
@@ -1401,6 +1411,7 @@ def __get_HTML_format__(orig_st):
 
 def text(shape, orig_st):
     if shape:
+        _.doc.lockControllers()
         # analyse HTML
         st, formatting, extra_data = __get_HTML_format__(orig_st)
         shape.setString(__string__(st, _.decimal))
@@ -1460,8 +1471,17 @@ def text(shape, orig_st):
                 prev_format = i
                 if len(extra_data) > 0:
                     prev_extra_data = extra_data.pop(0)
+        _.doc.unlockControllers()
 
 def sleep(t):
+    if t < 0:
+        # lock shape repaint, if SLEEP argument is negative
+        _.doc.lockControllers()
+        return
+    else:
+        # otherwise unlock one level
+        if _.doc.hasControllersLocked():
+            _.doc.unlockControllers()
     _.time = _.time + t
     __removeshape__(__ACTUAL__)
     for i in range(int(t/__SLEEP_SLICE_IN_MILLISECONDS__)):
diff --git a/sw/qa/uitest/librelogo/run.py b/sw/qa/uitest/librelogo/run.py
index 6bcca4ade8a8..a7f2d0aa2529 100644
--- a/sw/qa/uitest/librelogo/run.py
+++ b/sw/qa/uitest/librelogo/run.py
@@ -100,7 +100,10 @@ x 3 ; draw only a few levels
             # new shape + previous two ones = 3
             self.assertEqual(document.DrawPage.getCount(), 3)
 
-   def test_LABEL(self):
+   def check_label(self, hasCustomLock):
+        sLock = "CLEARSCREEN "
+        if hasCustomLock:
+            sLock = sLock + "SLEEP -1 "
         with self.ui_test.create_doc_in_start_center("writer") as document:
             xWriterDoc = self.xUITest.getTopFocusWindow()
             xWriterEdit = xWriterDoc.getChild("writer_edit")
@@ -109,7 +112,7 @@ x 3 ; draw only a few levels
 
             #1 run a program with basic LABEL command
 
-            type_text(xWriterEdit, "LABEL 'Hello, World!'")
+            type_text(xWriterEdit, sLock + "LABEL 'Hello, World!'")
             self.logo("run")
             # wait for LibreLogo program termination
             while xIsAlive.invoke((), (), ())[0]:
@@ -123,7 +126,7 @@ x 3 ; draw only a few levels
 
             #2 check italic, bold, underline + red and blue formatting
 
-            document.Text.String = "CLEARSCREEN LABEL '<i><red>Hello</red>, 
<bold><blue>W<u>orld</blue></bold>!</i></u>'"
+            document.Text.String = sLock + "LABEL '<i><red>Hello</red>, 
<bold><blue>W<u>orld</blue></bold>!</i></u>'"
             self.logo("run")
             # wait for LibreLogo program termination
             while xIsAlive.invoke((), (), ())[0]:
@@ -170,7 +173,7 @@ x 3 ; draw only a few levels
             #2 check strike out, sub, sup, font name and font size formatting
 
             document.Text.String = (
-                "CLEARSCREEN FONTFAMILY 'Linux Biolinum G' FONTSIZE 12 " +
+                sLock + "FONTFAMILY 'Linux Biolinum G' FONTSIZE 12 " +
                 "LABEL '<s>x</s>, <sub>x</sub>, <sup>x</sup>, " +
                     "<FONTFAMILY Liberation Sans>x</FONTFAMILY>, " +
                     "<FONTHEIGHT 20>x</FONTHEIGHT>...'" )
@@ -223,8 +226,7 @@ x 3 ; draw only a few levels
 
             #3 check colors
 
-            document.Text.String = (
-                "CLEARSCREEN " +
+            document.Text.String = ( sLock +
                 "LABEL '<red>x</red>, <BLUE>x</BLUE>, " +  # check ignoring 
case
                     "<FONTCOLOR GREEN>x</FONTCOLOR>, " +   # check with command
                     "<FONTCOLOR 0x0000FF>x, " +            # check with hexa 
code
@@ -279,7 +281,7 @@ x 3 ; draw only a few levels
             #4 check font features
 
             document.Text.String = (
-                "CLEARSCREEN FONTFAMILY 'Linux Biolinum G' " +
+                sLock + "FONTFAMILY 'Linux Biolinum G' " +
                 "LABEL 'a <smcp>smcp <pnum>1<onum>1</pnum> 
1</onum>1</smcp>...'" )
 
             self.logo("run")
@@ -311,4 +313,10 @@ x 3 ; draw only a few levels
             c.goRight(1, False)
             self.assertEqual(c.CharFontName, "Linux Biolinum G:smcp")
 
+   def test_LABEL(self):
+        self.check_label(False)
+
+   def test_custom_lock(self):
+        self.check_label(True)
+
 # vim: set shiftwidth=4 softtabstop=4 expandtab:

Reply via email to