xref: /trunk/test/odf-validate/fixtures/draw/make.py (revision 0e16a31d78a652c56c5c0fc79c752f48b9048df9)
1*0e16a31dSJim Jagielski#**************************************************************
2*0e16a31dSJim Jagielski#
3*0e16a31dSJim Jagielski#  Licensed to the Apache Software Foundation (ASF) under one
4*0e16a31dSJim Jagielski#  or more contributor license agreements.  See the NOTICE file
5*0e16a31dSJim Jagielski#  distributed with this work for additional information
6*0e16a31dSJim Jagielski#  regarding copyright ownership.  The ASF licenses this file
7*0e16a31dSJim Jagielski#  to you under the Apache License, Version 2.0 (the
8*0e16a31dSJim Jagielski#  "License"); you may not use this file except in compliance
9*0e16a31dSJim Jagielski#  with the License.  You may obtain a copy of the License at
10*0e16a31dSJim Jagielski#
11*0e16a31dSJim Jagielski#    http://www.apache.org/licenses/LICENSE-2.0
12*0e16a31dSJim Jagielski#
13*0e16a31dSJim Jagielski#  Unless required by applicable law or agreed to in writing,
14*0e16a31dSJim Jagielski#  software distributed under the License is distributed on an
15*0e16a31dSJim Jagielski#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*0e16a31dSJim Jagielski#  KIND, either express or implied.  See the License for the
17*0e16a31dSJim Jagielski#  specific language governing permissions and limitations
18*0e16a31dSJim Jagielski#  under the License.
19*0e16a31dSJim Jagielski#
20*0e16a31dSJim Jagielski#**************************************************************
21*0e16a31dSJim Jagielski# usage: runpy.sh fixtures/draw/make.py <port> <outdir>
22*0e16a31dSJim Jagielski# Draw and Impress features the corpus lacks: animations, transitions, presentation settings, click actions, image maps,
23*0e16a31dSJim Jagielski# 3D scenes, custom shapes, fontwork, connectors, glue points, measure, captions, plugin/applet/frame, page anchors.
24*0e16a31dSJim Jagielski# Saves with the office's configured ODF version: run it against the strict and extended profiles.
25*0e16a31dSJim Jagielskiimport sys, os, math, wave, struct, tempfile, threading, uno
26*0e16a31dSJim Jagielskifrom unohelp import connect, desktop, pv, odf_version
27*0e16a31dSJim Jagielski
28*0e16a31dSJim Jagielskiport, out = int(sys.argv[1]), os.path.abspath(sys.argv[2])
29*0e16a31dSJim Jagielskios.makedirs(out, exist_ok=True)
30*0e16a31dSJim Jagielskictx = connect(port)
31*0e16a31dSJim Jagielskismgr = ctx.ServiceManager
32*0e16a31dSJim Jagielskidesk = desktop(ctx)
33*0e16a31dSJim Jagielskifailed = []
34*0e16a31dSJim JagielskiSTEP_SECONDS = 90
35*0e16a31dSJim Jagielskicrashes = []
36*0e16a31dSJim JagielskiONLY = set(sys.argv[3:]) | set(os.environ.get("DRAW_ONLY", "").split())
37*0e16a31dSJim Jagielskitmp = tempfile.mkdtemp(prefix="t12_draw_")
38*0e16a31dSJim JagielskiSOUND = os.path.join(tmp, "beep.wav")
39*0e16a31dSJim Jagielskiw = wave.open(SOUND, "wb")
40*0e16a31dSJim Jagielskiw.setnchannels(1); w.setsampwidth(2); w.setframerate(8000)
41*0e16a31dSJim Jagielskiw.writeframes(b"".join(struct.pack("<h", int(8000 * math.sin(i / 5.0))) for i in range(4000)))
42*0e16a31dSJim Jagielskiw.close()
43*0e16a31dSJim JagielskiSOUND_URL = uno.systemPathToFileUrl(SOUND)
44*0e16a31dSJim Jagielski
45*0e16a31dSJim Jagielski# online spelling runs on a timer and was seen crashing the office on closed documents (ImpEditEngine::DoOnlineSpelling)
46*0e16a31dSJim Jagielskidef quiet_spelling():
47*0e16a31dSJim Jagielski    try:
48*0e16a31dSJim Jagielski        smgr.createInstanceWithContext("com.sun.star.linguistic2.LinguProperties", ctx).IsSpellAuto = False
49*0e16a31dSJim Jagielski    except Exception as e:
50*0e16a31dSJim Jagielski        print("  cannot disable online spelling", repr(e)[:100])
51*0e16a31dSJim Jagielski
52*0e16a31dSJim Jagielski
53*0e16a31dSJim Jagielskiquiet_spelling()
54*0e16a31dSJim JagielskiPROFILE = "t12_draw_" + ("strict" if odf_version(ctx) == 4 else "ext")
55*0e16a31dSJim Jagielski
56*0e16a31dSJim JagielskiCLIP = {"odp": "impress8", "odg": "draw8", "otp": "impress8_template", "otg": "draw8_template",
57*0e16a31dSJim Jagielski        "odt": "writer8", "ods": "calc8"}
58*0e16a31dSJim JagielskiFACTORY = {"odp": "simpress", "odg": "sdraw", "odt": "swriter", "ods": "scalc"}
59*0e16a31dSJim Jagielski
60*0e16a31dSJim Jagielski
61*0e16a31dSJim Jagielskidef new(kind):
62*0e16a31dSJim Jagielski    return desk.loadComponentFromURL("private:factory/" + FACTORY[kind], "_blank", 0, (pv("Hidden", True),))
63*0e16a31dSJim Jagielski
64*0e16a31dSJim Jagielski
65*0e16a31dSJim JagielskiKEEP = []
66*0e16a31dSJim Jagielski
67*0e16a31dSJim Jagielski
68*0e16a31dSJim Jagielskidef done(doc):
69*0e16a31dSJim Jagielski    # closing documents or releasing annotation/table proxies after a close crashed the office (use after free); leak them and _exit
70*0e16a31dSJim Jagielski    KEEP.append(doc)
71*0e16a31dSJim Jagielski
72*0e16a31dSJim Jagielski
73*0e16a31dSJim Jagielskidef save(doc, name):
74*0e16a31dSJim Jagielski    try:
75*0e16a31dSJim Jagielski        doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, name)), (pv("FilterName", CLIP[name.rsplit(".", 1)[1]]),))
76*0e16a31dSJim Jagielski        print("saved", name)
77*0e16a31dSJim Jagielski    except Exception as e:
78*0e16a31dSJim Jagielski        failed.append(name)
79*0e16a31dSJim Jagielski        print("FAIL save", name, repr(e)[:300])
80*0e16a31dSJim Jagielski
81*0e16a31dSJim Jagielski
82*0e16a31dSJim Jagielskidef step(label, fn, *a, **kw):
83*0e16a31dSJim Jagielski    print('  step', label, flush=True)
84*0e16a31dSJim Jagielski    try:
85*0e16a31dSJim Jagielski        return fn(*a, **kw)
86*0e16a31dSJim Jagielski    except Exception as e:
87*0e16a31dSJim Jagielski        failed.append(label)
88*0e16a31dSJim Jagielski        import traceback
89*0e16a31dSJim Jagielski        print("FAIL", label, type(e).__name__, repr(e)[:300], traceback.format_exc().splitlines()[-3:-1])
90*0e16a31dSJim Jagielski
91*0e16a31dSJim Jagielski
92*0e16a31dSJim Jagielskidef office_alive():
93*0e16a31dSJim Jagielski    try:
94*0e16a31dSJim Jagielski        desk.getImplementationName()
95*0e16a31dSJim Jagielski        return True
96*0e16a31dSJim Jagielski    except Exception:
97*0e16a31dSJim Jagielski        return False
98*0e16a31dSJim Jagielski
99*0e16a31dSJim Jagielski
100*0e16a31dSJim Jagielskidef kill_office():
101*0e16a31dSJim Jagielski    import subprocess
102*0e16a31dSJim Jagielski    print("WATCHDOG: step exceeded %ds, killing the office" % STEP_SECONDS, flush=True)
103*0e16a31dSJim Jagielski    subprocess.run(["pkill", "-f", "[p]rofile_" + PROFILE])
104*0e16a31dSJim Jagielski
105*0e16a31dSJim Jagielski
106*0e16a31dSJim Jagielskidef restart_office():
107*0e16a31dSJim Jagielski    global ctx, smgr, desk
108*0e16a31dSJim Jagielski    import subprocess
109*0e16a31dSJim Jagielski    harness = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))))
110*0e16a31dSJim Jagielski    prof = PROFILE
111*0e16a31dSJim Jagielski    subprocess.run(["pkill", "-f", "[p]rofile_" + prof])
112*0e16a31dSJim Jagielski    subprocess.run([os.path.join(harness, "start.sh"), prof, str(port)], check=True)
113*0e16a31dSJim Jagielski    ctx = connect(port)
114*0e16a31dSJim Jagielski    smgr = ctx.ServiceManager
115*0e16a31dSJim Jagielski    desk = desktop(ctx)
116*0e16a31dSJim Jagielski    quiet_spelling()
117*0e16a31dSJim Jagielski
118*0e16a31dSJim Jagielski
119*0e16a31dSJim Jagielskidef top(label, fn, *a):
120*0e16a31dSJim Jagielski    if ONLY and label not in ONLY:
121*0e16a31dSJim Jagielski        return
122*0e16a31dSJim Jagielski    print('step', label, flush=True)
123*0e16a31dSJim Jagielski    for attempt in (1, 2):
124*0e16a31dSJim Jagielski        nfailed = len(failed)
125*0e16a31dSJim Jagielski        dog = threading.Timer(STEP_SECONDS, kill_office)
126*0e16a31dSJim Jagielski        dog.start()
127*0e16a31dSJim Jagielski        try:
128*0e16a31dSJim Jagielski            fn(*a)
129*0e16a31dSJim Jagielski            return
130*0e16a31dSJim Jagielski        except Exception as e:
131*0e16a31dSJim Jagielski            if office_alive():
132*0e16a31dSJim Jagielski                failed.append(label)
133*0e16a31dSJim Jagielski                print("FAIL", label, type(e).__name__, repr(e)[:300])
134*0e16a31dSJim Jagielski                return
135*0e16a31dSJim Jagielski            del failed[nfailed:]
136*0e16a31dSJim Jagielski            crashes.append(label)
137*0e16a31dSJim Jagielski            print("CRASH", label, "attempt", attempt, repr(e)[:150])
138*0e16a31dSJim Jagielski            restart_office()
139*0e16a31dSJim Jagielski        finally:
140*0e16a31dSJim Jagielski            dog.cancel()
141*0e16a31dSJim Jagielski    failed.append(label)
142*0e16a31dSJim Jagielski
143*0e16a31dSJim Jagielski
144*0e16a31dSJim Jagielskidef struct_(name, *a):
145*0e16a31dSJim Jagielski    return uno.createUnoStruct(name, *a)
146*0e16a31dSJim Jagielski
147*0e16a31dSJim Jagielski
148*0e16a31dSJim Jagielskidef pt(x, y):
149*0e16a31dSJim Jagielski    return struct_("com.sun.star.awt.Point", x, y)
150*0e16a31dSJim Jagielski
151*0e16a31dSJim Jagielski
152*0e16a31dSJim Jagielskidef sz(w, h):
153*0e16a31dSJim Jagielski    return struct_("com.sun.star.awt.Size", w, h)
154*0e16a31dSJim Jagielski
155*0e16a31dSJim Jagielski
156*0e16a31dSJim Jagielskidef mk(doc, page, service, x=1000, y=1000, w=3000, h=2000, text=None, **props):
157*0e16a31dSJim Jagielski    s = doc.createInstance("com.sun.star.drawing." + service)
158*0e16a31dSJim Jagielski    page.add(s)
159*0e16a31dSJim Jagielski    if w is not None:
160*0e16a31dSJim Jagielski        s.Position = pt(x, y)
161*0e16a31dSJim Jagielski        s.Size = sz(w, h)
162*0e16a31dSJim Jagielski    if text is not None:
163*0e16a31dSJim Jagielski        s.String = text
164*0e16a31dSJim Jagielski    for k, v in props.items():
165*0e16a31dSJim Jagielski        try:
166*0e16a31dSJim Jagielski            setattr(s, k, v)
167*0e16a31dSJim Jagielski        except Exception as e:
168*0e16a31dSJim Jagielski            print("  prop", service, k, repr(e)[:120])
169*0e16a31dSJim Jagielski    return s
170*0e16a31dSJim Jagielski
171*0e16a31dSJim Jagielski
172*0e16a31dSJim Jagielskidef setp(obj, **props):
173*0e16a31dSJim Jagielski    for k, v in props.items():
174*0e16a31dSJim Jagielski        try:
175*0e16a31dSJim Jagielski            setattr(obj, k, v)
176*0e16a31dSJim Jagielski        except Exception as e:
177*0e16a31dSJim Jagielski            print("  prop", k, repr(e)[:120])
178*0e16a31dSJim Jagielski
179*0e16a31dSJim Jagielski
180*0e16a31dSJim Jagielskidef spec(name):
181*0e16a31dSJim Jagielski    return smgr.createInstanceWithContext("com.sun.star.animations." + name, ctx)
182*0e16a31dSJim Jagielski
183*0e16a31dSJim Jagielski
184*0e16a31dSJim Jagielskidef add_page(doc):
185*0e16a31dSJim Jagielski    doc.DrawPages.insertNewByIndex(doc.DrawPages.Count)
186*0e16a31dSJim Jagielski    return doc.DrawPages.getByIndex(doc.DrawPages.Count - 1)
187*0e16a31dSJim Jagielski
188*0e16a31dSJim Jagielski
189*0e16a31dSJim Jagielskidef presentation_settings():
190*0e16a31dSJim Jagielski    doc = new("odp")
191*0e16a31dSJim Jagielski    pages = [doc.DrawPages.getByIndex(0)] + [add_page(doc) for _ in range(3)]
192*0e16a31dSJim Jagielski    for i, p in enumerate(pages):
193*0e16a31dSJim Jagielski        p.Name = "Slide%d" % (i + 1)
194*0e16a31dSJim Jagielski        mk(doc, p, "RectangleShape", text="slide %d" % (i + 1))
195*0e16a31dSJim Jagielski    shows = doc.CustomPresentations
196*0e16a31dSJim Jagielski    for nm, idx in (("ShowA", (0, 2)), ("ShowB", (1, 3, 0))):
197*0e16a31dSJim Jagielski        show = shows.createInstance()
198*0e16a31dSJim Jagielski        for i in idx:
199*0e16a31dSJim Jagielski            show.insertByIndex(show.Count, pages[i])
200*0e16a31dSJim Jagielski        shows.insertByName(nm, show)
201*0e16a31dSJim Jagielski    pres = doc.Presentation
202*0e16a31dSJim Jagielski    pres.IsShowAll = False
203*0e16a31dSJim Jagielski    pres.CustomShow = "ShowB"
204*0e16a31dSJim Jagielski    pres.IsEndless = True
205*0e16a31dSJim Jagielski    pres.Pause = 7
206*0e16a31dSJim Jagielski    pres.AllowAnimations = False
207*0e16a31dSJim Jagielski    pres.IsAlwaysOnTop = True
208*0e16a31dSJim Jagielski    pres.IsAutomatic = True
209*0e16a31dSJim Jagielski    pres.IsFullScreen = False
210*0e16a31dSJim Jagielski    pres.IsMouseVisible = False
211*0e16a31dSJim Jagielski    pres.StartWithNavigator = True
212*0e16a31dSJim Jagielski    pres.UsePen = True
213*0e16a31dSJim Jagielski    pres.IsTransitionOnClick = False
214*0e16a31dSJim Jagielski    pres.IsShowLogo = True
215*0e16a31dSJim Jagielski    save(doc, "pres-settings.odp")
216*0e16a31dSJim Jagielski    pres.CustomShow = ""
217*0e16a31dSJim Jagielski    pres.FirstPage = "Slide3"
218*0e16a31dSJim Jagielski    save(doc, "pres-settings-start.odp")
219*0e16a31dSJim Jagielski    done(doc)
220*0e16a31dSJim Jagielski
221*0e16a31dSJim Jagielski
222*0e16a31dSJim Jagielskidef header_footer():
223*0e16a31dSJim Jagielski    doc = new("odp")
224*0e16a31dSJim Jagielski    p1 = doc.DrawPages.getByIndex(0)
225*0e16a31dSJim Jagielski    p2 = add_page(doc)
226*0e16a31dSJim Jagielski    for i, p in enumerate((p1, p2)):
227*0e16a31dSJim Jagielski        mk(doc, p, "RectangleShape", text="hf %d" % i)
228*0e16a31dSJim Jagielski        setp(p, IsFooterVisible=True, FooterText="footer %d" % i, IsPageNumberVisible=True, IsDateTimeVisible=True)
229*0e16a31dSJim Jagielski    setp(p1, IsDateTimeFixed=True, DateTimeText="fixed date")
230*0e16a31dSJim Jagielski    setp(p2, IsDateTimeFixed=False, DateTimeFormat=0x2002)
231*0e16a31dSJim Jagielski    for p in (p1, p2):
232*0e16a31dSJim Jagielski        setp(p.NotesPage, IsHeaderVisible=True, HeaderText="notes header", IsFooterVisible=True, FooterText="notes footer",
233*0e16a31dSJim Jagielski             IsDateTimeVisible=True, IsDateTimeFixed=True, DateTimeText="notes date", IsPageNumberVisible=True)
234*0e16a31dSJim Jagielski    setp(doc.MasterPages.getByIndex(0), IsFooterVisible=True, FooterText="master footer", IsPageNumberVisible=True)
235*0e16a31dSJim Jagielski    try:
236*0e16a31dSJim Jagielski        hm = doc.getHandoutMasterPage()
237*0e16a31dSJim Jagielski    except Exception as e:
238*0e16a31dSJim Jagielski        hm = None
239*0e16a31dSJim Jagielski        print("  handout master", repr(e)[:100])
240*0e16a31dSJim Jagielski    hm is not None and setp(hm, IsHeaderVisible=True, HeaderText="handout header", IsFooterVisible=True,
241*0e16a31dSJim Jagielski         FooterText="handout footer", IsDateTimeVisible=True, IsDateTimeFixed=True, DateTimeText="handout date")
242*0e16a31dSJim Jagielski    save(doc, "header-footer.odp")
243*0e16a31dSJim Jagielski    done(doc)
244*0e16a31dSJim Jagielski
245*0e16a31dSJim Jagielski
246*0e16a31dSJim Jagielskidef layouts():
247*0e16a31dSJim Jagielski    doc = new("odp")
248*0e16a31dSJim Jagielski    first = True
249*0e16a31dSJim Jagielski    for n in range(0, 40):
250*0e16a31dSJim Jagielski        try:
251*0e16a31dSJim Jagielski            p = doc.DrawPages.getByIndex(0) if first else add_page(doc)
252*0e16a31dSJim Jagielski            first = False
253*0e16a31dSJim Jagielski            p.Layout = n
254*0e16a31dSJim Jagielski        except Exception as e:
255*0e16a31dSJim Jagielski            print("  layout", n, repr(e)[:100])
256*0e16a31dSJim Jagielski    save(doc, "layouts.odp")
257*0e16a31dSJim Jagielski    done(doc)
258*0e16a31dSJim Jagielski
259*0e16a31dSJim Jagielski
260*0e16a31dSJim Jagielskidef const(prefix, name):
261*0e16a31dSJim Jagielski    mod = "presentation" if prefix in ("EffectNodeType", "EffectPresetClass", "ShapeAnimationSubType", "EffectCommands") else "animations"
262*0e16a31dSJim Jagielski    return uno.getConstantByName("com.sun.star.%s.%s.%s" % (mod, prefix, name))
263*0e16a31dSJim Jagielski
264*0e16a31dSJim Jagielski
265*0e16a31dSJim Jagielskidef transitions():
266*0e16a31dSJim Jagielski    doc = new("odp")
267*0e16a31dSJim Jagielski    first = True
268*0e16a31dSJim Jagielski    types = [uno.getConstantByName("com.sun.star.animations.TransitionType.BARWIPE") + i for i in range(43)]
269*0e16a31dSJim Jagielski    subs = list(range(0, 120))
270*0e16a31dSJim Jagielski    combos = [(t, 0) for t in types] + [(1, st) for st in subs if st]
271*0e16a31dSJim Jagielski    for i, (t, st) in enumerate(combos):
272*0e16a31dSJim Jagielski        p = doc.DrawPages.getByIndex(0) if first else add_page(doc)
273*0e16a31dSJim Jagielski        first = False
274*0e16a31dSJim Jagielski        setp(p, TransitionType=t, TransitionSubtype=st, TransitionDuration=1.5 + (i % 3), TransitionDirection=bool(i % 2),
275*0e16a31dSJim Jagielski             TransitionFadeColor=0x336699 + i)
276*0e16a31dSJim Jagielski    p = add_page(doc)
277*0e16a31dSJim Jagielski    setp(p, TransitionType=37, TransitionSubtype=const("TransitionSubType", "FADETOCOLOR"), TransitionDirection=False,
278*0e16a31dSJim Jagielski         TransitionFadeColor=0xFF8800)
279*0e16a31dSJim Jagielski    p = add_page(doc)
280*0e16a31dSJim Jagielski    setp(p, TransitionType=37, TransitionSubtype=const("TransitionSubType", "FADEFROMCOLOR"), TransitionFadeColor=0x0088FF)
281*0e16a31dSJim Jagielski    p = add_page(doc)
282*0e16a31dSJim Jagielski    setp(p, TransitionType=0, Sound=SOUND_URL, LoopSound=True)
283*0e16a31dSJim Jagielski    p = add_page(doc)
284*0e16a31dSJim Jagielski    setp(p, TransitionType=4, TransitionSubtype=3, Sound=SOUND_URL)
285*0e16a31dSJim Jagielski    p = add_page(doc)
286*0e16a31dSJim Jagielski    setp(p, TransitionType=0, Sound=True)
287*0e16a31dSJim Jagielski    p = add_page(doc)
288*0e16a31dSJim Jagielski    setp(p, TransitionType=36, Sound=False, Change=1, Duration=5)
289*0e16a31dSJim Jagielski    save(doc, "transitions.odp")
290*0e16a31dSJim Jagielski    done(doc)
291*0e16a31dSJim Jagielski
292*0e16a31dSJim Jagielski
293*0e16a31dSJim Jagielskidef nv(name, value):
294*0e16a31dSJim Jagielski    return struct_("com.sun.star.beans.NamedValue", name, value)
295*0e16a31dSJim Jagielski
296*0e16a31dSJim Jagielski
297*0e16a31dSJim Jagielskidef node(name, **props):
298*0e16a31dSJim Jagielski    n = spec(name)
299*0e16a31dSJim Jagielski    for k, v in props.items():
300*0e16a31dSJim Jagielski        setattr(n, k, v)
301*0e16a31dSJim Jagielski    return n
302*0e16a31dSJim Jagielski
303*0e16a31dSJim Jagielski
304*0e16a31dSJim Jagielskidef userdata(**kw):
305*0e16a31dSJim Jagielski    return tuple(nv(k.replace("_", "-"), v) for k, v in kw.items())
306*0e16a31dSJim Jagielski
307*0e16a31dSJim Jagielski
308*0e16a31dSJim Jagielskidef event(trigger, source=None, offset=None):
309*0e16a31dSJim Jagielski    e = struct_("com.sun.star.animations.Event")
310*0e16a31dSJim Jagielski    e.Trigger = trigger
311*0e16a31dSJim Jagielski    if source is not None:
312*0e16a31dSJim Jagielski        e.Source = source
313*0e16a31dSJim Jagielski    if offset is not None:
314*0e16a31dSJim Jagielski        e.Offset = offset
315*0e16a31dSJim Jagielski    return e
316*0e16a31dSJim Jagielski
317*0e16a31dSJim Jagielski
318*0e16a31dSJim Jagielskidef animations_one(doc, p, k):
319*0e16a31dSJim Jagielski    sh = mk(doc, p, "RectangleShape", text="target one\ntwo\nthree")
320*0e16a31dSJim Jagielski    sh2 = mk(doc, p, "EllipseShape", x=6000, y=1000, text="second")
321*0e16a31dSJim Jagielski    sh3 = mk(doc, p, "RectangleShape", x=1000, y=5000, text="third")
322*0e16a31dSJim Jagielski    root = p.AnimationNode
323*0e16a31dSJim Jagielski    seq = node("SequenceTimeContainer", UserData=userdata(node_type=const("EffectNodeType", "MAIN_SEQUENCE")))
324*0e16a31dSJim Jagielski    root.appendChild(seq)
325*0e16a31dSJim Jagielski    EN = lambda n: const("EffectNodeType", n)
326*0e16a31dSJim Jagielski
327*0e16a31dSJim Jagielski    def effect(nodetype, preset, cls, *children, **kw):
328*0e16a31dSJim Jagielski        par = node("ParallelTimeContainer", Begin=kw.pop("Begin", 0.0),
329*0e16a31dSJim Jagielski                   UserData=userdata(node_type=EN(nodetype), preset_id=preset, preset_class=const("EffectPresetClass", cls),
330*0e16a31dSJim Jagielski                                     preset_sub_type="", group_id=1))
331*0e16a31dSJim Jagielski        for c in children:
332*0e16a31dSJim Jagielski            par.appendChild(c)
333*0e16a31dSJim Jagielski        for a, b in kw.items():
334*0e16a31dSJim Jagielski            setattr(par, a, b)
335*0e16a31dSJim Jagielski        return par
336*0e16a31dSJim Jagielski
337*0e16a31dSJim Jagielski    def click(*effects, trig=True):
338*0e16a31dSJim Jagielski        outer = node("ParallelTimeContainer", Begin=event(const("EventTrigger", "ON_NEXT")) if trig else 0.0)
339*0e16a31dSJim Jagielski        inner = node("ParallelTimeContainer", Begin=0.0)
340*0e16a31dSJim Jagielski        for e in effects:
341*0e16a31dSJim Jagielski            inner.appendChild(e)
342*0e16a31dSJim Jagielski        outer.appendChild(inner)
343*0e16a31dSJim Jagielski        seq.appendChild(outer)
344*0e16a31dSJim Jagielski
345*0e16a31dSJim Jagielski    st = node("AnimateSet", Target=sh, AttributeName="Visibility", To=True, Begin=0.0, Duration=0.001, Fill=const("AnimationFill", "HOLD"))
346*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "ooo-entrance-appear", "ENTRANCE", st))
347*0e16a31dSJim Jagielski    an = node("Animate", Target=sh2, AttributeName="X", Values=(0.0, 0.5), KeyTimes=(0.0, 1.0), Duration=2.0,
348*0e16a31dSJim Jagielski              Formula="$X+#x", CalcMode=const("AnimationCalcMode", "DISCRETE"), Accumulate=True,
349*0e16a31dSJim Jagielski              Additive=const("AnimationAdditiveMode", "SUM"), TimeFilter=(struct_("com.sun.star.animations.TimeFilterPair", 0.0, 0.0), struct_("com.sun.star.animations.TimeFilterPair", 1.0, 1.0)))
350*0e16a31dSJim Jagielski    an2 = node("Animate", Target=sh2, AttributeName="Opacity", From=0.0, By=0.1, To=1.0, Duration=1.0,
351*0e16a31dSJim Jagielski               CalcMode=const("AnimationCalcMode", "PACED"), Additive=const("AnimationAdditiveMode", "MULTIPLY"))
352*0e16a31dSJim Jagielski    an3 = node("Animate", Target=sh2, AttributeName="Y", From=0.0, To=0.5, Duration=1.0, Additive=const("AnimationAdditiveMode", "BASE"))
353*0e16a31dSJim Jagielski    an4 = node("Animate", Target=sh2, AttributeName="Height", From=0.0, To=0.5, Duration=1.0, Additive=const("AnimationAdditiveMode", "NONE"))
354*0e16a31dSJim Jagielski    click(effect("WITH_PREVIOUS", "ooo-entrance-fly-in", "ENTRANCE", an, an2, an3, an4))
355*0e16a31dSJim Jagielski    ac = node("AnimateColor", Target=sh, AttributeName="FillColor", From=0xFF0000, To=0x00FF00, Duration=1.0,
356*0e16a31dSJim Jagielski              ColorInterpolation=const("AnimationColorSpace", "HSL"), Direction=False)
357*0e16a31dSJim Jagielski    ac2 = node("AnimateColor", Target=sh3, AttributeName="LineColor", By=0x101010, Duration=1.0,
358*0e16a31dSJim Jagielski               ColorInterpolation=const("AnimationColorSpace", "RGB"), Direction=True)
359*0e16a31dSJim Jagielski    click(effect("AFTER_PREVIOUS", "ooo-emphasis-change-fill-color", "EMPHASIS", ac, ac2))
360*0e16a31dSJim Jagielski    am = node("AnimateMotion", Target=sh3, Path="M 0 0 L 0.25 0.25 C 0.3 0.3 0.4 0.3 0.5 0.5", Duration=2.0,
361*0e16a31dSJim Jagielski              CalcMode=const("AnimationCalcMode", "PACED"))
362*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "ooo-motionpath-user", "MOTIONPATH", am))
363*0e16a31dSJim Jagielski    ats = [node("AnimateTransform", Target=sh2, TransformType=tt, Values=("1", "2"), Duration=1.0, SubItem=sub)
364*0e16a31dSJim Jagielski           for tt, sub in ((0, 0), (1, 1), (2, 2), (3, 0), (4, 1))]
365*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "ooo-emphasis-spin", "EMPHASIS", *ats))
366*0e16a31dSJim Jagielski    attrs = [("Width", "0", "width"), ("Height", "0", "height"), ("Y", "0", "y"), ("Rotate", 0.0, 90.0), ("SkewX", 0.0, 30.0),
367*0e16a31dSJim Jagielski             ("CharColor", 0, 0xFF0000), ("CharRotation", 0, 90), ("CharWeight", 100.0, 150.0), ("CharUnderline", 0, 1),
368*0e16a31dSJim Jagielski             ("CharFontName", "Arial", "Times"), ("CharHeight", 1.0, 2.0), ("CharPosture", 0, 2),
369*0e16a31dSJim Jagielski             ("LineStyle", 0, 1), ("FillStyle", 0, 1), ("DimColor", 0, 0xAAAAAA), ("Visibility", False, True)]
370*0e16a31dSJim Jagielski    kids = []
371*0e16a31dSJim Jagielski    for an_name, fr, to in attrs:
372*0e16a31dSJim Jagielski        try:
373*0e16a31dSJim Jagielski            kids.append(node("Animate", Target=sh3, AttributeName=an_name, From=fr, To=to, Duration=0.5,
374*0e16a31dSJim Jagielski                             Restart=const("AnimationRestart", "ALWAYS"), RestartDefault=const("AnimationRestart", "NEVER"),
375*0e16a31dSJim Jagielski                             FillDefault=const("AnimationFill", "FREEZE"), Acceleration=0.2, Decelerate=0.3,
376*0e16a31dSJim Jagielski                             AutoReverse=True, RepeatCount=3.0, RepeatDuration=9.0, EndSync=const("AnimationEndSync", "FIRST"),
377*0e16a31dSJim Jagielski                             End=5.0))
378*0e16a31dSJim Jagielski        except Exception as e:
379*0e16a31dSJim Jagielski            print("  animate", an_name, repr(e)[:100])
380*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "ooo-emphasis-custom", "CUSTOM", *kids))
381*0e16a31dSJim Jagielski    tf = node("TransitionFilter", Target=sh, Transition=1, Subtype=2, Mode=False, Direction=False, FadeColor=0x123456, Duration=1.0)
382*0e16a31dSJim Jagielski    tf2 = node("TransitionFilter", Target=sh2, Transition=37, Subtype=const("TransitionSubType", "FADETOCOLOR"), Mode=True,
383*0e16a31dSJim Jagielski               Direction=True, FadeColor=0x654321, Duration=1.0)
384*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "ooo-entrance-wipe", "ENTRANCE", tf, tf2))
385*0e16a31dSJim Jagielski    au = node("Audio", Source=SOUND_URL, Volume=0.5, Begin=0.0)
386*0e16a31dSJim Jagielski    au2 = node("Audio", Source=SOUND_URL, Volume=1.0)
387*0e16a31dSJim Jagielski    cm = [node("Command", Target=sh, Command=c, Parameter=None) for c in range(6)]
388*0e16a31dSJim Jagielski    click(effect("ON_CLICK", "media-call", "MEDIACALL", au, au2, *cm))
389*0e16a31dSJim Jagielski    it = node("IterateContainer", Target=sh, SubItem=const("ShapeAnimationSubType", "ONLY_TEXT"),
390*0e16a31dSJim Jagielski              IterateType=1, IterateInterval=0.25,
391*0e16a31dSJim Jagielski              UserData=userdata(node_type=EN("ON_CLICK"), preset_id="ooo-entrance-fade-in", preset_class=const("EffectPresetClass", "ENTRANCE")))
392*0e16a31dSJim Jagielski    it.appendChild(node("AnimateSet", Target=sh, AttributeName="Visibility", To=True, Begin=0.0, Duration=0.001))
393*0e16a31dSJim Jagielski    click(it)
394*0e16a31dSJim Jagielski    for sub, itype in ((1, 0), (0, 2)):
395*0e16a31dSJim Jagielski        it2 = node("IterateContainer", Target=ParagraphTarget(sh, 1), SubItem=sub, IterateType=itype, IterateInterval=1.5)
396*0e16a31dSJim Jagielski        it2.appendChild(node("AnimateSet", Target=ParagraphTarget(sh, 1), AttributeName="Visibility", To=True))
397*0e16a31dSJim Jagielski        click(it2)
398*0e16a31dSJim Jagielski    seq2 = node("SequenceTimeContainer", UserData=userdata(node_type=EN("INTERACTIVE_SEQUENCE")),
399*0e16a31dSJim Jagielski                Begin=event(const("EventTrigger", "ON_CLICK"), sh3), End=(event(const("EventTrigger", "ON_END"), sh), 5.0))
400*0e16a31dSJim Jagielski    seq2.appendChild(node("AnimateSet", Target=sh2, AttributeName="Visibility", To=False))
401*0e16a31dSJim Jagielski    root.appendChild(seq2)
402*0e16a31dSJim Jagielski    for kind in range(12):
403*0e16a31dSJim Jagielski        trig = kind + 1
404*0e16a31dSJim Jagielski        e = event(trig, sh, 0.5 if kind % 2 else None)
405*0e16a31dSJim Jagielski        seq3 = node("SequenceTimeContainer", UserData=userdata(node_type=EN("INTERACTIVE_SEQUENCE")), Begin=e)
406*0e16a31dSJim Jagielski        seq3.appendChild(node("AnimateSet", Target=sh2, AttributeName="Visibility", To=True))
407*0e16a31dSJim Jagielski        root.appendChild(seq3)
408*0e16a31dSJim Jagielski    for fill, rest in ((1, 1), (2, 2), (3, 3), (4, 0), (5, 1)):
409*0e16a31dSJim Jagielski        par = node("ParallelTimeContainer", Fill=fill, Restart=rest, Begin=0.0)
410*0e16a31dSJim Jagielski        par.appendChild(node("AnimateSet", Target=sh, AttributeName="Visibility", To=True))
411*0e16a31dSJim Jagielski        root.appendChild(par)
412*0e16a31dSJim Jagielski
413*0e16a31dSJim Jagielski
414*0e16a31dSJim Jagielskidef ParagraphTarget(shape, n):
415*0e16a31dSJim Jagielski    return struct_("com.sun.star.presentation.ParagraphTarget", shape, n)
416*0e16a31dSJim Jagielski
417*0e16a31dSJim Jagielski
418*0e16a31dSJim Jagielskidef animations():
419*0e16a31dSJim Jagielski    doc = new("odp")
420*0e16a31dSJim Jagielski    p = doc.DrawPages.getByIndex(0)
421*0e16a31dSJim Jagielski    step("anim-tree", animations_one, doc, p, 0)
422*0e16a31dSJim Jagielski    save(doc, "animations.odp")
423*0e16a31dSJim Jagielski    done(doc)
424*0e16a31dSJim Jagielski
425*0e16a31dSJim Jagielski
426*0e16a31dSJim Jagielskidef enum(t, v):
427*0e16a31dSJim Jagielski    return uno.Enum("com.sun.star.presentation." + t, v)
428*0e16a31dSJim Jagielski
429*0e16a31dSJim Jagielski
430*0e16a31dSJim JagielskiANIM_EFFECTS = """FADE_FROM_LEFT FADE_FROM_TOP FADE_FROM_RIGHT FADE_FROM_BOTTOM FADE_TO_CENTER FADE_FROM_CENTER MOVE_FROM_LEFT MOVE_FROM_TOP
431*0e16a31dSJim JagielskiMOVE_FROM_RIGHT MOVE_FROM_BOTTOM VERTICAL_STRIPES HORIZONTAL_STRIPES CLOCKWISE COUNTERCLOCKWISE FADE_FROM_UPPERLEFT FADE_FROM_UPPERRIGHT
432*0e16a31dSJim JagielskiFADE_FROM_LOWERLEFT FADE_FROM_LOWERRIGHT CLOSE_VERTICAL CLOSE_HORIZONTAL OPEN_VERTICAL OPEN_HORIZONTAL PATH MOVE_TO_LEFT MOVE_TO_TOP
433*0e16a31dSJim JagielskiMOVE_TO_RIGHT MOVE_TO_BOTTOM SPIRALIN_LEFT SPIRALIN_RIGHT SPIRALOUT_LEFT SPIRALOUT_RIGHT DISSOLVE WAVYLINE_FROM_LEFT WAVYLINE_FROM_TOP
434*0e16a31dSJim JagielskiWAVYLINE_FROM_RIGHT WAVYLINE_FROM_BOTTOM RANDOM VERTICAL_LINES HORIZONTAL_LINES LASER_FROM_LEFT LASER_FROM_TOP LASER_FROM_RIGHT
435*0e16a31dSJim JagielskiLASER_FROM_BOTTOM LASER_FROM_UPPERLEFT LASER_FROM_UPPERRIGHT LASER_FROM_LOWERLEFT LASER_FROM_LOWERRIGHT APPEAR HIDE MOVE_FROM_UPPERLEFT
436*0e16a31dSJim JagielskiMOVE_FROM_UPPERRIGHT MOVE_FROM_LOWERRIGHT MOVE_FROM_LOWERLEFT MOVE_TO_UPPERLEFT MOVE_TO_UPPERRIGHT MOVE_TO_LOWERRIGHT MOVE_TO_LOWERLEFT
437*0e16a31dSJim JagielskiMOVE_SHORT_FROM_LEFT MOVE_SHORT_FROM_UPPERLEFT MOVE_SHORT_FROM_TOP MOVE_SHORT_FROM_UPPERRIGHT MOVE_SHORT_FROM_RIGHT
438*0e16a31dSJim JagielskiMOVE_SHORT_FROM_LOWERRIGHT MOVE_SHORT_FROM_BOTTOM MOVE_SHORT_FROM_LOWERLEFT MOVE_SHORT_TO_LEFT MOVE_SHORT_TO_UPPERLEFT MOVE_SHORT_TO_TOP
439*0e16a31dSJim JagielskiMOVE_SHORT_TO_UPPERRIGHT MOVE_SHORT_TO_RIGHT MOVE_SHORT_TO_LOWERRIGHT MOVE_SHORT_TO_BOTTOM MOVE_SHORT_TO_LOWERLEFT VERTICAL_CHECKERBOARD
440*0e16a31dSJim JagielskiHORIZONTAL_CHECKERBOARD HORIZONTAL_ROTATE VERTICAL_ROTATE HORIZONTAL_STRETCH VERTICAL_STRETCH STRETCH_FROM_LEFT STRETCH_FROM_UPPERLEFT
441*0e16a31dSJim JagielskiSTRETCH_FROM_TOP STRETCH_FROM_UPPERRIGHT STRETCH_FROM_RIGHT STRETCH_FROM_LOWERRIGHT STRETCH_FROM_BOTTOM STRETCH_FROM_LOWERLEFT ZOOM_IN
442*0e16a31dSJim JagielskiZOOM_IN_SMALL ZOOM_IN_SPIRAL ZOOM_OUT ZOOM_OUT_SMALL ZOOM_OUT_SPIRAL ZOOM_IN_FROM_LEFT ZOOM_IN_FROM_UPPERLEFT ZOOM_IN_FROM_TOP
443*0e16a31dSJim JagielskiZOOM_IN_FROM_UPPERRIGHT ZOOM_IN_FROM_RIGHT ZOOM_IN_FROM_LOWERRIGHT ZOOM_IN_FROM_BOTTOM ZOOM_IN_FROM_LOWERLEFT ZOOM_IN_FROM_CENTER
444*0e16a31dSJim JagielskiZOOM_OUT_FROM_LEFT ZOOM_OUT_FROM_UPPERLEFT ZOOM_OUT_FROM_TOP ZOOM_OUT_FROM_UPPERRIGHT ZOOM_OUT_FROM_RIGHT ZOOM_OUT_FROM_LOWERRIGHT
445*0e16a31dSJim JagielskiZOOM_OUT_FROM_BOTTOM ZOOM_OUT_FROM_LOWERLEFT ZOOM_OUT_FROM_CENTER""".split()
446*0e16a31dSJim JagielskiCLICK_ACTIONS = "NONE PREVPAGE NEXTPAGE FIRSTPAGE LASTPAGE BOOKMARK DOCUMENT INVISIBLE SOUND VERB VANISH PROGRAM MACRO STOPPRESENTATION".split()
447*0e16a31dSJim Jagielski
448*0e16a31dSJim Jagielski
449*0e16a31dSJim Jagielskidef png(path, w=8, h=8):
450*0e16a31dSJim Jagielski    import zlib
451*0e16a31dSJim Jagielski    raw = b"".join(b"\x00" + b"".join(bytes((x * 30 % 256, y * 30 % 256, 128)) for x in range(w)) for y in range(h))
452*0e16a31dSJim Jagielski    def chunk(t, d):
453*0e16a31dSJim Jagielski        c = struct.pack(">I", len(d)) + t + d
454*0e16a31dSJim Jagielski        return c + struct.pack(">I", zlib.crc32(t + d) & 0xffffffff)
455*0e16a31dSJim Jagielski    data = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)) + chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b"")
456*0e16a31dSJim Jagielski    open(path, "wb").write(data)
457*0e16a31dSJim Jagielski
458*0e16a31dSJim Jagielski
459*0e16a31dSJim JagielskiPNG = os.path.join(tmp, "pix.png")
460*0e16a31dSJim Jagielskipng(PNG)
461*0e16a31dSJim JagielskiPNG_URL = uno.systemPathToFileUrl(PNG)
462*0e16a31dSJim Jagielski
463*0e16a31dSJim Jagielski
464*0e16a31dSJim Jagielskidef actions():
465*0e16a31dSJim Jagielski    doc = new("odp")
466*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
467*0e16a31dSJim Jagielski    pg2 = add_page(doc)
468*0e16a31dSJim Jagielski    pg2.Name = "Target"
469*0e16a31dSJim Jagielski    x = 500
470*0e16a31dSJim Jagielski    y = 500
471*0e16a31dSJim Jagielski    for i, a in enumerate(CLICK_ACTIONS):
472*0e16a31dSJim Jagielski        sh = mk(doc, page, "RectangleShape", x=x, y=y, w=2000, h=1000, text=a)
473*0e16a31dSJim Jagielski        x += 2200
474*0e16a31dSJim Jagielski        if x > 22000:
475*0e16a31dSJim Jagielski            x = 500; y += 1200
476*0e16a31dSJim Jagielski        props = dict(OnClick=enum("ClickAction", a))
477*0e16a31dSJim Jagielski        if a in ("BOOKMARK",):
478*0e16a31dSJim Jagielski            props["Bookmark"] = "Target"
479*0e16a31dSJim Jagielski        if a in ("DOCUMENT",):
480*0e16a31dSJim Jagielski            props["Bookmark"] = "file:///tmp/other.odp#Slide1"
481*0e16a31dSJim Jagielski        if a == "PROGRAM":
482*0e16a31dSJim Jagielski            props["Bookmark"] = "file:///usr/bin/true"
483*0e16a31dSJim Jagielski        if a == "SOUND":
484*0e16a31dSJim Jagielski            props.update(Bookmark=SOUND_URL, PlayFull=True)
485*0e16a31dSJim Jagielski        if a == "VERB":
486*0e16a31dSJim Jagielski            props["Verb"] = 1
487*0e16a31dSJim Jagielski        if a == "MACRO":
488*0e16a31dSJim Jagielski            props["Bookmark"] = "macro:///Standard.Module1.Main"
489*0e16a31dSJim Jagielski        setp(sh, **props)
490*0e16a31dSJim Jagielski    for i, eff in enumerate(ANIM_EFFECTS):
491*0e16a31dSJim Jagielski        sh = mk(doc, page, "RectangleShape", x=500 + (i % 10) * 2200, y=6000 + (i // 10) * 1100, w=2000, h=900, text=eff[:14])
492*0e16a31dSJim Jagielski        setp(sh, OnClick=enum("ClickAction", "VANISH"), Effect=enum("AnimationEffect", eff),
493*0e16a31dSJim Jagielski             Speed=enum("AnimationSpeed", ("SLOW", "MEDIUM", "FAST")[i % 3]), SoundOn=bool(i % 2), Sound=SOUND_URL, PlayFull=bool(i % 3 == 0),
494*0e16a31dSJim Jagielski             DimPrevious=False, DimHide=False)
495*0e16a31dSJim Jagielski    save(doc, "click-actions.odp")
496*0e16a31dSJim Jagielski    done(doc)
497*0e16a31dSJim Jagielski
498*0e16a31dSJim Jagielski
499*0e16a31dSJim Jagielskidef draw_links():
500*0e16a31dSJim Jagielski    doc = new("odg")
501*0e16a31dSJim Jagielski    pages = [doc.DrawPages.getByIndex(0), add_page(doc)]
502*0e16a31dSJim Jagielski    pages[1].Name = "Second"
503*0e16a31dSJim Jagielski    for i, a in enumerate(("BOOKMARK", "DOCUMENT")):
504*0e16a31dSJim Jagielski        sh = mk(doc, pages[0], "RectangleShape", x=500 + i * 3500, text=a)
505*0e16a31dSJim Jagielski        setp(sh, OnClick=enum("ClickAction", a), Bookmark="Second" if i == 0 else "file:///tmp/other.odg#Page1")
506*0e16a31dSJim Jagielski    save(doc, "draw-links.odg")
507*0e16a31dSJim Jagielski    done(doc)
508*0e16a31dSJim Jagielski
509*0e16a31dSJim Jagielski
510*0e16a31dSJim Jagielskidef image_maps():
511*0e16a31dSJim Jagielski    doc = new("odg")
512*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
513*0e16a31dSJim Jagielski    g = mk(doc, page, "GraphicObjectShape", x=1000, y=1000, w=8000, h=6000)
514*0e16a31dSJim Jagielski    g.GraphicURL = PNG_URL
515*0e16a31dSJim Jagielski    imap = g.ImageMap
516*0e16a31dSJim Jagielski    r = doc.createInstance("com.sun.star.image.ImageMapRectangleObject")
517*0e16a31dSJim Jagielski    r.Boundary = struct_("com.sun.star.awt.Rectangle", 0, 0, 3000, 2000)
518*0e16a31dSJim Jagielski    r.URL = "http://example.org/rect"
519*0e16a31dSJim Jagielski    r.Target = "_blank"
520*0e16a31dSJim Jagielski    r.Description = "rect area"
521*0e16a31dSJim Jagielski    r.IsActive = True
522*0e16a31dSJim Jagielski    r.Name = "r1"
523*0e16a31dSJim Jagielski    imap.insertByIndex(0, r)
524*0e16a31dSJim Jagielski    c = doc.createInstance("com.sun.star.image.ImageMapCircleObject")
525*0e16a31dSJim Jagielski    c.Center = pt(5000, 3000)
526*0e16a31dSJim Jagielski    c.Radius = 1000
527*0e16a31dSJim Jagielski    c.URL = "http://example.org/circle"
528*0e16a31dSJim Jagielski    c.Title = "circle title"
529*0e16a31dSJim Jagielski    c.IsActive = False
530*0e16a31dSJim Jagielski    imap.insertByIndex(1, c)
531*0e16a31dSJim Jagielski    po = doc.createInstance("com.sun.star.image.ImageMapPolygonObject")
532*0e16a31dSJim Jagielski    po.Polygon = (pt(0, 0), pt(100, 0), pt(100, 100), pt(0, 100))
533*0e16a31dSJim Jagielski    po.URL = "#target"
534*0e16a31dSJim Jagielski    po.Description = "poly area"
535*0e16a31dSJim Jagielski    imap.insertByIndex(2, po)
536*0e16a31dSJim Jagielski    g.ImageMap = imap
537*0e16a31dSJim Jagielski    gr2 = mk(doc, page, "GraphicObjectShape", x=10000, y=1000, w=3000, h=3000)
538*0e16a31dSJim Jagielski    gr2.GraphicURL = PNG_URL
539*0e16a31dSJim Jagielski    setp(gr2, Title="a picture", Description="a described picture")
540*0e16a31dSJim Jagielski    save(doc, "image-map.odg")
541*0e16a31dSJim Jagielski    done(doc)
542*0e16a31dSJim Jagielski
543*0e16a31dSJim Jagielski
544*0e16a31dSJim Jagielskidef pts(*xy):
545*0e16a31dSJim Jagielski    return tuple(pt(x, y) for x, y in xy)
546*0e16a31dSJim Jagielski
547*0e16a31dSJim Jagielski
548*0e16a31dSJim Jagielskidef poly(doc, page, service, points, **props):
549*0e16a31dSJim Jagielski    s_ = doc.createInstance("com.sun.star.drawing." + service)
550*0e16a31dSJim Jagielski    page.add(s_)
551*0e16a31dSJim Jagielski    s_.PolyPolygon = (pts(*points),)
552*0e16a31dSJim Jagielski    setp(s_, **props)
553*0e16a31dSJim Jagielski    return s_
554*0e16a31dSJim Jagielski
555*0e16a31dSJim Jagielski
556*0e16a31dSJim Jagielskidef bezier(doc, page, service, **props):
557*0e16a31dSJim Jagielski    s_ = doc.createInstance("com.sun.star.drawing." + service)
558*0e16a31dSJim Jagielski    page.add(s_)
559*0e16a31dSJim Jagielski    C = uno.Enum("com.sun.star.drawing.PolygonFlags", "NORMAL")
560*0e16a31dSJim Jagielski    K = uno.Enum("com.sun.star.drawing.PolygonFlags", "CONTROL")
561*0e16a31dSJim Jagielski    coords = struct_("com.sun.star.drawing.PolyPolygonBezierCoords")
562*0e16a31dSJim Jagielski    coords.Coordinates = (pts((1000, 1000), (2000, 0), (3000, 2000), (4000, 1000), (5000, 3000), (1000, 3000)),)
563*0e16a31dSJim Jagielski    coords.Flags = ((C, K, K, C, C, C),)
564*0e16a31dSJim Jagielski    s_.PolyPolygonBezier = coords
565*0e16a31dSJim Jagielski    setp(s_, **props)
566*0e16a31dSJim Jagielski    return s_
567*0e16a31dSJim Jagielski
568*0e16a31dSJim Jagielski
569*0e16a31dSJim Jagielskidef shapes_core(doc, page):
570*0e16a31dSJim Jagielski    mk(doc, page, "RectangleShape", x=500, y=500, text="plain", Name="rect1")
571*0e16a31dSJim Jagielski    mk(doc, page, "RectangleShape", x=4000, y=500, text="round", CornerRadius=400, RotateAngle=3000, ShearAngle=500, Name="rect2")
572*0e16a31dSJim Jagielski    mk(doc, page, "RectangleShape", x=8000, y=500, text="rot", RotateAngle=9000)
573*0e16a31dSJim Jagielski    for i, kind in enumerate(("FULL", "CUT", "SECTION", "ARC")):
574*0e16a31dSJim Jagielski        ck = uno.Enum("com.sun.star.drawing.CircleKind", kind)
575*0e16a31dSJim Jagielski        mk(doc, page, "EllipseShape", x=500 + i * 2600, y=3500, w=2400, h=2400, CircleKind=ck,
576*0e16a31dSJim Jagielski           CircleStartAngle=3000, CircleEndAngle=24000, Name="circle-" + kind)
577*0e16a31dSJim Jagielski        mk(doc, page, "EllipseShape", x=500 + i * 3200, y=6500, w=3000, h=2000, CircleKind=ck,
578*0e16a31dSJim Jagielski           CircleStartAngle=3000, CircleEndAngle=24000, Name="ellipse-" + kind)
579*0e16a31dSJim Jagielski        mk(doc, page, "EllipseShape", x=500 + i * 3200, y=9000, w=2400, h=2400, CircleKind=ck, RotateAngle=4500,
580*0e16a31dSJim Jagielski           CircleStartAngle=3000, CircleEndAngle=24000)
581*0e16a31dSJim Jagielski    mk(doc, page, "EllipseShape", x=22000, y=9000, w=3000, h=2000, RotateAngle=2500, Name="ellipse-rot")
582*0e16a31dSJim Jagielski    poly(doc, page, "LineShape", ((500, 12000), (4000, 13000)), Name="line1")
583*0e16a31dSJim Jagielski    poly(doc, page, "LineShape", ((4500, 12000), (8000, 13000)), RotateAngle=2000)
584*0e16a31dSJim Jagielski    poly(doc, page, "PolyLineShape", ((9000, 12000), (10000, 14000), (11000, 12000), (12000, 14000)), Name="polyline1")
585*0e16a31dSJim Jagielski    poly(doc, page, "PolyLineShape", ((13000, 12000), (14000, 14000), (15000, 12000)), RotateAngle=3000)
586*0e16a31dSJim Jagielski    poly(doc, page, "PolyPolygonShape", ((16000, 12000), (18000, 12000), (17000, 14000)), Name="polygon1")
587*0e16a31dSJim Jagielski    poly(doc, page, "PolyPolygonShape", ((19000, 12000), (21000, 12000), (20000, 14000)), RotateAngle=1500)
588*0e16a31dSJim Jagielski    bezier(doc, page, "ClosedBezierShape", Name="path-closed")
589*0e16a31dSJim Jagielski    bezier(doc, page, "OpenBezierShape", RotateAngle=1000)
590*0e16a31dSJim Jagielski    bezier(doc, page, "ClosedFreeHandShape")
591*0e16a31dSJim Jagielski    bezier(doc, page, "OpenFreeHandShape")
592*0e16a31dSJim Jagielski    poly(doc, page, "PolyLinePathShape", ((1000, 16000), (2000, 17000), (3000, 16000)))
593*0e16a31dSJim Jagielski    poly(doc, page, "PolyPolygonPathShape", ((4000, 16000), (6000, 16000), (5000, 17500)))
594*0e16a31dSJim Jagielski    mk(doc, page, "TextShape", x=7000, y=16000, w=4000, h=1000, text="text box", TextAutoGrowHeight=True,
595*0e16a31dSJim Jagielski       TextMinimumFrameWidth=2000, TextMaximumFrameWidth=6000, TextMinimumFrameHeight=500, TextMaximumFrameHeight=3000, Name="text1")
596*0e16a31dSJim Jagielski    t = mk(doc, page, "TextShape", x=12000, y=16000, w=4000, h=1000, text="titled")
597*0e16a31dSJim Jagielski    setp(t, Title="text title", Description="text description")
598*0e16a31dSJim Jagielski    g1 = mk(doc, page, "RectangleShape", x=500, y=18000, text="g1")
599*0e16a31dSJim Jagielski    g2 = mk(doc, page, "EllipseShape", x=4000, y=18000, text="g2")
600*0e16a31dSJim Jagielski    grp = doc.createInstance("com.sun.star.drawing.GroupShape")
601*0e16a31dSJim Jagielski    page.add(grp)
602*0e16a31dSJim Jagielski    grp.add(g1)
603*0e16a31dSJim Jagielski    grp.add(g2)
604*0e16a31dSJim Jagielski    setp(grp, Name="group1", Title="group title", Description="group desc")
605*0e16a31dSJim Jagielski    inner = doc.createInstance("com.sun.star.drawing.GroupShape")
606*0e16a31dSJim Jagielski    page.add(inner)
607*0e16a31dSJim Jagielski    inner.add(mk(doc, page, "RectangleShape", x=8000, y=18000, text="n1"))
608*0e16a31dSJim Jagielski    inner.add(mk(doc, page, "RectangleShape", x=11000, y=18000, text="n2"))
609*0e16a31dSJim Jagielski    outer = doc.createInstance("com.sun.star.drawing.GroupShape")
610*0e16a31dSJim Jagielski    page.add(outer)
611*0e16a31dSJim Jagielski    outer.add(inner)
612*0e16a31dSJim Jagielski    outer.add(mk(doc, page, "RectangleShape", x=14000, y=18000, text="n3"))
613*0e16a31dSJim Jagielski    setp(outer, Name="group2")
614*0e16a31dSJim Jagielski
615*0e16a31dSJim Jagielski
616*0e16a31dSJim Jagielskidef connectors(doc, page):
617*0e16a31dSJim Jagielski    r = [mk(doc, page, "RectangleShape", x=1000 + (i % 3) * 6000, y=1000 + (i // 3) * 5000, w=2500, h=1500, text="n%d" % i, Name="node%d" % i)
618*0e16a31dSJim Jagielski         for i in range(9)]
619*0e16a31dSJim Jagielski    for i in range(4):
620*0e16a31dSJim Jagielski        gp = struct_("com.sun.star.drawing.GluePoint2")
621*0e16a31dSJim Jagielski        gp.Position = pt(500 * i, 200 * i)
622*0e16a31dSJim Jagielski        gp.IsRelative = bool(i % 2)
623*0e16a31dSJim Jagielski        gp.PositionAlignment = uno.Enum("com.sun.star.drawing.Alignment", ("TOP_LEFT", "CENTER", "BOTTOM_RIGHT", "LEFT")[i])
624*0e16a31dSJim Jagielski        gp.Escape = uno.Enum("com.sun.star.drawing.EscapeDirection", ("SMART", "LEFT", "UP", "DOWN")[i])
625*0e16a31dSJim Jagielski        gp.IsUserDefined = True
626*0e16a31dSJim Jagielski        r[0].GluePoints.insert(gp)
627*0e16a31dSJim Jagielski    escs = ("SMART", "LEFT", "RIGHT", "UP", "DOWN", "HORIZONTAL", "VERTICAL")
628*0e16a31dSJim Jagielski    for i, esc in enumerate(escs):
629*0e16a31dSJim Jagielski        gp = struct_("com.sun.star.drawing.GluePoint2")
630*0e16a31dSJim Jagielski        gp.Position = pt(100 * i, 100 * i)
631*0e16a31dSJim Jagielski        gp.IsRelative = False
632*0e16a31dSJim Jagielski        gp.PositionAlignment = uno.Enum("com.sun.star.drawing.Alignment", ("TOP_LEFT", "TOP", "TOP_RIGHT", "LEFT", "CENTER", "RIGHT", "BOTTOM_LEFT")[i])
633*0e16a31dSJim Jagielski        gp.Escape = uno.Enum("com.sun.star.drawing.EscapeDirection", esc)
634*0e16a31dSJim Jagielski        gp.IsUserDefined = True
635*0e16a31dSJim Jagielski        r[1].GluePoints.insert(gp)
636*0e16a31dSJim Jagielski    kinds = ("STANDARD", "CURVE", "LINE", "LINES")
637*0e16a31dSJim Jagielski    n = 0
638*0e16a31dSJim Jagielski    for k in kinds:
639*0e16a31dSJim Jagielski        c = doc.createInstance("com.sun.star.drawing.ConnectorShape")
640*0e16a31dSJim Jagielski        page.add(c)
641*0e16a31dSJim Jagielski        c.EdgeKind = uno.Enum("com.sun.star.drawing.ConnectorType", k)
642*0e16a31dSJim Jagielski        c.StartShape = r[n % 9]
643*0e16a31dSJim Jagielski        c.EndShape = r[(n + 4) % 9]
644*0e16a31dSJim Jagielski        c.StartGluePointIndex = 0 if n % 2 else 4
645*0e16a31dSJim Jagielski        c.EndGluePointIndex = 5 + n
646*0e16a31dSJim Jagielski        setp(c, Title="conn " + k, Description="connector " + k, EdgeLine1Delta=300, EdgeLine2Delta=-300, EdgeNode1HorzDist=100, EdgeNode2VertDist=200)
647*0e16a31dSJim Jagielski        n += 1
648*0e16a31dSJim Jagielski        c2 = doc.createInstance("com.sun.star.drawing.ConnectorShape")
649*0e16a31dSJim Jagielski        page.add(c2)
650*0e16a31dSJim Jagielski        c2.EdgeKind = uno.Enum("com.sun.star.drawing.ConnectorType", k)
651*0e16a31dSJim Jagielski        c2.StartPosition = pt(1000, 12000 + n * 700)
652*0e16a31dSJim Jagielski        c2.EndPosition = pt(9000, 13000 + n * 900)
653*0e16a31dSJim Jagielski        c2.String = "free " + k
654*0e16a31dSJim Jagielski
655*0e16a31dSJim Jagielski
656*0e16a31dSJim Jagielskidef measure_caption(doc, page):
657*0e16a31dSJim Jagielski    for i, (a, b) in enumerate((((1000, 1000), (9000, 1000)), ((1000, 3000), (9000, 6000)), ((11000, 1000), (11000, 8000)))):
658*0e16a31dSJim Jagielski        m = doc.createInstance("com.sun.star.drawing.MeasureShape")
659*0e16a31dSJim Jagielski        page.add(m)
660*0e16a31dSJim Jagielski        m.StartPosition = pt(*a)
661*0e16a31dSJim Jagielski        m.EndPosition = pt(*b)
662*0e16a31dSJim Jagielski        setp(m, Name="measure%d" % i, MeasureTextHorizontalPosition=i % 4, MeasureTextVerticalPosition=i % 4,
663*0e16a31dSJim Jagielski             MeasureLineDistance=500, MeasureHelpLine1Length=200, MeasureHelpLine2Length=200, MeasureOverhang=100,
664*0e16a31dSJim Jagielski             MeasureUnit=i, MeasureShowUnit=True, MeasureBelowReferenceEdge=bool(i % 2), MeasureTextRotate90=bool(i % 2),
665*0e16a31dSJim Jagielski             MeasureTextIsFixedAngle=True, MeasureTextFixedAngle=1500 * i, MeasureDecimalPlaces=2,
666*0e16a31dSJim Jagielski             MeasureTextAutoAngle=False, MeasureTextAutoAngleView=i, Title="m", Description="measure")
667*0e16a31dSJim Jagielski        m.String = "measure %d" % i
668*0e16a31dSJim Jagielski    for i in range(3):
669*0e16a31dSJim Jagielski        c = doc.createInstance("com.sun.star.drawing.CaptionShape")
670*0e16a31dSJim Jagielski        page.add(c)
671*0e16a31dSJim Jagielski        c.Position = pt(1000 + i * 7000, 10000)
672*0e16a31dSJim Jagielski        c.Size = sz(4000, 2000)
673*0e16a31dSJim Jagielski        c.String = "caption %d" % i
674*0e16a31dSJim Jagielski        setp(c, CaptionPoint=pt(500 + i * 7000, 14000), CaptionType=i, CaptionIsFitLineLength=bool(i % 2), CaptionIsEscapeRelative=bool(i % 2),
675*0e16a31dSJim Jagielski             CaptionEscapeDirection=i, CaptionEscapeRelative=500, CaptionEscapeAbsolute=300, CaptionLineLength=700,
676*0e16a31dSJim Jagielski             CaptionGap=100, CaptionAngle=300 * i, CornerRadius=300 * i, Name="caption%d" % i)
677*0e16a31dSJim Jagielski
678*0e16a31dSJim Jagielski
679*0e16a31dSJim Jagielskidef layers_doc():
680*0e16a31dSJim Jagielski    doc = new("odg")
681*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
682*0e16a31dSJim Jagielski    lm = doc.LayerManager
683*0e16a31dSJim Jagielski    for i, nm in enumerate(("layerA", "layerB")):
684*0e16a31dSJim Jagielski        ly = lm.insertNewByIndex(lm.Count)
685*0e16a31dSJim Jagielski        ly.Name = nm
686*0e16a31dSJim Jagielski        setp(ly, IsVisible=bool(i % 2 == 0), IsPrintable=bool(i == 0), IsLocked=bool(i == 1), Title="t" + nm, Description="d" + nm)
687*0e16a31dSJim Jagielski        sh = mk(doc, page, "RectangleShape", x=500 + 3000 * i, text=nm)
688*0e16a31dSJim Jagielski        sh.LayerName = nm
689*0e16a31dSJim Jagielski    for k, v in enumerate(("a", "b")):
690*0e16a31dSJim Jagielski        sh = mk(doc, page, "EllipseShape", x=500 + 3000 * k, y=4000, text="nav%d" % k)
691*0e16a31dSJim Jagielski    try:
692*0e16a31dSJim Jagielski        order = smgr.createInstance("com.sun.star.drawing.ShapeCollection")
693*0e16a31dSJim Jagielski        for i in reversed(range(page.Count)):
694*0e16a31dSJim Jagielski            order.add(page.getByIndex(i))
695*0e16a31dSJim Jagielski        page.NavigationOrder = order
696*0e16a31dSJim Jagielski    except Exception as e:
697*0e16a31dSJim Jagielski        print("  navorder", repr(e)[:150])
698*0e16a31dSJim Jagielski    save(doc, "layers.odg")
699*0e16a31dSJim Jagielski    done(doc)
700*0e16a31dSJim Jagielski
701*0e16a31dSJim Jagielski
702*0e16a31dSJim Jagielskidef shapes_docs():
703*0e16a31dSJim Jagielski    for kind in ("odg", "odp"):
704*0e16a31dSJim Jagielski        for label, fn in (("core", shapes_core), ("connectors", connectors), ("measure", measure_caption)):
705*0e16a31dSJim Jagielski            doc = new(kind)
706*0e16a31dSJim Jagielski            page = doc.DrawPages.getByIndex(0)
707*0e16a31dSJim Jagielski            step("%s-%s" % (label, kind), fn, doc, page)
708*0e16a31dSJim Jagielski            save(doc, "%s.%s" % (label, kind))
709*0e16a31dSJim Jagielski            done(doc)
710*0e16a31dSJim Jagielski
711*0e16a31dSJim Jagielski
712*0e16a31dSJim Jagielskidef p3(x, y, z):
713*0e16a31dSJim Jagielski    return struct_("com.sun.star.drawing.Position3D", x, y, z)
714*0e16a31dSJim Jagielski
715*0e16a31dSJim Jagielski
716*0e16a31dSJim Jagielskidef d3(x, y, z):
717*0e16a31dSJim Jagielski    return struct_("com.sun.star.drawing.Direction3D", x, y, z)
718*0e16a31dSJim Jagielski
719*0e16a31dSJim Jagielski
720*0e16a31dSJim Jagielskidef scene_3d(doc, page, x, y, nm, mode="SMOOTH", proj="PERSPECTIVE", extra=None):
721*0e16a31dSJim Jagielski    sc = doc.createInstance("com.sun.star.drawing.Shape3DSceneObject")
722*0e16a31dSJim Jagielski    page.add(sc)
723*0e16a31dSJim Jagielski    sc.Position = pt(x, y)
724*0e16a31dSJim Jagielski    sc.Size = sz(5000, 5000)
725*0e16a31dSJim Jagielski    cube = doc.createInstance("com.sun.star.drawing.Shape3DCubeObject")
726*0e16a31dSJim Jagielski    sc.add(cube)
727*0e16a31dSJim Jagielski    setp(cube, D3DPosition=p3(-1000, -1000, -1000), D3DSize=d3(2000, 3000, 2500))
728*0e16a31dSJim Jagielski    sph = doc.createInstance("com.sun.star.drawing.Shape3DSphereObject")
729*0e16a31dSJim Jagielski    sc.add(sph)
730*0e16a31dSJim Jagielski    setp(sph, D3DPosition=p3(500, 500, 0), D3DSize=d3(1500, 1500, 1500), D3DHorizontalSegments=12, D3DVerticalSegments=10)
731*0e16a31dSJim Jagielski    ex = doc.createInstance("com.sun.star.drawing.Shape3DExtrudeObject")
732*0e16a31dSJim Jagielski    sc.add(ex)
733*0e16a31dSJim Jagielski    poly3 = struct_("com.sun.star.drawing.PolyPolygonShape3D")
734*0e16a31dSJim Jagielski    poly3.SequenceX = ((0.0, 1000.0, 1000.0, 0.0),)
735*0e16a31dSJim Jagielski    poly3.SequenceY = ((0.0, 0.0, 1000.0, 1000.0),)
736*0e16a31dSJim Jagielski    poly3.SequenceZ = ((0.0, 0.0, 0.0, 0.0),)
737*0e16a31dSJim Jagielski    setp(ex, D3DPolyPolygon3D=poly3, D3DDepth=700, D3DPercentDiagonal=5, D3DDoubleSided=True,
738*0e16a31dSJim Jagielski         D3DCloseFront=True, D3DCloseBack=False, D3DNormalsKind=uno.Enum("com.sun.star.drawing.NormalsKind", "SPECIFIC"),
739*0e16a31dSJim Jagielski         D3DNormalsInvert=True, D3DTextureProjectionX=uno.Enum("com.sun.star.drawing.TextureProjectionMode", "SPHERE"),
740*0e16a31dSJim Jagielski         D3DTextureProjectionY=uno.Enum("com.sun.star.drawing.TextureProjectionMode", "OBJECTSPECIFIC"),
741*0e16a31dSJim Jagielski         D3DTextureKind=uno.Enum("com.sun.star.drawing.TextureKind", "COLOR"),
742*0e16a31dSJim Jagielski         D3DTextureMode=uno.Enum("com.sun.star.drawing.TextureMode", "BLEND"), D3DTextureFilter=True,
743*0e16a31dSJim Jagielski         D3DMaterialColor=0x336699, D3DMaterialEmission=0x101010, D3DMaterialSpecular=0xAAAAAA, D3DMaterialSpecularIntensity=40,
744*0e16a31dSJim Jagielski         D3DShadow3D=True)
745*0e16a31dSJim Jagielski    la = doc.createInstance("com.sun.star.drawing.Shape3DLatheObject")
746*0e16a31dSJim Jagielski    sc.add(la)
747*0e16a31dSJim Jagielski    poly4 = struct_("com.sun.star.drawing.PolyPolygonShape3D")
748*0e16a31dSJim Jagielski    poly4.SequenceX = ((500.0, 1500.0, 1000.0),)
749*0e16a31dSJim Jagielski    poly4.SequenceY = ((0.0, 0.0, 1500.0),)
750*0e16a31dSJim Jagielski    poly4.SequenceZ = ((0.0, 0.0, 0.0),)
751*0e16a31dSJim Jagielski    setp(la, D3DPolyPolygon3D=poly4, D3DHorizontalSegments=16, D3DEndAngle=2700, D3DPercentDiagonal=10)
752*0e16a31dSJim Jagielski    cg = struct_("com.sun.star.drawing.CameraGeometry")
753*0e16a31dSJim Jagielski    cg.vrp = p3(0.0, 0.0, 6000.0)
754*0e16a31dSJim Jagielski    cg.vpn = d3(1.0, 1.0, 5.0)
755*0e16a31dSJim Jagielski    cg.vup = d3(0.0, 1.0, 0.2)
756*0e16a31dSJim Jagielski    setp(sc, Name=nm, D3DCameraGeometry=cg, D3DScenePerspective=uno.Enum("com.sun.star.drawing.ProjectionMode", proj),
757*0e16a31dSJim Jagielski         D3DSceneShadeMode=uno.Enum("com.sun.star.drawing.ShadeMode", mode), D3DSceneDistance=3000, D3DSceneFocalLength=40,
758*0e16a31dSJim Jagielski         D3DSceneShadowSlant=15, D3DSceneAmbientColor=0x202040, D3DSceneTwoSidedLighting=True,
759*0e16a31dSJim Jagielski         D3DSceneLightOn1=True, D3DSceneLightOn2=True, D3DSceneLightOn3=False, D3DSceneLightColor1=0xFFFFFF,
760*0e16a31dSJim Jagielski         D3DSceneLightColor2=0xFF0000, D3DSceneLightColor5=0x00FF00, D3DSceneLightOn5=True,
761*0e16a31dSJim Jagielski         D3DSceneLightDirection1=d3(1.0, 1.0, 1.0), D3DSceneLightDirection2=d3(-1.0, 0.0, 1.0), RotateAngle=1000 if extra else 0,
762*0e16a31dSJim Jagielski         Title="3d scene", Description="a scene")
763*0e16a31dSJim Jagielski    if extra:
764*0e16a31dSJim Jagielski        setp(sc, **extra)
765*0e16a31dSJim Jagielski    return sc
766*0e16a31dSJim Jagielski
767*0e16a31dSJim Jagielski
768*0e16a31dSJim Jagielskidef threed(kind):
769*0e16a31dSJim Jagielski    doc = new(kind)
770*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
771*0e16a31dSJim Jagielski    n = 0
772*0e16a31dSJim Jagielski    for mode in ("FLAT", "PHONG", "SMOOTH", "DRAFT"):
773*0e16a31dSJim Jagielski        for proj in ("PERSPECTIVE", "PARALLEL"):
774*0e16a31dSJim Jagielski            step("scene-%s-%s" % (mode, proj), scene_3d, doc, page, 500 + (n % 4) * 5500, 500 + (n // 4) * 5500, "scene%d" % n, mode, proj)
775*0e16a31dSJim Jagielski            n += 1
776*0e16a31dSJim Jagielski    save(doc, "scenes.%s" % kind)
777*0e16a31dSJim Jagielski    done(doc)
778*0e16a31dSJim Jagielski
779*0e16a31dSJim Jagielski
780*0e16a31dSJim Jagielskidef pv_(name, value):
781*0e16a31dSJim Jagielski    return pv(name, value)
782*0e16a31dSJim Jagielski
783*0e16a31dSJim Jagielski
784*0e16a31dSJim Jagielskidef param(value, kind=0):
785*0e16a31dSJim Jagielski    p_ = struct_("com.sun.star.drawing.EnhancedCustomShapeParameter")
786*0e16a31dSJim Jagielski    p_.Value = value
787*0e16a31dSJim Jagielski    p_.Type = kind
788*0e16a31dSJim Jagielski    return p_
789*0e16a31dSJim Jagielski
790*0e16a31dSJim Jagielski
791*0e16a31dSJim Jagielskidef pair(a, b, ka=0, kb=0):
792*0e16a31dSJim Jagielski    pp = struct_("com.sun.star.drawing.EnhancedCustomShapeParameterPair")
793*0e16a31dSJim Jagielski    pp.First = param(a, ka)
794*0e16a31dSJim Jagielski    pp.Second = param(b, kb)
795*0e16a31dSJim Jagielski    return pp
796*0e16a31dSJim Jagielski
797*0e16a31dSJim Jagielski
798*0e16a31dSJim Jagielskidef custom(doc, page, x, y, w, h, geometry, text=None, **props):
799*0e16a31dSJim Jagielski    c = doc.createInstance("com.sun.star.drawing.CustomShape")
800*0e16a31dSJim Jagielski    page.add(c)
801*0e16a31dSJim Jagielski    c.Position = pt(x, y)
802*0e16a31dSJim Jagielski    c.Size = sz(w, h)
803*0e16a31dSJim Jagielski    if text:
804*0e16a31dSJim Jagielski        c.String = text
805*0e16a31dSJim Jagielski    c.CustomShapeGeometry = tuple(pv(k, v) for k, v in geometry)
806*0e16a31dSJim Jagielski    setp(c, **props)
807*0e16a31dSJim Jagielski    return c
808*0e16a31dSJim Jagielski
809*0e16a31dSJim Jagielski
810*0e16a31dSJim JagielskiPRESETS = """rectangle round-rectangle ellipse diamond isosceles-triangle right-triangle parallelogram trapezoid octagon hexagon pentagon cross
811*0e16a31dSJim Jagielskiring heart sun moon smiley-face lightning flower-1 cloud-callout star4 star5 star6 star8 star12 star24 right-arrow left-arrow up-arrow
812*0e16a31dSJim Jagielskidown-arrow left-right-arrow quad-arrow bent-arrow u-turn-arrow circular-arrow notched-right-arrow striped-right-arrow pentagon-right
813*0e16a31dSJim Jagielskichevron flowchart-process flowchart-decision flowchart-terminator flowchart-document flowchart-data flowchart-connector
814*0e16a31dSJim Jagielskiflowchart-card flowchart-delay flowchart-sort mso-spt100 mso-spt21 round-callout rectangular-callout line-callout-1 bracket-pair
815*0e16a31dSJim Jagielskibrace-pair left-bracket right-brace wave double-wave horizontal-scroll vertical-scroll cube can bevel frame folded-corner
816*0e16a31dSJim Jagielskiblock-arc forbidden down-ribbon up-ribbon quad-bevel octagon-bevel diamond-bevel left-right-up-arrow
817*0e16a31dSJim Jagielskiellipse-ribbon ellipse-ribbon-2 irregular-seal1 irregular-seal2 doorplate
818*0e16a31dSJim Jagielskifontwork-plain-text fontwork-slant-up fontwork-wave fontwork-fade-up-and-right fontwork-arch-up-curve fontwork-circle-curve
819*0e16a31dSJim Jagielskifontwork-open-circle-curve fontwork-arch-up-pour fontwork-circle-pour fontwork-triangle-up fontwork-stop fontwork-inflate""".split()
820*0e16a31dSJim Jagielski
821*0e16a31dSJim Jagielski
822*0e16a31dSJim Jagielskidef custom_shapes():
823*0e16a31dSJim Jagielski    doc = new("odg")
824*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
825*0e16a31dSJim Jagielski    for i, name in enumerate(PRESETS):
826*0e16a31dSJim Jagielski        step("preset " + name, custom, doc, page, 500 + (i % 8) * 2700, 500 + (i // 8) * 2300, 2400, 2000, [("Type", name)], text=name[:8])
827*0e16a31dSJim Jagielski    save(doc, "custom-presets.odg")
828*0e16a31dSJim Jagielski    done(doc)
829*0e16a31dSJim Jagielski
830*0e16a31dSJim Jagielski
831*0e16a31dSJim Jagielskidef custom_full():
832*0e16a31dSJim Jagielski    doc = new("odg")
833*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
834*0e16a31dSJim Jagielski    PV = "[]com.sun.star.beans.PropertyValue"
835*0e16a31dSJim Jagielski    ECS = "com.sun.star.drawing.EnhancedCustomShape"
836*0e16a31dSJim Jagielski    pairs = lambda seq: uno.Any("[]" + ECS + "ParameterPair", tuple(seq))
837*0e16a31dSJim Jagielski    shade = lambda n: uno.Enum("com.sun.star.drawing.ShadeMode", n)
838*0e16a31dSJim Jagielski    proj = lambda n: uno.Enum("com.sun.star.drawing.ProjectionMode", n)
839*0e16a31dSJim Jagielski    for i, (sm, pm) in enumerate((("FLAT", "PARALLEL"), ("PHONG", "PERSPECTIVE"), ("SMOOTH", "PARALLEL"), ("DRAFT", "PERSPECTIVE"))):
840*0e16a31dSJim Jagielski        ext = uno.Any(PV, (pv("Extrusion", True), pv("Brightness", 33.0), pv("Depth", pair(900.0, 0.5)), pv("Diffusion", 20.0),
841*0e16a31dSJim Jagielski               pv("NumberOfLineSegments", 12), pv("LightFace", bool(i % 2)), pv("FirstLightHarsh", True), pv("SecondLightHarsh", False),
842*0e16a31dSJim Jagielski               pv("FirstLightLevel", 60.0), pv("SecondLightLevel", 40.0), pv("FirstLightDirection", d3(10.0, 20.0, 30.0)),
843*0e16a31dSJim Jagielski               pv("SecondLightDirection", d3(-1.0, 2.0, 3.0)), pv("Metal", bool(i % 2)), pv("ShadeMode", shade(sm)),
844*0e16a31dSJim Jagielski               pv("RotateAngle", pair(10.0, 20.0)), pv("RotationCenter", d3(0.1, 0.2, 0.3)), pv("Shininess", 50.0),
845*0e16a31dSJim Jagielski               pv("Skew", pair(50.0, 135.0)), pv("Specularity", 70.0), pv("ProjectionMode", proj(pm)),
846*0e16a31dSJim Jagielski               pv("ViewPoint", p3(3500.0, -3500.0, 25000.0)), pv("Origin", pair(0.5, -0.5)), pv("Color", True)))
847*0e16a31dSJim Jagielski        tp = uno.Any(PV, (pv("TextPath", True), pv("TextPathMode", uno.Enum("com.sun.star.drawing.EnhancedCustomShapeTextPathMode", ("NORMAL", "PATH", "SHAPE", "NORMAL")[i])),
848*0e16a31dSJim Jagielski              pv("ScaleX", bool(i % 2)), pv("SameLetterHeights", bool(i // 2))))
849*0e16a31dSJim Jagielski        path = uno.Any(PV, (pv("ExtrusionAllowed", True), pv("ConcentricGradientFillAllowed", True), pv("TextPathAllowed", True),
850*0e16a31dSJim Jagielski                pv("GluePointType", i % 3), pv("StretchX", 100 * i), pv("StretchY", 50 * i),
851*0e16a31dSJim Jagielski                pv("GluePoints", pairs((pair(0, 0), pair(10800, 0), pair(21600, 21600)))),
852*0e16a31dSJim Jagielski                pv("Coordinates", pairs((pair(0, 0), pair(21600, 0), pair(21600, 21600), pair(0, 21600)))),
853*0e16a31dSJim Jagielski                pv("Segments", uno.Any("[]" + ECS + "Segment", (struct_(ECS + "Segment", 1, 1), struct_(ECS + "Segment", 2, 3), struct_(ECS + "Segment", 4, 1)))),
854*0e16a31dSJim Jagielski                pv("TextFrames", uno.Any("[]" + ECS + "TextFrame", (struct_(ECS + "TextFrame", pair(0, 0), pair(21600, 21600)),)))))
855*0e16a31dSJim Jagielski        h = uno.Any(PV, (pv("Position", pair(10800, 0)), pv("MirroredX", bool(i % 2)), pv("MirroredY", bool(i // 2)), pv("Switched", bool(i % 2)),
856*0e16a31dSJim Jagielski             pv("RangeXMinimum", param(0)), pv("RangeXMaximum", param(21600)), pv("RangeYMinimum", param(0)), pv("RangeYMaximum", param(21600))))
857*0e16a31dSJim Jagielski        hp = uno.Any(PV, (pv("Position", pair(10800, 10800)), pv("Polar", pair(10800, 10800)), pv("RadiusRangeMinimum", param(0)),
858*0e16a31dSJim Jagielski              pv("RadiusRangeMaximum", param(10800))))
859*0e16a31dSJim Jagielski        adj = struct_(ECS + "AdjustmentValue")
860*0e16a31dSJim Jagielski        adj.Value = 5400
861*0e16a31dSJim Jagielski        adj.State = uno.Enum("com.sun.star.beans.PropertyState", "DIRECT_VALUE")
862*0e16a31dSJim Jagielski        geo = [("Type", "non-primitive"), ("MirroredX", bool(i % 2)), ("MirroredY", bool(i // 2)),
863*0e16a31dSJim Jagielski               ("ViewBox", struct_("com.sun.star.awt.Rectangle", 0, 0, 21600, 21600)), ("TextRotateAngle", 15.0 * i),
864*0e16a31dSJim Jagielski               ("Extrusion", ext), ("TextPath", tp), ("Path", path), ("Equations", uno.Any("[]string", ("x*2", "?0 -3", "$0 +1"))),
865*0e16a31dSJim Jagielski               ("Handles", uno.Any("[][]com.sun.star.beans.PropertyValue", (h.value, hp.value))),
866*0e16a31dSJim Jagielski               ("AdjustmentValues", uno.Any("[]" + ECS + "AdjustmentValue", (adj,)))]
867*0e16a31dSJim Jagielski        step("custom-full-%d" % i, custom, doc, page, 500 + (i % 2) * 8000, 500 + (i // 2) * 7000, 7000, 6000, geo, text="fw%d" % i,
868*0e16a31dSJim Jagielski             CustomShapeEngine="com.sun.star.drawing.EnhancedCustomShapeEngine", CustomShapeData="data%d" % i)
869*0e16a31dSJim Jagielski    save(doc, "custom-full.odg")
870*0e16a31dSJim Jagielski    done(doc)
871*0e16a31dSJim Jagielski
872*0e16a31dSJim Jagielski
873*0e16a31dSJim Jagielskidef fontwork():
874*0e16a31dSJim Jagielski    doc = new("odg")
875*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
876*0e16a31dSJim Jagielski    for i, name in enumerate(("fontwork-plain-text", "fontwork-wave", "fontwork-slant-up", "fontwork-arch-up-curve", "fontwork-circle-pour")):
877*0e16a31dSJim Jagielski        geo = [("Type", name), ("TextPath", uno.Any("[]com.sun.star.beans.PropertyValue", (pv("TextPath", True), pv("TextPathMode", uno.Enum("com.sun.star.drawing.EnhancedCustomShapeTextPathMode", "SHAPE")),
878*0e16a31dSJim Jagielski                                              pv("ScaleX", False), pv("SameLetterHeights", bool(i % 2))))),
879*0e16a31dSJim Jagielski               ("Path", uno.Any("[]com.sun.star.beans.PropertyValue", (pv("TextPathAllowed", True), pv("ExtrusionAllowed", True)))),
880*0e16a31dSJim Jagielski               ("Extrusion", uno.Any("[]com.sun.star.beans.PropertyValue", (pv("Extrusion", bool(i % 2)),)))]
881*0e16a31dSJim Jagielski        c = step("fw-" + name, custom, doc, page, 500, 500 + i * 3200, 12000, 3000, geo, text="Fontwork " + name[9:])
882*0e16a31dSJim Jagielski        if c is not None:
883*0e16a31dSJim Jagielski            setp(c, TextAutoGrowHeight=False)
884*0e16a31dSJim Jagielski    save(doc, "fontwork.odg")
885*0e16a31dSJim Jagielski    done(doc)
886*0e16a31dSJim Jagielski
887*0e16a31dSJim Jagielski
888*0e16a31dSJim Jagielskidef cmds(**kw):
889*0e16a31dSJim Jagielski    return uno.Any("[]com.sun.star.beans.PropertyValue", tuple(pv(k, v) for k, v in kw.items()))
890*0e16a31dSJim Jagielski
891*0e16a31dSJim Jagielski
892*0e16a31dSJim Jagielskidef special_shapes(doc, page, impress):
893*0e16a31dSJim Jagielski    step("plugin", lambda: mk(doc, page, "PluginShape", x=500, y=500, w=4000, h=3000, PluginURL="file:///tmp/clip.mov",
894*0e16a31dSJim Jagielski                              PluginMimeType="video/quicktime", PluginCommands=cmds(autoplay="true", loop="false")))
895*0e16a31dSJim Jagielski    step("applet", lambda: mk(doc, page, "AppletShape", x=5000, y=500, w=4000, h=3000, AppletCodeBase="file:///tmp/",
896*0e16a31dSJim Jagielski                              AppletName="myapplet", AppletCode="Demo.class", AppletIsScript=True,
897*0e16a31dSJim Jagielski                              AppletCommands=cmds(speed="5", color="red")))
898*0e16a31dSJim Jagielski    step("frame", lambda: mk(doc, page, "FrameShape", x=10000, y=500, w=4000, h=3000, FrameURL="http://example.org/",
899*0e16a31dSJim Jagielski                             FrameName="myframe", FrameIsAutoScroll=True, FrameIsBorder=True, FrameMarginWidth=100, FrameMarginHeight=200))
900*0e16a31dSJim Jagielski    step("frame2", lambda: mk(doc, page, "FrameShape", x=15000, y=500, w=4000, h=3000, FrameURL="file:///tmp/x.html", FrameIsAutoScroll=False,
901*0e16a31dSJim Jagielski                              FrameIsBorder=False))
902*0e16a31dSJim Jagielski
903*0e16a31dSJim Jagielski    def media():
904*0e16a31dSJim Jagielski        m = mk(doc, page, "MediaShape", x=500, y=4000, w=4000, h=3000)
905*0e16a31dSJim Jagielski        setp(m, MediaURL=SOUND_URL, Loop=True, Mute=True, VolumeDB=-6,
906*0e16a31dSJim Jagielski             Zoom=uno.Enum("com.sun.star.media.ZoomLevel", "FIT_TO_WINDOW"))
907*0e16a31dSJim Jagielski        for i, z in enumerate(("ZOOM_1_TO_4", "ZOOM_1_TO_2", "ORIGINAL", "ZOOM_2_TO_1", "ZOOM_4_TO_1", "FIT_TO_WINDOW_FIXED_ASPECT", "FULLSCREEN")):
908*0e16a31dSJim Jagielski            m2 = mk(doc, page, "MediaShape", x=5000 + i * 2000, y=4000, w=1800, h=1500)
909*0e16a31dSJim Jagielski            setp(m2, MediaURL=SOUND_URL, Zoom=uno.Enum("com.sun.star.media.ZoomLevel", z))
910*0e16a31dSJim Jagielski    step("media", media)
911*0e16a31dSJim Jagielski    step("page-thumb", lambda: mk(doc, page, "PageShape", x=500, y=8000, w=4000, h=3000, PageNumber=1, Name="thumb"))
912*0e16a31dSJim Jagielski    step("page-thumb-rot", lambda: mk(doc, page, "PageShape", x=5000, y=8000, w=4000, h=3000, PageNumber=1, RotateAngle=2000,
913*0e16a31dSJim Jagielski                                      Title="thumb title", Description="thumb desc"))
914*0e16a31dSJim Jagielski    for i, (clsid, nm) in enumerate((("078B7ABA-54FC-457F-8551-6147E776A997", "math"), ("12DCAE26-281F-416F-A234-C3086127382E", "chart"),
915*0e16a31dSJim Jagielski                                     ("47BBB4CB-CE4C-4E80-A591-42D9AE74950F", "calc"))):
916*0e16a31dSJim Jagielski        def ole(clsid=clsid, nm=nm, i=i):
917*0e16a31dSJim Jagielski            o = doc.createInstance("com.sun.star.drawing.OLE2Shape")
918*0e16a31dSJim Jagielski            page.add(o)
919*0e16a31dSJim Jagielski            o.CLSID = clsid
920*0e16a31dSJim Jagielski            o.Position = pt(500 + i * 5000, 12000)
921*0e16a31dSJim Jagielski            o.Size = sz(4000, 3000)
922*0e16a31dSJim Jagielski            o.Name = "ole-" + nm
923*0e16a31dSJim Jagielski            o.Title = "ole"
924*0e16a31dSJim Jagielski            o.Description = nm
925*0e16a31dSJim Jagielski        step("ole-" + nm, ole)
926*0e16a31dSJim Jagielski
927*0e16a31dSJim Jagielski    def control():
928*0e16a31dSJim Jagielski        form = doc.createInstance("com.sun.star.form.component.Form")
929*0e16a31dSJim Jagielski        page.Forms.insertByIndex(0, form)
930*0e16a31dSJim Jagielski        for i, svc in enumerate(("CommandButton", "TextField", "CheckBox")):
931*0e16a31dSJim Jagielski            model = doc.createInstance("com.sun.star.form.component." + svc)
932*0e16a31dSJim Jagielski            model.Name = "ctl%d" % i
933*0e16a31dSJim Jagielski            form.insertByIndex(i, model)
934*0e16a31dSJim Jagielski            cs = doc.createInstance("com.sun.star.drawing.ControlShape")
935*0e16a31dSJim Jagielski            page.add(cs)
936*0e16a31dSJim Jagielski            cs.Position = pt(500 + i * 4000, 16000)
937*0e16a31dSJim Jagielski            cs.Size = sz(3000, 800)
938*0e16a31dSJim Jagielski            cs.Control = model
939*0e16a31dSJim Jagielski            setp(cs, Title="control", Description="ctl", Name="shape-ctl%d" % i, RotateAngle=0)
940*0e16a31dSJim Jagielski    step("control", control)
941*0e16a31dSJim Jagielski
942*0e16a31dSJim Jagielski
943*0e16a31dSJim Jagielskidef special_docs():
944*0e16a31dSJim Jagielski    for kind in ("odg", "odp"):
945*0e16a31dSJim Jagielski        doc = new(kind)
946*0e16a31dSJim Jagielski        page = doc.DrawPages.getByIndex(0)
947*0e16a31dSJim Jagielski        step("special-" + kind, special_shapes, doc, page, kind == "odp")
948*0e16a31dSJim Jagielski        save(doc, "special.%s" % kind)
949*0e16a31dSJim Jagielski        done(doc)
950*0e16a31dSJim Jagielski
951*0e16a31dSJim Jagielski
952*0e16a31dSJim Jagielskidef masters_and_notes():
953*0e16a31dSJim Jagielski    doc = new("odp")
954*0e16a31dSJim Jagielski    mp = doc.MasterPages.getByIndex(0)
955*0e16a31dSJim Jagielski    mp.Name = "MasterOne"
956*0e16a31dSJim Jagielski    mk(doc, mp, "RectangleShape", x=500, y=500, text="on master")
957*0e16a31dSJim Jagielski    mp2 = doc.MasterPages.insertNewByIndex(doc.MasterPages.Count)
958*0e16a31dSJim Jagielski    mp2.Name = "MasterTwo"
959*0e16a31dSJim Jagielski    mk(doc, mp2, "EllipseShape", x=500, y=500, text="master two")
960*0e16a31dSJim Jagielski    pages = [doc.DrawPages.getByIndex(0), add_page(doc)]
961*0e16a31dSJim Jagielski    pages[0].MasterPage = mp
962*0e16a31dSJim Jagielski    pages[1].MasterPage = mp2
963*0e16a31dSJim Jagielski    for i, p in enumerate(pages):
964*0e16a31dSJim Jagielski        mk(doc, p, "RectangleShape", text="slide %d" % i)
965*0e16a31dSJim Jagielski        np_ = p.NotesPage
966*0e16a31dSJim Jagielski        mk(doc, np_, "RectangleShape", x=500, y=9000, text="note shape")
967*0e16a31dSJim Jagielski        mk(doc, np_, "PageShape", x=500, y=500, w=4000, h=3000, PageNumber=i + 1)
968*0e16a31dSJim Jagielski    try:
969*0e16a31dSJim Jagielski        mk(doc, doc.getHandoutMasterPage(), "RectangleShape", x=500, y=500, text="handout")
970*0e16a31dSJim Jagielski    except Exception as e:
971*0e16a31dSJim Jagielski        print("  handout master", repr(e)[:100])
972*0e16a31dSJim Jagielski    save(doc, "masters-notes.odp")
973*0e16a31dSJim Jagielski    doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, "masters-notes.otp")), (pv("FilterName", "impress8_template"),))
974*0e16a31dSJim Jagielski    done(doc)
975*0e16a31dSJim Jagielski    doc = new("odg")
976*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
977*0e16a31dSJim Jagielski    mp = doc.MasterPages.getByIndex(0)
978*0e16a31dSJim Jagielski    mk(doc, mp, "RectangleShape", x=500, y=500, text="draw master")
979*0e16a31dSJim Jagielski    page.MasterPage = mp
980*0e16a31dSJim Jagielski    shapes_core(doc, page)
981*0e16a31dSJim Jagielski    save(doc, "draw-master.odg")
982*0e16a31dSJim Jagielski    doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, "draw-master.otg")), (pv("FilterName", "draw8_template"),))
983*0e16a31dSJim Jagielski    done(doc)
984*0e16a31dSJim Jagielski
985*0e16a31dSJim Jagielski
986*0e16a31dSJim JagielskiANCHORS = ("AS_CHARACTER", "AT_CHARACTER", "AT_PARAGRAPH", "AT_PAGE", "AT_FRAME")
987*0e16a31dSJim Jagielski
988*0e16a31dSJim Jagielski
989*0e16a31dSJim Jagielskidef anchor_enum(n):
990*0e16a31dSJim Jagielski    return uno.Enum("com.sun.star.text.TextContentAnchorType", n)
991*0e16a31dSJim Jagielski
992*0e16a31dSJim Jagielski
993*0e16a31dSJim Jagielskidef writer_shapes():
994*0e16a31dSJim Jagielski    doc = new("odt")
995*0e16a31dSJim Jagielski    text = doc.Text
996*0e16a31dSJim Jagielski    cur = text.createTextCursor()
997*0e16a31dSJim Jagielski    text.insertString(cur, "Anchoring test paragraph with some text to anchor to.", False)
998*0e16a31dSJim Jagielski    text.insertControlCharacter(cur, uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"), False)
999*0e16a31dSJim Jagielski    frame = doc.createInstance("com.sun.star.text.TextFrame")
1000*0e16a31dSJim Jagielski    frame.Size = sz(8000, 4000)
1001*0e16a31dSJim Jagielski    frame.Name = "Host"
1002*0e16a31dSJim Jagielski    frame.AnchorType = anchor_enum("AT_PARAGRAPH")
1003*0e16a31dSJim Jagielski    text.insertTextContent(cur, frame, False)
1004*0e16a31dSJim Jagielski    frame.Text.insertString(frame.Text.createTextCursor(), "frame text", False)
1005*0e16a31dSJim Jagielski    services = ("RectangleShape", "EllipseShape", "LineShape", "PolyPolygonShape", "ClosedBezierShape", "CustomShape", "TextShape")
1006*0e16a31dSJim Jagielski    for sv in services:
1007*0e16a31dSJim Jagielski        for a in ANCHORS:
1008*0e16a31dSJim Jagielski            def one(sv=sv, a=a):
1009*0e16a31dSJim Jagielski                if sv in ("LineShape", "PolyPolygonShape"):
1010*0e16a31dSJim Jagielski                    sh = doc.createInstance("com.sun.star.drawing." + sv)
1011*0e16a31dSJim Jagielski                    sh.PolyPolygon = (pts((0, 0), (1500, 800)) if sv == "LineShape" else pts((0, 0), (1500, 0), (800, 1000)),)
1012*0e16a31dSJim Jagielski                elif sv == "ClosedBezierShape":
1013*0e16a31dSJim Jagielski                    sh = doc.createInstance("com.sun.star.drawing.ClosedBezierShape")
1014*0e16a31dSJim Jagielski                    coords = struct_("com.sun.star.drawing.PolyPolygonBezierCoords")
1015*0e16a31dSJim Jagielski                    coords.Coordinates = (pts((0, 0), (1000, 0), (1000, 1000)),)
1016*0e16a31dSJim Jagielski                    N = uno.Enum("com.sun.star.drawing.PolygonFlags", "NORMAL")
1017*0e16a31dSJim Jagielski                    coords.Flags = ((N, N, N),)
1018*0e16a31dSJim Jagielski                    sh.PolyPolygonBezier = coords
1019*0e16a31dSJim Jagielski                else:
1020*0e16a31dSJim Jagielski                    sh = doc.createInstance("com.sun.star.drawing." + sv)
1021*0e16a31dSJim Jagielski                    sh.Size = sz(1500, 1000)
1022*0e16a31dSJim Jagielski                    if sv == "CustomShape":
1023*0e16a31dSJim Jagielski                        sh.CustomShapeGeometry = (pv("Type", "diamond"),)
1024*0e16a31dSJim Jagielski                sh.AnchorType = anchor_enum(a)
1025*0e16a31dSJim Jagielski                if a == "AT_PAGE":
1026*0e16a31dSJim Jagielski                    sh.AnchorPageNo = 1
1027*0e16a31dSJim Jagielski                cursor = text.createTextCursor()
1028*0e16a31dSJim Jagielski                cursor.gotoStart(False)
1029*0e16a31dSJim Jagielski                if a == "AT_FRAME":
1030*0e16a31dSJim Jagielski                    sh.AnchorFrame = frame
1031*0e16a31dSJim Jagielski                    frame.Text.insertTextContent(frame.Text.createTextCursor(), sh, False)
1032*0e16a31dSJim Jagielski                else:
1033*0e16a31dSJim Jagielski                    text.insertTextContent(cursor, sh, False)
1034*0e16a31dSJim Jagielski                setp(sh, Title="t " + sv, Description="d " + a)
1035*0e16a31dSJim Jagielski            step("%s-%s" % (sv, a), one)
1036*0e16a31dSJim Jagielski    def group():
1037*0e16a31dSJim Jagielski        for a in ANCHORS[:4]:
1038*0e16a31dSJim Jagielski            g = doc.createInstance("com.sun.star.drawing.GroupShape")
1039*0e16a31dSJim Jagielski            doc.DrawPage.add(g)
1040*0e16a31dSJim Jagielski            for k in range(2):
1041*0e16a31dSJim Jagielski                r = doc.createInstance("com.sun.star.drawing.RectangleShape")
1042*0e16a31dSJim Jagielski                r.Size = sz(800, 800)
1043*0e16a31dSJim Jagielski                r.Position = pt(k * 900, 0)
1044*0e16a31dSJim Jagielski                g.add(r)
1045*0e16a31dSJim Jagielski            g.AnchorType = anchor_enum(a)
1046*0e16a31dSJim Jagielski            if a == "AT_PAGE":
1047*0e16a31dSJim Jagielski                g.AnchorPageNo = 1
1048*0e16a31dSJim Jagielski    step("groups", group)
1049*0e16a31dSJim Jagielski
1050*0e16a31dSJim Jagielski    def controls():
1051*0e16a31dSJim Jagielski        form = doc.createInstance("com.sun.star.form.component.Form")
1052*0e16a31dSJim Jagielski        doc.DrawPage.Forms.insertByIndex(0, form)
1053*0e16a31dSJim Jagielski        for i, a in enumerate(ANCHORS):
1054*0e16a31dSJim Jagielski            model = doc.createInstance("com.sun.star.form.component.CommandButton")
1055*0e16a31dSJim Jagielski            model.Name = "btn%d" % i
1056*0e16a31dSJim Jagielski            form.insertByIndex(i, model)
1057*0e16a31dSJim Jagielski            cs = doc.createInstance("com.sun.star.drawing.ControlShape")
1058*0e16a31dSJim Jagielski            cs.Size = sz(2000, 700)
1059*0e16a31dSJim Jagielski            cs.Control = model
1060*0e16a31dSJim Jagielski            cs.AnchorType = anchor_enum(a)
1061*0e16a31dSJim Jagielski            if a == "AT_PAGE":
1062*0e16a31dSJim Jagielski                cs.AnchorPageNo = 1
1063*0e16a31dSJim Jagielski            if a == "AT_FRAME":
1064*0e16a31dSJim Jagielski                cs.AnchorFrame = frame
1065*0e16a31dSJim Jagielski            cursor = text.createTextCursor()
1066*0e16a31dSJim Jagielski            cursor.gotoStart(False)
1067*0e16a31dSJim Jagielski            if a == "AT_FRAME":
1068*0e16a31dSJim Jagielski                frame.Text.insertTextContent(frame.Text.createTextCursor(), cs, False)
1069*0e16a31dSJim Jagielski            else:
1070*0e16a31dSJim Jagielski                text.insertTextContent(cursor, cs, False)
1071*0e16a31dSJim Jagielski    step("controls", controls)
1072*0e16a31dSJim Jagielski    save(doc, "anchors.odt")
1073*0e16a31dSJim Jagielski    done(doc)
1074*0e16a31dSJim Jagielski
1075*0e16a31dSJim Jagielski
1076*0e16a31dSJim Jagielskidef writer_group_frame():
1077*0e16a31dSJim Jagielski    doc = new("odt")
1078*0e16a31dSJim Jagielski    text = doc.Text
1079*0e16a31dSJim Jagielski    cur = text.createTextCursor()
1080*0e16a31dSJim Jagielski    text.insertString(cur, "Group anchored to a frame.", False)
1081*0e16a31dSJim Jagielski    frame = doc.createInstance("com.sun.star.text.TextFrame")
1082*0e16a31dSJim Jagielski    frame.Size = sz(8000, 4000)
1083*0e16a31dSJim Jagielski    frame.AnchorType = anchor_enum("AT_PARAGRAPH")
1084*0e16a31dSJim Jagielski    text.insertTextContent(cur, frame, False)
1085*0e16a31dSJim Jagielski    g = doc.createInstance("com.sun.star.drawing.GroupShape")
1086*0e16a31dSJim Jagielski    r1 = doc.createInstance("com.sun.star.drawing.RectangleShape")
1087*0e16a31dSJim Jagielski    r1.Size = sz(800, 800)
1088*0e16a31dSJim Jagielski    g.AnchorType = anchor_enum("AT_FRAME")
1089*0e16a31dSJim Jagielski    g.AnchorFrame = frame
1090*0e16a31dSJim Jagielski    frame.Text.insertTextContent(frame.Text.createTextCursor(), g, False)
1091*0e16a31dSJim Jagielski    g.add(r1)
1092*0e16a31dSJim Jagielski    save(doc, "anchors-group-frame.odt")
1093*0e16a31dSJim Jagielski    done(doc)
1094*0e16a31dSJim Jagielski
1095*0e16a31dSJim Jagielski
1096*0e16a31dSJim Jagielskidef writer_graphics():
1097*0e16a31dSJim Jagielski    doc = new("odt")
1098*0e16a31dSJim Jagielski    text = doc.Text
1099*0e16a31dSJim Jagielski    cur = text.createTextCursor()
1100*0e16a31dSJim Jagielski    text.insertString(cur, "Graphics with contours, image maps and chained frames.", False)
1101*0e16a31dSJim Jagielski    text.insertControlCharacter(cur, uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"), False)
1102*0e16a31dSJim Jagielski    for i, (name, contour) in enumerate((("single", (pts((0, 0), (100, 0), (100, 100), (0, 100)),)),
1103*0e16a31dSJim Jagielski                                         ("multi", (pts((0, 0), (50, 0), (50, 50)), pts((60, 60), (100, 60), (100, 100)))),
1104*0e16a31dSJim Jagielski                                         ("none", None))):
1105*0e16a31dSJim Jagielski        def one(i=i, name=name, contour=contour):
1106*0e16a31dSJim Jagielski            g = doc.createInstance("com.sun.star.text.TextGraphicObject")
1107*0e16a31dSJim Jagielski            g.GraphicURL = PNG_URL
1108*0e16a31dSJim Jagielski            g.AnchorType = anchor_enum(("AS_CHARACTER", "AT_PARAGRAPH", "AT_PAGE")[i])
1109*0e16a31dSJim Jagielski            g.Width = 3000
1110*0e16a31dSJim Jagielski            g.Height = 2000
1111*0e16a31dSJim Jagielski            g.Name = "grf-" + name
1112*0e16a31dSJim Jagielski            if contour is not None:
1113*0e16a31dSJim Jagielski                setp(g, ContourPolyPolygon=contour, SurroundContour=True, ContourOutside=bool(i % 2), IsPixelContour=bool(i // 1 % 2))
1114*0e16a31dSJim Jagielski            setp(g, GraphicFilter="png", Title="graphic " + name, Description="described", GraphicRotation=900 * i)
1115*0e16a31dSJim Jagielski            cursor = text.createTextCursor()
1116*0e16a31dSJim Jagielski            cursor.gotoEnd(False)
1117*0e16a31dSJim Jagielski            text.insertTextContent(cursor, g, False)
1118*0e16a31dSJim Jagielski        step("grf-" + name, one)
1119*0e16a31dSJim Jagielski    def chain():
1120*0e16a31dSJim Jagielski        f1 = doc.createInstance("com.sun.star.text.TextFrame")
1121*0e16a31dSJim Jagielski        f2 = doc.createInstance("com.sun.star.text.TextFrame")
1122*0e16a31dSJim Jagielski        for f, nm in ((f1, "Chain1"), (f2, "Chain2")):
1123*0e16a31dSJim Jagielski            f.Name = nm
1124*0e16a31dSJim Jagielski            f.Size = sz(4000, 1500)
1125*0e16a31dSJim Jagielski            f.AnchorType = anchor_enum("AT_PARAGRAPH")
1126*0e16a31dSJim Jagielski            cursor = text.createTextCursor()
1127*0e16a31dSJim Jagielski            cursor.gotoEnd(False)
1128*0e16a31dSJim Jagielski            text.insertTextContent(cursor, f, False)
1129*0e16a31dSJim Jagielski        f1.ChainNextName = "Chain2"
1130*0e16a31dSJim Jagielski        f1.Text.insertString(f1.Text.createTextCursor(), "first frame of a chain " * 20, False)
1131*0e16a31dSJim Jagielski        f3 = doc.createInstance("com.sun.star.text.TextFrame")
1132*0e16a31dSJim Jagielski        f3.Name = "MinMax"
1133*0e16a31dSJim Jagielski        f3.Width = 3000
1134*0e16a31dSJim Jagielski        setp(f3, WidthType=uno.getConstantByName("com.sun.star.text.SizeType.MIN"), HeightType=uno.getConstantByName("com.sun.star.text.SizeType.MIN"),
1135*0e16a31dSJim Jagielski             Height=800)
1136*0e16a31dSJim Jagielski        f3.AnchorType = anchor_enum("AT_CHARACTER")
1137*0e16a31dSJim Jagielski        cursor = text.createTextCursor()
1138*0e16a31dSJim Jagielski        cursor.gotoEnd(False)
1139*0e16a31dSJim Jagielski        text.insertTextContent(cursor, f3, False)
1140*0e16a31dSJim Jagielski    step("chain", chain)
1141*0e16a31dSJim Jagielski    save(doc, "graphics.odt")
1142*0e16a31dSJim Jagielski    done(doc)
1143*0e16a31dSJim Jagielski
1144*0e16a31dSJim Jagielski
1145*0e16a31dSJim Jagielskidef calc_shapes():
1146*0e16a31dSJim Jagielski    doc = new("ods")
1147*0e16a31dSJim Jagielski    sh = doc.Sheets.getByIndex(0)
1148*0e16a31dSJim Jagielski    dp = sh.DrawPage
1149*0e16a31dSJim Jagielski    for r in range(6):
1150*0e16a31dSJim Jagielski        sh.getCellByPosition(0, r).String = "row %d" % r
1151*0e16a31dSJim Jagielski    kinds = ("RectangleShape", "EllipseShape", "LineShape", "PolyPolygonShape", "PolyLineShape", "ClosedBezierShape", "CustomShape",
1152*0e16a31dSJim Jagielski             "GraphicObjectShape", "TextShape", "ConnectorShape", "CaptionShape", "MeasureShape", "PageShape")
1153*0e16a31dSJim Jagielski    for i, sv in enumerate(kinds):
1154*0e16a31dSJim Jagielski        def one(i=i, sv=sv):
1155*0e16a31dSJim Jagielski            o = doc.createInstance("com.sun.star.drawing." + sv)
1156*0e16a31dSJim Jagielski            dp.add(o)
1157*0e16a31dSJim Jagielski            if sv in ("LineShape", "PolyPolygonShape", "PolyLineShape"):
1158*0e16a31dSJim Jagielski                o.PolyPolygon = (pts((0, 0), (1500, 0), (800, 1000)),)
1159*0e16a31dSJim Jagielski            elif sv == "ClosedBezierShape":
1160*0e16a31dSJim Jagielski                coords = struct_("com.sun.star.drawing.PolyPolygonBezierCoords")
1161*0e16a31dSJim Jagielski                coords.Coordinates = (pts((0, 0), (1000, 0), (1000, 1000)),)
1162*0e16a31dSJim Jagielski                N = uno.Enum("com.sun.star.drawing.PolygonFlags", "NORMAL")
1163*0e16a31dSJim Jagielski                coords.Flags = ((N, N, N),)
1164*0e16a31dSJim Jagielski                o.PolyPolygonBezier = coords
1165*0e16a31dSJim Jagielski            else:
1166*0e16a31dSJim Jagielski                o.Size = sz(2500, 1500)
1167*0e16a31dSJim Jagielski            if sv == "CustomShape":
1168*0e16a31dSJim Jagielski                o.CustomShapeGeometry = (pv("Type", "diamond"),)
1169*0e16a31dSJim Jagielski            if sv == "GraphicObjectShape":
1170*0e16a31dSJim Jagielski                o.GraphicURL = PNG_URL
1171*0e16a31dSJim Jagielski            if sv not in ("LineShape", "PolyPolygonShape", "PolyLineShape", "ClosedBezierShape", "ConnectorShape", "MeasureShape"):
1172*0e16a31dSJim Jagielski                o.Position = pt(500 + (i % 4) * 4000, 500 + (i // 4) * 3000)
1173*0e16a31dSJim Jagielski            elif sv == "ConnectorShape":
1174*0e16a31dSJim Jagielski                o.StartPosition = pt(500, 12000)
1175*0e16a31dSJim Jagielski                o.EndPosition = pt(5000, 14000)
1176*0e16a31dSJim Jagielski            elif sv == "MeasureShape":
1177*0e16a31dSJim Jagielski                o.StartPosition = pt(6000, 12000)
1178*0e16a31dSJim Jagielski                o.EndPosition = pt(10000, 12000)
1179*0e16a31dSJim Jagielski            if i % 2 == 0:
1180*0e16a31dSJim Jagielski                setp(o, Anchor=sh.getCellByPosition(1 + i % 3, i))
1181*0e16a31dSJim Jagielski            if i % 3 == 1:
1182*0e16a31dSJim Jagielski                setp(o, LayerName="background")
1183*0e16a31dSJim Jagielski            setp(o, Title="calc " + sv, Description="d")
1184*0e16a31dSJim Jagielski        step("calc-" + sv, one)
1185*0e16a31dSJim Jagielski    g = doc.createInstance("com.sun.star.drawing.GroupShape")
1186*0e16a31dSJim Jagielski    dp.add(g)
1187*0e16a31dSJim Jagielski    for k in range(2):
1188*0e16a31dSJim Jagielski        r = doc.createInstance("com.sun.star.drawing.RectangleShape")
1189*0e16a31dSJim Jagielski        r.Size = sz(800, 800)
1190*0e16a31dSJim Jagielski        r.Position = pt(k * 900 + 15000, 1000)
1191*0e16a31dSJim Jagielski        g.add(r)
1192*0e16a31dSJim Jagielski    sh2 = doc.Sheets.getByIndex(0)
1193*0e16a31dSJim Jagielski    save(doc, "shapes.ods")
1194*0e16a31dSJim Jagielski    done(doc)
1195*0e16a31dSJim Jagielski
1196*0e16a31dSJim Jagielski
1197*0e16a31dSJim Jagielskidef annotations_docs():
1198*0e16a31dSJim Jagielski    for kind in ("odp", "odg"):
1199*0e16a31dSJim Jagielski        doc = new(kind)
1200*0e16a31dSJim Jagielski        for n in range(2):
1201*0e16a31dSJim Jagielski            page = doc.DrawPages.getByIndex(0) if n == 0 else add_page(doc)
1202*0e16a31dSJim Jagielski            mk(doc, page, "RectangleShape", text="annotated %d" % n)
1203*0e16a31dSJim Jagielski            for k in range(2):
1204*0e16a31dSJim Jagielski                ann = page.createAndInsertAnnotation()
1205*0e16a31dSJim Jagielski                KEEP.append(ann)
1206*0e16a31dSJim Jagielski                ann.Author = "Tester %d" % k
1207*0e16a31dSJim Jagielski                ann.Position = struct_("com.sun.star.geometry.RealPoint2D", 3.0 + k, 4.0)
1208*0e16a31dSJim Jagielski                ann.Size = struct_("com.sun.star.geometry.RealSize2D", 5.0, 6.0)
1209*0e16a31dSJim Jagielski                ann.TextRange.String = "annotation %d.%d" % (n, k)
1210*0e16a31dSJim Jagielski                ann.DateTime = struct_("com.sun.star.util.DateTime", 0, 12, 30, 10, 5, 6, 2025)
1211*0e16a31dSJim Jagielski        save(doc, "annotations.%s" % kind)
1212*0e16a31dSJim Jagielski        done(doc)
1213*0e16a31dSJim Jagielski
1214*0e16a31dSJim Jagielski
1215*0e16a31dSJim Jagielskidef fills():
1216*0e16a31dSJim Jagielski    doc = new("odg")
1217*0e16a31dSJim Jagielski    page = doc.DrawPages.getByIndex(0)
1218*0e16a31dSJim Jagielski    GS = lambda n: uno.Enum("com.sun.star.awt.GradientStyle", n)
1219*0e16a31dSJim Jagielski    for i, gs in enumerate(("LINEAR", "AXIAL", "RADIAL", "ELLIPTICAL", "SQUARE", "RECT")):
1220*0e16a31dSJim Jagielski        g = struct_("com.sun.star.awt.Gradient", GS(gs), 0xFF0000, 0x0000FF, 450 * i, 10 * i, 40 + i, 60 - i, 100, 80, 5)
1221*0e16a31dSJim Jagielski        t = struct_("com.sun.star.awt.Gradient", GS(gs), 0x202020, 0xE0E0E0, 300 * i, 5 * i, 50, 50, 100, 100, 0)
1222*0e16a31dSJim Jagielski        mk(doc, page, "RectangleShape", x=500 + i * 3000, y=500, w=2800, h=2000, FillStyle=uno.Enum("com.sun.star.drawing.FillStyle", "GRADIENT"),
1223*0e16a31dSJim Jagielski           FillGradient=g)
1224*0e16a31dSJim Jagielski        tt = doc.createInstance("com.sun.star.drawing.TransparencyGradientTable")
1225*0e16a31dSJim Jagielski        tt.insertByName("trans-" + gs, t)
1226*0e16a31dSJim Jagielski        mk(doc, page, "RectangleShape", x=500 + i * 3000, y=3000, w=2800, h=2000, FillStyle=uno.Enum("com.sun.star.drawing.FillStyle", "SOLID"),
1227*0e16a31dSJim Jagielski           FillColor=0x3366CC, FillTransparenceGradientName="trans-" + gs)
1228*0e16a31dSJim Jagielski    for i, hs in enumerate(("SINGLE", "DOUBLE", "TRIPLE")):
1229*0e16a31dSJim Jagielski        h = struct_("com.sun.star.drawing.Hatch", uno.Enum("com.sun.star.drawing.HatchStyle", hs), 0x00AA00, 120 + 20 * i, 450 * i)
1230*0e16a31dSJim Jagielski        mk(doc, page, "RectangleShape", x=500 + i * 3000, y=5500, w=2800, h=2000, FillStyle=uno.Enum("com.sun.star.drawing.FillStyle", "HATCH"),
1231*0e16a31dSJim Jagielski           FillHatch=h, FillBackground=bool(i % 2), FillColor=0xFFEECC)
1232*0e16a31dSJim Jagielski    for i, ds in enumerate(("RECT", "ROUND", "RECTRELATIVE", "ROUNDRELATIVE")):
1233*0e16a31dSJim Jagielski        d = struct_("com.sun.star.drawing.LineDash", uno.Enum("com.sun.star.drawing.DashStyle", ds), 2, 100, 3, 300, 150)
1234*0e16a31dSJim Jagielski        mk(doc, page, "LineShape" if False else "RectangleShape", x=500 + i * 3000, y=8000, w=2800, h=1500,
1235*0e16a31dSJim Jagielski           LineStyle=uno.Enum("com.sun.star.drawing.LineStyle", "DASH"), LineDash=d, LineWidth=100)
1236*0e16a31dSJim Jagielski    save(doc, "fills.odg")
1237*0e16a31dSJim Jagielski    done(doc)
1238*0e16a31dSJim Jagielski
1239*0e16a31dSJim Jagielski
1240*0e16a31dSJim Jagielskitop("pres-settings", presentation_settings)
1241*0e16a31dSJim Jagielskitop("header-footer", header_footer)
1242*0e16a31dSJim Jagielskitop("layouts", layouts)
1243*0e16a31dSJim Jagielskitop("transitions", transitions)
1244*0e16a31dSJim Jagielskitop("animations", animations)
1245*0e16a31dSJim Jagielskitop("actions", actions)
1246*0e16a31dSJim Jagielskitop("draw-links", draw_links)
1247*0e16a31dSJim Jagielskitop("image-maps", image_maps)
1248*0e16a31dSJim Jagielskitop("shapes", shapes_docs)
1249*0e16a31dSJim Jagielskitop("layers", layers_doc)
1250*0e16a31dSJim Jagielskitop("special", special_docs)
1251*0e16a31dSJim Jagielskitop("annotations", annotations_docs)
1252*0e16a31dSJim Jagielskitop("fills", fills)
1253*0e16a31dSJim Jagielskitop("masters-notes", masters_and_notes)
1254*0e16a31dSJim Jagielskitop("writer-shapes", writer_shapes)
1255*0e16a31dSJim Jagielskitop("writer-group-frame", writer_group_frame)
1256*0e16a31dSJim Jagielskitop("writer-graphics", writer_graphics)
1257*0e16a31dSJim Jagielskitop("calc-shapes", calc_shapes)
1258*0e16a31dSJim Jagielskitop("custom-presets", custom_shapes)
1259*0e16a31dSJim Jagielskitop("custom-full", custom_full)
1260*0e16a31dSJim Jagielskitop("fontwork", fontwork)
1261*0e16a31dSJim Jagielskitop("3d-odg", threed, "odg")
1262*0e16a31dSJim Jagielskitop("3d-odp", threed, "odp")
1263*0e16a31dSJim Jagielski
1264*0e16a31dSJim Jagielskiprint("crashed steps (retried):", crashes)
1265*0e16a31dSJim Jagielskiprint("failed:", failed)
1266*0e16a31dSJim Jagielskisys.stdout.flush()
1267*0e16a31dSJim Jagielskios._exit(1 if failed else 0)
1268