xref: /trunk/test/odf-validate/fixtures/styles-gfx/make.py (revision 0e16a31d78a652c56c5c0fc79c752f48b9048df9)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#
21# usage: runpy.sh fixtures/styles-gfx/make.py <port> <outdir> [<document name>...]
22# Documents with every enumerated value of the graphic, drawing page, page layout, header/footer and table style
23# properties. Saves with the office's configured ODF version: run it against the strict and extended profiles.
24import sys, os, shutil, struct, tempfile, zlib, gc, uno
25from unohelp import connect, desktop, pv
26
27port, out = int(sys.argv[1]), os.path.abspath(sys.argv[2])
28only = set(sys.argv[3:])
29os.makedirs(out, exist_ok=True)
30ctx = connect(port)
31desk = desktop(ctx)
32failed = []
33NOPROP = set()
34work = tempfile.mkdtemp(prefix="styles-gfx-")
35SZ, PT = "com.sun.star.awt.Size", "com.sun.star.awt.Point"
36
37
38def E(typ, val):
39    return uno.Enum(typ, val)
40
41
42def st(name):
43    return uno.createUnoStruct(name)
44
45
46def png(path, w=16, h=16):
47    raw = b"".join(b"\x00" + bytes(v for x in range(w) for v in (x * 255 // w, y * 255 // h, 128)) for y in range(h))
48
49    def chunk(t, d):
50        c = struct.pack(">I", len(d)) + t + d
51        return c + struct.pack(">I", zlib.crc32(t + d) & 0xffffffff)
52    with open(path, "wb") as f:
53        f.write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)) +
54                chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b""))
55
56
57IMG = os.path.join(work, "img.png")
58png(IMG)
59IMGURL = uno.systemPathToFileUrl(IMG)
60
61
62def new(factory):
63    return desk.loadComponentFromURL(factory, "_blank", 0, (pv("Hidden", True),))
64
65
66def save(doc, name, filt):
67    try:
68        doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, name)), (pv("FilterName", filt),))
69        print("saved", name, filt)
70    except Exception as e:
71        failed.append(name)
72        print("FAIL save", name, filt, type(e).__name__, str(e)[:200])
73
74
75def setp(o, tag, quiet=False, **kw):
76    for k, v in kw.items():
77        try:
78            o.setPropertyValue(k, v)
79        except Exception as e:
80            if type(e).__name__.endswith("UnknownPropertyException"):
81                if not quiet and k not in NOPROP:
82                    NOPROP.add(k)
83                    print("NOPROP", tag, k)
84            elif not quiet:
85                failed.append(tag + "." + k)
86                print("FAIL set", tag, k, repr(v)[:60], type(e).__name__, str(e)[:100])
87
88
89def guard(tag, fn, *a, **kw):
90    try:
91        return fn(*a, **kw)
92    except Exception as e:
93        failed.append(tag)
94        print("FAIL", tag, type(e).__name__, str(e)[:200])
95
96
97def wanted(name):
98    return not only or name in only
99
100
101class Grid:
102    def __init__(self, cols=6, w=3000, h=2000, gap=500):
103        self.i, self.cols, self.w, self.h, self.gap = 0, cols, w, h, gap
104
105    def next(self):
106        c, r = self.i % self.cols, self.i // self.cols
107        self.i += 1
108        return (500 + c * (self.w + self.gap), 500 + r * (self.h + self.gap))
109
110
111def draw_tables(doc):
112    t = doc.createInstance("com.sun.star.drawing.DashTable")
113    d = st("com.sun.star.drawing.LineDash")
114    d.Style = E("com.sun.star.drawing.DashStyle", "ROUND")
115    d.Dots, d.DotLen, d.Dashes, d.DashLen, d.Distance = 2, 100, 1, 300, 150
116    t.insertByName("dash-a", d)
117    d.Style = E("com.sun.star.drawing.DashStyle", "RECT")
118    t.insertByName("dash-b", d)
119    t = doc.createInstance("com.sun.star.drawing.GradientTable")
120    for n, s in (("grad-lin", "LINEAR"), ("grad-ax", "AXIAL"), ("grad-rad", "RADIAL"), ("grad-ell", "ELLIPTICAL"),
121                 ("grad-sq", "SQUARE"), ("grad-rect", "RECT")):
122        g = st("com.sun.star.awt.Gradient")
123        g.Style = E("com.sun.star.awt.GradientStyle", s)
124        g.StartColor, g.EndColor, g.Angle, g.Border = 0xff0000, 0x0000ff, 300, 10
125        g.XOffset, g.YOffset, g.StartIntensity, g.EndIntensity, g.StepCount = 40, 60, 90, 80, 0
126        t.insertByName(n, g)
127    t = doc.createInstance("com.sun.star.drawing.TransparencyGradientTable")
128    g = st("com.sun.star.awt.Gradient")
129    g.Style = E("com.sun.star.awt.GradientStyle", "LINEAR")
130    g.StartColor, g.EndColor, g.Angle, g.Border = 0x000000, 0xcccccc, 0, 0
131    g.XOffset, g.YOffset, g.StartIntensity, g.EndIntensity = 50, 50, 100, 100
132    t.insertByName("trans-a", g)
133    t = doc.createInstance("com.sun.star.drawing.HatchTable")
134    for n, s in (("hatch-s", "SINGLE"), ("hatch-d", "DOUBLE"), ("hatch-t", "TRIPLE")):
135        h = st("com.sun.star.drawing.Hatch")
136        h.Style = E("com.sun.star.drawing.HatchStyle", s)
137        h.Color, h.Distance, h.Angle = 0x008000, 150, 450
138        t.insertByName(n, h)
139    t = doc.createInstance("com.sun.star.drawing.BitmapTable")
140    t.insertByName("bitmap-a", IMGURL)
141
142
143def mkstyle(doc, family, name, parent=None, service=None, **props):
144    fam = doc.StyleFamilies.getByName(family)
145    s = doc.createInstance(service) if service else fam.createInstance()
146    fam.insertByName(name, s)
147    s = fam.getByName(name)
148    if parent:
149        s.ParentStyle = parent
150    setp(s, "style " + name, quiet=True, **props)
151    return s
152
153
154STYLE_N = [0]
155
156
157class DrawBuilder:
158    def __init__(self, doc, page, grid=None):
159        self.doc, self.page, self.grid = doc, page, grid or Grid()
160
161    def shape(self, kind, tag, props, text=None, style=True, size=None, ns="drawing"):
162        STYLE_N[0] += 1
163        s = self.doc.createInstance("com.sun.star.%s.%s" % (ns, kind))
164        self.page.add(s)
165        x, y = self.grid.next()
166        s.Position = uno.createUnoStruct(PT, x, y)
167        s.Size = uno.createUnoStruct(SZ, *(size or (self.grid.w, self.grid.h)))
168        if text:
169            s.String = text
170        setp(s, tag, **props)
171        if style:
172            fam = "graphics"
173            guard("style " + tag, mkstyle, self.doc, fam, "gs-%s-%d" % (tag, STYLE_N[0]), None, **props)
174        return s
175
176
177def fillprops():
178    FS = "com.sun.star.drawing.FillStyle"
179    cases = []
180    cases.append(("fill-solid", dict(FillStyle=E(FS, "SOLID"), FillColor=0xffcc00, FillColor2=0x00ccff, FillTransparence=40)))
181    cases.append(("fill-none", dict(FillStyle=E(FS, "NONE"))))
182    for g in ("grad-lin", "grad-ax", "grad-rad", "grad-ell", "grad-sq", "grad-rect"):
183        cases.append((g, dict(FillStyle=E(FS, "GRADIENT"), FillGradientName=g, FillGradientStepCount=7)))
184    cases.append(("grad-trans", dict(FillStyle=E(FS, "GRADIENT"), FillGradientName="grad-lin",
185                                      FillTransparenceGradientName="trans-a")))
186    for h in ("hatch-s", "hatch-d", "hatch-t"):
187        for bg in (True, False):
188            cases.append((h + str(bg), dict(FillStyle=E(FS, "HATCH"), FillHatchName=h, FillBackground=bg, FillColor=0xffff99)))
189    BM = "com.sun.star.drawing.BitmapMode"
190    for m in ("REPEAT", "STRETCH", "NO_REPEAT"):
191        cases.append(("bmp-" + m, dict(FillStyle=E(FS, "BITMAP"), FillBitmapName="bitmap-a", FillBitmapMode=E(BM, m))))
192    for p in ("LEFT_TOP", "MIDDLE_TOP", "RIGHT_TOP", "LEFT_MIDDLE", "MIDDLE_MIDDLE", "RIGHT_MIDDLE", "LEFT_BOTTOM",
193              "MIDDLE_BOTTOM", "RIGHT_BOTTOM"):
194        cases.append(("bmp-ref-" + p, dict(FillStyle=E(FS, "BITMAP"), FillBitmapName="bitmap-a",
195                                            FillBitmapMode=E(BM, "REPEAT"), FillBitmapRectanglePoint=E("com.sun.star.drawing.RectanglePoint", p),
196                                            FillBitmapPositionOffsetX=25, FillBitmapPositionOffsetY=75,
197                                            FillBitmapSizeX=500, FillBitmapSizeY=700, FillBitmapLogicalSize=False)))
198    cases.append(("bmp-offx", dict(FillStyle=E(FS, "BITMAP"), FillBitmapName="bitmap-a", FillBitmapOffsetX=30,
199                                    FillBitmapLogicalSize=True, FillBitmapSizeX=40, FillBitmapSizeY=40)))
200    cases.append(("bmp-offy", dict(FillStyle=E(FS, "BITMAP"), FillBitmapName="bitmap-a", FillBitmapOffsetY=20)))
201    return cases
202
203
204def linecases():
205    LS, LJ, LC = "com.sun.star.drawing.LineStyle", "com.sun.star.drawing.LineJoint", "com.sun.star.drawing.LineCap"
206    cases = []
207    for j in ("NONE", "MITER", "ROUND", "BEVEL", "MIDDLE"):
208        cases.append(("join-" + j, dict(LineStyle=E(LS, "SOLID"), LineWidth=300, LineColor=0x336699, LineJoint=E(LJ, j))))
209    for c in ("BUTT", "ROUND", "SQUARE"):
210        cases.append(("cap-" + c, dict(LineStyle=E(LS, "SOLID"), LineWidth=300, LineCap=E(LC, c))))
211    cases.append(("line-none", dict(LineStyle=E(LS, "NONE"))))
212    cases.append(("line-dash-a", dict(LineStyle=E(LS, "DASH"), LineDashName="dash-a", LineTransparence=30)))
213    cases.append(("line-dash-b", dict(LineStyle=E(LS, "DASH"), LineDashName="dash-b")))
214    return cases
215
216
217def draw_gfx(kind, tag, doc, page, cases, text=None, **extra):
218    b = DrawBuilder(doc, page)
219    for n, p in cases:
220        guard("shape " + n, b.shape, kind, n, p, text, **extra)
221    return b
222
223
224def doc_draw_fill():
225    doc = new("private:factory/sdraw")
226    guard("tables", draw_tables, doc)
227    page = doc.DrawPages.getByIndex(0)
228    draw_gfx("RectangleShape", "fill", doc, page, fillprops())
229    draw_gfx("EllipseShape", "line", doc, page, linecases())
230    p2 = doc.DrawPages.insertNewByIndex(1)
231    b = DrawBuilder(doc, p2)
232    LS = "com.sun.star.drawing.LineStyle"
233    arrows = []
234    for sc, ec in ((True, False), (False, True), (True, True), (False, False)):
235        arrows.append(("arrow-%d%d" % (sc, ec), dict(LineStyle=E(LS, "SOLID"), LineWidth=200, LineStartName="Arrow",
236                                                       LineStartWidth=600, LineStartCenter=sc, LineEndName="Arrow", LineEndWidth=800,
237                                                       LineEndCenter=ec)))
238    for n, p in arrows:
239        guard("line " + n, b.shape, "LineShape", n, p)
240    shp = []
241    for tr in (0, 25, 75):
242        shp.append(("shadow%d" % tr, dict(Shadow=True, ShadowXDistance=200, ShadowYDistance=250, ShadowColor=0x808080,
243                                          ShadowTransparence=tr, FillColor=0xaaddff)))
244    shp.append(("noshadow", dict(Shadow=False)))
245    for n, p in shp:
246        guard("shadow " + n, b.shape, "RectangleShape", n, p)
247    save(doc, "draw-fill-line.odg", "draw8")
248    doc.close(True)
249
250
251def doc_draw_text():
252    doc = new("private:factory/sdraw")
253    page = doc.DrawPages.getByIndex(0)
254    D = "com.sun.star.drawing."
255    b = DrawBuilder(doc, page)
256    for a in ("LEFT", "CENTER", "RIGHT", "BLOCK"):
257        for v in ("TOP", "CENTER", "BOTTOM", "BLOCK"):
258            b.shape("RectangleShape", "tadj-%s-%s" % (a, v), dict(TextHorizontalAdjust=E(D + "TextHorizontalAdjust", a),
259                    TextVerticalAdjust=E(D + "TextVerticalAdjust", v)), text="adjust")
260    for ft in ("NONE", "PROPORTIONAL", "ALLLINES", "RESIZEATTR"):
261        b.shape("RectangleShape", "fit-" + ft, dict(TextFitToSize=E(D + "TextFitToSizeType", ft)), text="fit to size text")
262    for i, (gh, gw, cf, ww) in enumerate(((True, True, True, True), (False, False, False, False), (True, False, True, False))):
263        b.shape("RectangleShape", "grow%d" % i, dict(TextAutoGrowHeight=gh, TextAutoGrowWidth=gw, TextContourFrame=cf,
264                TextWordWrap=ww, TextMinimumFrameHeight=500, TextMinimumFrameWidth=600, TextMaximumFrameHeight=5000,
265                TextMaximumFrameWidth=6000, TextLeftDistance=100, TextRightDistance=120, TextUpperDistance=140,
266                TextLowerDistance=160), text="grow")
267    b.shape("TextShape", "plain", dict(TextAutoGrowHeight=True), text="text shape")
268    p2 = doc.DrawPages.insertNewByIndex(1)
269    b = DrawBuilder(doc, p2)
270    AK, AD = D + "TextAnimationKind", D + "TextAnimationDirection"
271    for k in ("NONE", "BLINK", "SCROLL", "ALTERNATE", "SLIDE"):
272        for d in ("LEFT", "RIGHT", "UP", "DOWN"):
273            b.shape("TextShape", "anim-%s-%s" % (k, d), dict(TextAnimationKind=E(AK, k), TextAnimationDirection=E(AD, d),
274                    TextAnimationStartInside=(d in ("LEFT", "UP")), TextAnimationStopInside=(d in ("RIGHT", "UP")),
275                    TextAnimationCount=3, TextAnimationDelay=250, TextAnimationAmount=5), text="animated")
276    b.shape("TextShape", "anim-defaults", dict(TextAnimationKind=E(AK, "SCROLL"), TextAnimationStartInside=False,
277            TextAnimationStopInside=False, TextAnimationAmount=0, TextAnimationCount=0), text="scroll")
278    save(doc, "draw-text.odg", "draw8")
279    doc.close(True)
280
281
282def doc_draw_objects():
283    doc = new("private:factory/sdraw")
284    page = doc.DrawPages.getByIndex(0)
285    D = "com.sun.star.drawing."
286    b = DrawBuilder(doc, page)
287    GM = D + "ColorMode"
288    for m in ("STANDARD", "GREYS", "MONO", "WATERMARK"):
289        b.shape("GraphicObjectShape", "gfx-" + m, dict(GraphicURL=IMGURL, GraphicColorMode=E(GM, m), AdjustLuminance=10,
290                AdjustContrast=-10, Gamma=1.5, AdjustRed=5, AdjustGreen=-5, AdjustBlue=15, Transparency=20))
291    b.shape("GraphicObjectShape", "gfx-crop", dict(GraphicURL=IMGURL, GraphicCrop=uno.createUnoStruct("com.sun.star.text.GraphicCrop", 100, 100, 100, 100)))
292    mp = doc.DrawPages.insertNewByIndex(1)
293    b = DrawBuilder(doc, mp)
294    HP, VP = D + "MeasureTextHorzPos", D + "MeasureTextVertPos"
295    i = 0
296    for h in ("AUTO", "LEFTOUTSIDE", "INSIDE", "RIGHTOUTSIDE"):
297        for v in ("AUTO", "EAST", "WEST", "CENTERED"):
298            u = (0, 1, 2, 3, 4, 6, 7, 8, 9, 10)[i % 10]
299            i += 1
300            sh = b.shape("MeasureShape", "meas-%s-%s" % (h, v), dict(MeasureTextHorizontalPosition=E(HP, h),
301                         MeasureTextVerticalPosition=E(VP, v), MeasureUnit=u, MeasureShowUnit=bool(i % 2),
302                         MeasureBelowReferenceEdge=bool(i % 3), MeasureTextRotate90=bool(i % 2), MeasureDecimalPlaces=i % 4,
303                         MeasureLineDistance=300, MeasureHelpLineOverhang=100, MeasureHelpLineDistance=120,
304                         MeasureHelpLine1Length=200, MeasureHelpLine2Length=250), size=(3000, 400))
305            if sh is not None:
306                setp(sh, "meas pos", StartPosition=uno.createUnoStruct(PT, 1000, 8000 + 500 * i),
307                     EndPosition=uno.createUnoStruct(PT, 6000, 8000 + 500 * i))
308    cp = doc.DrawPages.insertNewByIndex(2)
309    b = DrawBuilder(doc, cp)
310    for t in (0, 1, 2, 3):
311        for ed in (0, 1, 2):
312            sh = b.shape("CaptionShape", "cap-%d-%d" % (t, ed), dict(CaptionType=t, CaptionEscapeDirection=ed,
313                         CaptionIsFixedAngle=bool(ed % 2), CaptionAngle=45 * (t + 1), CaptionGap=100 + 50 * ed,
314                         CaptionLineLength=400, CaptionIsFitLineLength=bool(t % 2), CaptionIsEscapeRelative=bool(t % 2),
315                         CaptionEscapeRelative=500 * (t + 1), CaptionEscapeAbsolute=300), text="caption")
316            if sh is not None:
317                setp(sh, "cap pt", CaptionPoint=uno.createUnoStruct(PT, -1000, -1000))
318    ep = doc.DrawPages.insertNewByIndex(3)
319    b = DrawBuilder(doc, ep)
320    for k in ("STANDARD", "CURVE", "LINE", "LINES"):
321        s1 = b.shape("RectangleShape", "c1-" + k, {}, style=False, size=(1500, 1000))
322        s2 = b.shape("EllipseShape", "c2-" + k, {}, style=False, size=(1500, 1000))
323        c = b.shape("ConnectorShape", "conn-" + k, dict(EdgeKind=E(D + "ConnectorType", k), EdgeNode1HorzDist=100,
324                    EdgeNode1VertDist=110, EdgeNode2HorzDist=120, EdgeNode2VertDist=130, EdgeLine1Delta=50, EdgeLine2Delta=60,
325                    LineEndName="Arrow", LineEndWidth=400), size=(100, 100))
326        if c is not None and s1 is not None and s2 is not None:
327            setp(c, "conn", StartShape=s1, EndShape=s2)
328    save(doc, "draw-objects.odg", "draw8")
329    doc.close(True)
330
331
332def doc_draw_3d():
333    doc = new("private:factory/sdraw")
334    page = doc.DrawPages.getByIndex(0)
335    D = "com.sun.star.drawing."
336    scene = doc.createInstance(D + "Shape3DSceneObject")
337    page.add(scene)
338    scene.Position = uno.createUnoStruct(PT, 500, 500)
339    scene.Size = uno.createUnoStruct(SZ, 12000, 9000)
340    NK, TP, TK, TM = D + "NormalsKind", D + "TextureProjectionMode", D + "TextureKind", D + "TextureMode"
341    n = 0
342    for kind in ("Shape3DCubeObject", "Shape3DSphereObject"):
343        for nk in ("SPECIFIC", "FLAT", "SPHERE"):
344            for tp in ("OBJECTSPECIFIC", "PARALLEL", "SPHERE"):
345                o = guard("3d " + kind, doc.createInstance, D + kind)
346                if o is None:
347                    continue
348                guard("3d add", scene.add, o)
349                n += 1
350                setp(o, "3d %s %s %s" % (kind, nk, tp), D3DNormalsKind=E(NK, nk), D3DNormalsInvert=bool(n % 2),
351                     D3DTextureProjectionX=E(TP, tp), D3DTextureProjectionY=E(TP, tp), D3DTextureKind=E(TK, ("LUMINANCE", "COLOR")[n % 2]),
352                     D3DTextureMode=E(TM, ("REPLACE", "MODULATE", "BLEND")[n % 3]), D3DTextureFilter=bool(n % 2),
353                     D3DDoubleSided=bool(n % 2), D3DShadow3D=bool(n % 2), D3DMaterialColor=0xcc3300 + n,
354                     D3DMaterialEmission=0x101010, D3DMaterialSpecular=0xffffff, D3DMaterialSpecularIntensity=50,
355                     D3DHorizontalSegments=8, D3DVerticalSegments=6, D3DPercentDiagonal=10, D3DBackscale=80,
356                     D3DEndAngle=3000, D3DDepth=500, D3DCloseFront=bool(n % 2), D3DCloseBack=bool(n % 3))
357    setp(scene, "scene", D3DSceneAmbientColor=0x404040, D3DSceneTwoSidedLighting=True, D3DSceneShadowSlant=10,
358         D3DSceneShadeMode=E(D + "ShadeMode", "PHONG"))
359    for k, nm in (("Shape3DExtrudeObject", "ext"), ("Shape3DLatheObject", "lathe")):
360        o = guard("3d " + k, doc.createInstance, D + k)
361        if o is None:
362            continue
363        guard("3d add", scene.add, o)
364        pts = uno.createUnoStruct("com.sun.star.drawing.PolyPolygonShape3D")
365        pts.SequenceX = ((1000, 3000, 3000, 1000),)
366        pts.SequenceY = ((1000, 1000, 3000, 3000),)
367        pts.SequenceZ = ((0, 0, 0, 0),)
368        setp(o, "3d " + nm, D3DPolyPolygon3D=pts, D3DCloseFront=False, D3DCloseBack=False, D3DDepth=700,
369             D3DNormalsKind=E(NK, "FLAT"), D3DEndAngle=2000, D3DBackscale=70)
370    save(doc, "draw-3d.odg", "draw8")
371    doc.close(True)
372
373
374def doc_draw_frames():
375    doc = new("private:factory/sdraw")
376    page = doc.DrawPages.getByIndex(0)
377    D = "com.sun.star.drawing."
378    b = DrawBuilder(doc, page)
379    for i, (sc, br) in enumerate(((True, True), (False, False))):
380        b.shape("FrameShape", "frame%d" % i, dict(FrameURL="file:///nonexistent.html", FrameName="fr%d" % i,
381                FrameIsAutoScroll=sc, FrameIsBorder=br, FrameMarginWidth=12 + i, FrameMarginHeight=14 + i))
382    for i, kind in enumerate(("com.sun.star.drawing.OLE2Shape",)):
383        o = guard("ole", doc.createInstance, kind)
384        if o is not None:
385            page.add(o)
386            setp(o, "ole", CLSID="078B7ABA-54FC-457F-8551-6147e776a997")
387            o.Position = uno.createUnoStruct(PT, 500, 6000)
388            o.Size = uno.createUnoStruct(SZ, 4000, 2000)
389    forms = page.Forms
390    form = doc.createInstance("com.sun.star.form.component.Form")
391    forms.insertByName("Form1", form)
392    form = forms.getByName("Form1")
393    for i, kind in enumerate(("ScrollBar", "SpinButton", "CommandButton", "ComboBox")):
394        m = guard("ctl model", doc.createInstance, "com.sun.star.form.component." + kind)
395        cs = guard("control", doc.createInstance, D + "ControlShape")
396        if m is None or cs is None:
397            continue
398        form.insertByName("c%d" % i, m)
399        m = form.getByName("c%d" % i)
400        page.add(cs)
401        cs.Position = uno.createUnoStruct(PT, 500 + 4500 * i, 9000)
402        cs.Size = uno.createUnoStruct(SZ, 4000, 1500)
403        guard("ctl set", cs.setControl, m)
404        setp(cs, "ctl " + kind, ControlSymbolColor=0x0000ff + i, ControlBackground=0xeeeeee, ControlBorder=i % 3,
405             ControlBorderColor=0x00ff00)
406    save(doc, "draw-frames.odg", "draw8")
407    doc.close(True)
408
409
410def enum_names(name):
411    tdm = ctx.getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager")
412    return list(tdm.getByHierarchicalName(name).getEnumNames())
413
414
415def const(name):
416    return uno.getConstantByName(name)
417
418
419def background(doc, page, **props):
420    bg = doc.createInstance("com.sun.star.drawing.Background")
421    setp(bg, "background", **props)
422    guard("set background", setattr, page, "Background", bg)
423
424
425def bgcases():
426    return [c for c in fillprops() if not c[0].startswith("bmp-ref-") or c[0].endswith(("TOP", "BOTTOM"))]
427
428
429def doc_impress_slides():
430    doc = new("private:factory/simpress")
431    guard("tables", draw_tables, doc)
432    pages = doc.DrawPages
433    effects = enum_names("com.sun.star.presentation.FadeEffect")
434    spd = ("SLOW", "MEDIUM", "FAST")
435    for i, ef in enumerate(effects):
436        pg = pages.getByIndex(0) if i == 0 else pages.insertNewByIndex(i)
437        setp(pg, "slide " + ef, Effect=E("com.sun.star.presentation.FadeEffect", ef),
438             Speed=E("com.sun.star.presentation.AnimationSpeed", spd[i % 3]), Change=i % 3, Duration=1 + i % 5,
439             Visible=bool(i % 4), IsBackgroundVisible=bool(i % 3), IsBackgroundObjectsVisible=bool(i % 5),
440             IsHeaderVisible=bool(i % 2), IsFooterVisible=bool(i % 3), IsPageNumberVisible=bool(i % 4),
441             IsDateTimeVisible=bool(i % 5), HeaderText="hdr%d" % (i % 3), FooterText="ftr%d" % (i % 2),
442             DateTimeText="dt", IsDateTimeFixed=bool(i % 2), DateTimeFormat=i % 4)
443        setp(pg.NotesPage, "notes " + ef, IsHeaderVisible=bool(i % 2), IsFooterVisible=bool(i % 3),
444             IsPageNumberVisible=bool(i % 4), IsDateTimeVisible=bool(i % 5), HeaderText="nhdr%d" % (i % 3),
445             FooterText="nftr%d" % (i % 2), DateTimeText="ndt", IsDateTimeFixed=bool(i % 2), DateTimeFormat=i % 4)
446    save(doc, "impress-effects.odp", "impress8")
447    doc.close(True)
448
449
450def doc_impress_transitions():
451    doc = new("private:factory/simpress")
452    pages = doc.DrawPages
453    names = [n for n in dir(uno.getClass("com.sun.star.animations.TransitionType")) if n.isupper()] if False else None
454    types = {"BARWIPE": 1, "BOXWIPE": 2, "FOURBOXWIPE": 3, "BARNDOORWIPE": 4, "DIAGONALWIPE": 5, "BOWTIEWIPE": 6,
455             "VEEWIPE": 8, "ZIGZAGWIPE": 10, "TRIANGLEWIPE": 13, "ARROWHEADWIPE": 14, "PENTAGONWIPE": 15, "HEXAGONWIPE": 16,
456             "ELLIPSEWIPE": 17, "EYEWIPE": 18, "ROUNDRECTWIPE": 19, "STARWIPE": 20, "MISCSHAPEWIPE": 21, "CLOCKWIPE": 22,
457             "PINWHEELWIPE": 23, "SINGLESWEEPWIPE": 24, "FANWIPE": 25, "DOUBLEFANWIPE": 26, "DOUBLESWEEPWIPE": 27,
458             "SALOONDOORWIPE": 28, "WINDSHIELDWIPE": 29, "SNAKEWIPE": 30, "SPIRALWIPE": 31, "PARALLELSNAKESWIPE": 32,
459             "BOXSNAKESWIPE": 33, "WATERFALLWIPE": 34, "PUSHWIPE": 35, "SLIDEWIPE": 36, "FADE": 37, "RANDOMBARWIPE": 38,
460             "CHECKERBOARDWIPE": 39, "DISSOLVE": 40, "IRISWIPE": 41, "BLINDSWIPE": 42, "FOURBOXWIPE2": 43}
461    tc = {}
462    for n in types:
463        try:
464            tc[n] = const("com.sun.star.animations.TransitionType." + n)
465        except Exception:
466            pass
467    subs = []
468    for n in ("DEFAULT", "LEFTTORIGHT", "TOPTOBOTTOM", "TOPLEFT", "TOPRIGHT", "BOTTOMRIGHT", "BOTTOMLEFT", "TOPCENTER",
469              "RIGHTCENTER", "BOTTOMCENTER", "LEFTCENTER", "CORNERSIN", "CORNERSOUT", "VERTICAL", "HORIZONTAL", "FROMLEFT",
470              "FROMTOP", "FROMRIGHT", "FROMBOTTOM", "CROSSFADE", "FADETOCOLOR", "FADEFROMCOLOR", "FADEOVERCOLOR",
471              "THREEBLADE", "EIGHTBLADE", "ONEBLADE", "ACROSS", "TOPTOBOTTOMLEFT", "FOURBLADE", "TWOBOXTOP", "FOURBOXVERTICAL",
472              "CLOCKWISETOP", "COUNTERCLOCKWISETOP", "DIAGONALBOTTOMLEFT", "DIAGONALTOPLEFT", "RECTANGLE", "CIRCLE",
473              "DIAMOND", "HEART", "KEYHOLE", "HORIZONTALLEFT", "VERTICALTOP", "FANOUTVERTICAL", "FANINHORIZONTAL"):
474        try:
475            subs.append(const("com.sun.star.animations.TransitionSubType." + n))
476        except Exception:
477            pass
478    print("transition types", len(tc), "subtypes", len(subs))
479    i = 0
480    for n, t in tc.items():
481        pg = pages.getByIndex(0) if i == 0 else pages.insertNewByIndex(i)
482        setp(pg, "trans " + n, TransitionType=t, TransitionSubtype=subs[i % len(subs)], TransitionDirection=bool(i % 2),
483             TransitionFadeColor=0x102030 * (i % 8), Duration=2, Change=1 + i % 2, Speed=E("com.sun.star.presentation.AnimationSpeed", "FAST"))
484        i += 1
485    for sub in subs:
486        pg = pages.insertNewByIndex(i)
487        i += 1
488        setp(pg, "sub %s" % sub, TransitionType=tc.get("PUSHWIPE", 35), TransitionSubtype=sub, TransitionDirection=False)
489    save(doc, "impress-transitions.odp", "impress8")
490    doc.close(True)
491
492
493def doc_impress_backgrounds():
494    # after a Draw document in the same session getHandoutMasterPage is missing on a new Impress document: Impress first
495    doc = new("private:factory/simpress")
496    guard("tables", draw_tables, doc)
497    pages = doc.DrawPages
498    cases = bgcases()
499    for i, (n, p) in enumerate(cases):
500        pg = pages.getByIndex(0) if i == 0 else pages.insertNewByIndex(i)
501        background(doc, pg, **p)
502        setp(pg, "bgpage " + n, IsBackgroundVisible=bool(i % 7), IsBackgroundObjectsVisible=bool(i % 5))
503    masters = doc.MasterPages
504    mp = masters.getByIndex(0)
505    background(doc, mp, **dict(cases[1][1]))
506    m2 = masters.insertNewByIndex(1)
507    background(doc, m2, **dict(cases[8][1]))
508    for nm in ("BackgroundFullSize",):
509        setp(m2, "master " + nm, **{nm: True})
510        setp(mp, "master " + nm, **{nm: False})
511    hm = doc.getHandoutMasterPage()
512    setp(hm, "handout", HeaderText="handout header", FooterText="handout footer", DateTimeText="handout date",
513         IsDateTimeFixed=True, IsHeaderVisible=True, IsFooterVisible=True, IsDateTimeVisible=True, IsPageNumberVisible=True)
514    for pg in (mp, m2):
515        background(doc, pg, **dict(cases[4][1]))
516    save(doc, "impress-backgrounds.odp", "impress8")
517    doc.close(True)
518
519
520def doc_draw_backgrounds():
521    doc = new("private:factory/sdraw")
522    guard("tables", draw_tables, doc)
523    pages = doc.DrawPages
524    for i, (n, p) in enumerate(bgcases()):
525        pg = pages.getByIndex(0) if i == 0 else pages.insertNewByIndex(i)
526        background(doc, pg, **p)
527    save(doc, "draw-backgrounds.odg", "draw8")
528    doc.close(True)
529
530
531WT = "com.sun.star.text."
532
533
534def border(inner, outer, dist, color=0x3366cc):
535    b = st("com.sun.star.table.BorderLine")
536    b.Color, b.InnerLineWidth, b.OuterLineWidth, b.LineDistance = color, inner, outer, dist
537    return b
538
539
540def shadow(loc, width=150, color=0x808080, transparent=False):
541    sf = st("com.sun.star.table.ShadowFormat")
542    sf.Location = E("com.sun.star.table.ShadowLocation", loc)
543    sf.ShadowWidth, sf.Color, sf.IsTransparent = width, color, transparent
544    return sf
545
546
547def writer_doc(nparas=20):
548    doc = new("private:factory/swriter")
549    cur = doc.Text.createTextCursor()
550    for i in range(nparas):
551        doc.Text.insertString(cur, "Paragraph %d of the frame anchor test text, long enough to wrap." % i, False)
552        doc.Text.insertControlCharacter(cur, 0, False)
553    return doc
554
555
556def para_cursor(doc, i):
557    en = doc.Text.createEnumeration()
558    n = 0
559    while en.hasMoreElements():
560        p = en.nextElement()
561        if n == i:
562            return doc.Text.createTextCursorByRange(p.Start)
563        n += 1
564    return doc.Text.createTextCursor()
565
566
567class FrameBuilder:
568    def __init__(self, doc):
569        self.doc, self.n = doc, 0
570        self.styles = doc.StyleFamilies.getByName("FrameStyles")
571
572    def make(self, tag, kind, anchor, pre=None, post=None, para=0, text=None, size=(2500, 1200), style=True,
573             anchor_frame=None):
574        self.n += 1
575        STYLE_N[0] += 1
576        f = self.doc.createInstance(WT + kind)
577        f.AnchorType = E(WT + "TextContentAnchorType", "AT_PARAGRAPH" if anchor == "AT_FRAME" else anchor)
578        if kind == "TextFrame":
579            f.Width, f.Height = size
580        setp(f, tag + " pre", **(pre or {}))
581        cur = para_cursor(self.doc, para)
582        cur.goRight(5, False)
583        guard("insert " + tag, self.doc.Text.insertTextContent, cur, f, False)
584        if anchor_frame is not None:
585            setp(f, tag + " anchor", AnchorFrame=anchor_frame)
586        setp(f, tag, **(post or {}))
587        if text is not None:
588            guard("text " + tag, setattr, f.Text if kind == "TextFrame" else f, "String", text)
589        if style and kind == "TextFrame":
590            guard("fstyle " + tag, self.fstyle, "fs-%s-%d" % (tag, STYLE_N[0]),
591                  dict(pre or {}, AnchorType=E(WT + "TextContentAnchorType", anchor), **(post or {})))
592        return f
593
594    def fstyle(self, name, props):
595        s = self.doc.createInstance("com.sun.star.style.FrameStyle")
596        self.styles.insertByName(name, s)
597        s = self.styles.getByName(name)
598        setp(s, "style " + name, quiet=True, **props)
599
600
601def doc_writer_frames():
602    doc = writer_doc()
603    fb = FrameBuilder(doc)
604    RO = lambda n: n
605    for anchor in ("AT_PARAGRAPH", "AT_CHARACTER", "AT_PAGE", "AT_FRAME"):
606        base = None
607        if anchor == "AT_FRAME":
608            base = fb.make("base", "TextFrame", "AT_PARAGRAPH", para=19, text="base frame", size=(8000, 4000))
609        for i in range(30):
610            post = dict(HoriOrient=i % 6 if i % 6 != 6 else 0, HoriOrientRelation=(i * 7) % 10, PageToggle=bool((i // 6) % 2),
611                        VertOrient=i % 10, VertOrientRelation=(i * 3) % 10)
612            if i % 6 == 0 or anchor == "AT_PAGE":
613                post.update(HoriOrientPosition=500 + 20 * i, VertOrientPosition=300 + 20 * i)
614            if anchor == "AT_PAGE":
615                post["AnchorPageNo"] = 1 + i % 3
616            fb.make("%s-%d" % (anchor, i), "TextFrame", anchor, post=post, para=1 + i % 15, anchor_frame=base,
617                    text="f", style=(i < 12))
618    for i, anchor in enumerate(("AS_CHARACTER",) * 10):
619        fb.make("aschar-%d" % i, "TextFrame", anchor, post=dict(VertOrient=i, VertOrientRelation=0), para=3 + i % 5, text="c")
620    save(doc, "writer-frames-pos.odt", "writer8")
621    doc.close(True)
622
623
624def doc_writer_frames2():
625    doc = writer_doc()
626    fb = FrameBuilder(doc)
627    WM = "com.sun.star.text.WrapTextMode"
628    i = 0
629    for wrap in ("NONE", "THROUGHT", "PARALLEL", "DYNAMIC", "LEFT", "RIGHT"):
630        for contour, outside in ((False, False), (True, False), (True, True)):
631            i += 1
632            fb.make("wrap-%s-%d" % (wrap, i), "TextFrame", "AT_PARAGRAPH", para=i % 15,
633                    post=dict(TextWrap=E(WM, wrap), SurroundContour=contour, ContourOutside=outside,
634                              SurroundAnchorOnly=bool(i % 2), Opaque=bool(i % 3)), text="w")
635    for k in range(1, 4):
636        fb.make("infl-%d" % k, "TextFrame", "AT_CHARACTER", para=k, post=dict(WrapInfluenceOnPosition=k), text="i")
637    for k in range(5):
638        fb.make("wmode-%d" % k, "TextFrame", "AT_PARAGRAPH", para=4 + k, post=dict(WritingMode=k), text="m")
639    fb.make("flags", "TextFrame", "AT_PARAGRAPH", para=8, post=dict(Print=False, EditInReadonly=True, ContentProtected=True,
640            SizeProtected=True, PositionProtected=True, IsFollowingTextFlow=True), text="flags")
641    fb.make("flags2", "TextFrame", "AT_PARAGRAPH", para=9, post=dict(Print=True, EditInReadonly=False), text="flags2")
642    for k, (rw, rh, wt) in enumerate(((50, 20, 1), (100, 30, 1), (75, 0, 2), (40, 10, 0))):
643        fb.make("rel-%d" % k, "TextFrame", "AT_PARAGRAPH", para=10 + k,
644                post=dict(RelativeWidth=rw, RelativeHeight=rh, IsSyncWidthToHeight=bool(k % 2),
645                          IsSyncHeightToWidth=bool(k % 2), WidthType=wt, SizeType=wt), text="r")
646    for k, loc in enumerate(("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT", "NONE")):
647        fb.make("shadow-%s" % loc, "TextFrame", "AT_PARAGRAPH", para=k,
648                post=dict(ShadowFormat=shadow(loc, 100 + 20 * k, transparent=bool(k % 2)), LeftMargin=100 * k, RightMargin=100 * k,
649                          TopMargin=100 * k, BottomMargin=100 * k), text="s")
650    brd = (border(20, 30, 40), border(25, 45, 30), border(10, 10, 10), border(35, 15, 20))
651    fb.make("borders-all", "TextFrame", "AT_PARAGRAPH", para=5, text="b",
652            post=dict(LeftBorder=brd[0], RightBorder=brd[0], TopBorder=brd[0], BottomBorder=brd[0], LeftBorderDistance=100,
653                      RightBorderDistance=100, TopBorderDistance=100, BottomBorderDistance=100, LeftMargin=200, RightMargin=200,
654                      TopMargin=200, BottomMargin=200))
655    fb.make("borders-each", "TextFrame", "AT_PARAGRAPH", para=6, text="b",
656            post=dict(LeftBorder=brd[0], RightBorder=brd[1], TopBorder=brd[2], BottomBorder=brd[3], LeftBorderDistance=100,
657                      RightBorderDistance=110, TopBorderDistance=120, BottomBorderDistance=130, LeftMargin=100, RightMargin=200,
658                      TopMargin=300, BottomMargin=400))
659    FS = "com.sun.star.drawing.FillStyle"
660    fb.make("frame-fill", "TextFrame", "AT_PARAGRAPH", para=7, text="f",
661            post=dict(FillStyle=E(FS, "SOLID"), FillColor=0xccffcc, FillColor2=0xffcccc, FillTransparence=30))
662    fb.make("frame-back", "TextFrame", "AT_PARAGRAPH", para=7, text="f",
663            post=dict(BackColor=0xaabbcc, BackTransparent=False, BackColorTransparency=20))
664    save(doc, "writer-frames-misc.odt", "writer8")
665    doc.close(True)
666
667
668def doc_writer_objects():
669    doc = writer_doc()
670    fb = FrameBuilder(doc)
671    CM = "com.sun.star.drawing.ColorMode"
672    for i, m in enumerate(("STANDARD", "GREYS", "MONO", "WATERMARK")):
673        g = fb.make("gfx-" + m, "TextGraphicObject", "AT_PARAGRAPH", para=i, style=False, pre=dict(GraphicURL=IMGURL),
674                    post=dict(GraphicColorMode=E(CM, m), GraphicIsInverted=bool(i % 2), AdjustLuminance=10 * i,
675                              AdjustContrast=-5 * i, AdjustRed=i, AdjustGreen=-i, AdjustBlue=2 * i, Gamma=1.0 + i / 10.0,
676                              Transparency=10 * i, HoriMirroredOnEvenPages=bool(i % 2), HoriMirroredOnOddPages=bool(i % 3),
677                              VertMirrored=bool(i % 2), Width=2000, Height=1500))
678    for i in range(3):
679        fb.make("gfx-pos-%d" % i, "TextGraphicObject", ("AT_CHARACTER", "AS_CHARACTER", "AT_PAGE")[i], para=5 + i, style=False,
680                pre=dict(GraphicURL=IMGURL), post=dict(Width=1500, Height=1000, HoriOrient=i, VertOrient=i + 1))
681    S = "com.sun.star.drawing."
682    for i, anchor in enumerate(("AT_PARAGRAPH", "AT_CHARACTER", "AS_CHARACTER", "AT_PAGE")):
683        for j in range(8):
684            shp = doc.createInstance(S + "RectangleShape")
685            shp.AnchorType = E(WT + "TextContentAnchorType", anchor)
686            doc.DrawPage.add(shp)
687            shp.Size = uno.createUnoStruct(SZ, 1500, 1000)
688            shp.Position = uno.createUnoStruct(PT, 500 + 200 * j, 500 + 300 * i)
689            STYLE_N[0] += 1
690            post = dict(HoriOrient=j % 6, HoriOrientRelation=(j * 3) % 10, VertOrient=j % 10, VertOrientRelation=(j * 7) % 10,
691                        PageToggle=bool(j % 2), TextWrap=E("com.sun.star.text.WrapTextMode", ("NONE", "THROUGHT", "PARALLEL", "DYNAMIC", "LEFT", "RIGHT")[j % 6]),
692                        SurroundContour=bool(j % 2), ContourOutside=bool(j % 3), SurroundAnchorOnly=bool(j % 2), Opaque=bool(j % 2),
693                        WrapInfluenceOnPosition=1 + j % 3, IsFollowingTextFlow=bool(j % 2), LeftMargin=100, RightMargin=100,
694                        TopMargin=100, BottomMargin=100)
695            if anchor == "AS_CHARACTER":
696                post.pop("HoriOrient"); post.pop("HoriOrientRelation")
697            setp(shp, "wshape %s %d" % (anchor, j), **post)
698    emb = guard("ole", doc.createInstance, WT + "TextEmbeddedObject")
699    for clsid in ("078B7ABA-54FC-457F-8551-6147e776a997", "47BBB4CB-CE4C-4E80-A591-42D9AE74950F"):
700        emb = guard("ole", doc.createInstance, WT + "TextEmbeddedObject")
701        if emb is None:
702            continue
703        setp(emb, "ole", CLSID=clsid, AnchorType=E(WT + "TextContentAnchorType", "AT_PARAGRAPH"))
704        guard("ole insert", doc.Text.insertTextContent, para_cursor(doc, 12), emb, False)
705        setp(emb, "ole post", Width=3000, Height=2000)
706    save(doc, "writer-objects.odt", "writer8")
707    doc.close(True)
708
709
710def pagestyle(doc, name, props, service="com.sun.star.style.PageStyle"):
711    fam = doc.StyleFamilies.getByName("PageStyles")
712    s = doc.createInstance(service)
713    fam.insertByName(name, s)
714    s = fam.getByName(name)
715    setp(s, "pagestyle " + name, **props)
716    return s
717
718
719def hf_props(pre, i):
720    b = (border(20, 30, 40), border(10, 25, 15), border(35, 15, 20), border(5, 20, 10))
721    d = dict()
722    d[pre + "IsOn"] = True
723    d[pre + "IsShared"] = bool(i % 2)
724    d[pre + "IsDynamicHeight"] = bool(i % 2)
725    d[pre + "Height"] = 800 + 50 * i
726    d[pre + "BodyDistance"] = 100 + 10 * i
727    d[pre + "LeftMargin"] = 100 + 10 * i
728    d[pre + "RightMargin"] = 100 + 10 * i
729    d[pre + "DynamicSpacing"] = bool(i % 2)
730    if i % 3 == 0:
731        d[pre + "LeftBorder"] = d[pre + "RightBorder"] = d[pre + "TopBorder"] = d[pre + "BottomBorder"] = b[0]
732        d[pre + "LeftBorderDistance"] = d[pre + "RightBorderDistance"] = d[pre + "TopBorderDistance"] = d[pre + "BottomBorderDistance"] = 120
733    else:
734        d[pre + "LeftBorder"], d[pre + "RightBorder"], d[pre + "TopBorder"], d[pre + "BottomBorder"] = b
735        d[pre + "LeftBorderDistance"], d[pre + "RightBorderDistance"], d[pre + "TopBorderDistance"], d[pre + "BottomBorderDistance"] = 100, 110, 120, 130
736    d[pre + "ShadowFormat"] = shadow(("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT", "NONE")[i % 5])
737    d[pre + "BackColor"] = 0xeeeeee
738    d[pre + "BackTransparent"] = bool(i % 2)
739    return d
740
741
742def page_common(i):
743    b = (border(20, 30, 40), border(10, 25, 15), border(35, 15, 20), border(5, 20, 10))
744    d = dict(ShadowFormat=shadow(("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT", "NONE")[i % 5]))
745    if i % 2:
746        d.update(LeftBorder=b[0], RightBorder=b[1], TopBorder=b[2], BottomBorder=b[3], LeftBorderDistance=100,
747                 RightBorderDistance=110, TopBorderDistance=120, BottomBorderDistance=130)
748    else:
749        d.update(LeftBorder=b[0], RightBorder=b[0], TopBorder=b[0], BottomBorder=b[0], LeftBorderDistance=100,
750                 RightBorderDistance=100, TopBorderDistance=100, BottomBorderDistance=100)
751    d.update(LeftMargin=1500, RightMargin=1500, TopMargin=1500, BottomMargin=1500)
752    return d
753
754
755def doc_writer_pages():
756    doc = new("private:factory/swriter")
757    doc.Text.insertString(doc.Text.createTextCursor(), "page style test", False)
758    guard("tables", draw_tables, doc)
759    n = 0
760    for wm in range(5):
761        n += 1
762        pagestyle(doc, "ps-wm-%d" % wm, dict(WritingMode=wm))
763    for lay in ("ALL", "LEFT", "RIGHT", "MIRRORED"):
764        pagestyle(doc, "ps-layout-" + lay, dict(PageStyleLayout=E("com.sun.star.style.PageStyleLayout", lay)))
765    for nt in (0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 20, 30, 40):
766        pagestyle(doc, "ps-num-%d" % nt, dict(NumberingType=nt))
767    pagestyle(doc, "ps-tray", dict(RegisterModeActive=True, RegisterParagraphStyle="Text body",
768              FirstPageNumber=0, IsLandscape=True))
769    for gm in (0, 1, 2):
770        for std in (True, False):
771            pagestyle(doc, "ps-grid-%s-%d" % (gm, std), dict(GridMode=gm, GridDisplay=bool(std), GridPrint=not std,
772                      GridBaseHeight=500, GridBaseWidth=400, GridRubyHeight=200, GridLines=20, GridColor=0x00ff00,
773                      RubyBelow=not std, StandardPageMode=std, GridSnapToChars=bool(std)))
774    for i in range(6):
775        d = page_common(i)
776        d.update(hf_props("Header", i))
777        d.update(hf_props("Footer", i + 1))
778        pagestyle(doc, "ps-hf-%d" % i, d)
779    for i, adj in enumerate((0, 1, 2)):
780        pagestyle(doc, "ps-ftn-%d" % i, dict(FootnoteLineAdjust=adj, FootnoteLineWeight=20 + 10 * i, FootnoteLineColor=0xff0000,
781                  FootnoteLineRelativeWidth=50 + i, FootnoteLineDistance=100, FootnoteLineTextDistance=50, FootnoteHeight=2000))
782    nfam = doc.StyleFamilies.getByName("NumberingStyles")
783    for lf in (0, 1, 2):
784        ns = doc.createInstance("com.sun.star.style.NumberingStyle")
785        nfam.insertByName("ns-lf-%d" % lf, ns)
786        ns = nfam.getByName("ns-lf-%d" % lf)
787        rule = ns.NumberingRules
788        lvl = [pv(p.Name, lf if p.Name == "LabelFollowedBy" else p.Value) for p in rule.getByIndex(0)]
789        guard("numbering", uno.invoke, rule, "replaceByIndex", (0, uno.Any("[]com.sun.star.beans.PropertyValue", tuple(lvl))))
790        guard("numbering set", setattr, ns, "NumberingRules", rule)
791        doc.Text.insertString(doc.Text.createTextCursor(), "list %d" % lf, False)
792    pagestyle(doc, "ps-hdr-off", dict(HeaderIsOn=False, FooterIsOn=False))
793    pagestyle(doc, "ps-hdr-on", dict(HeaderIsOn=True, FooterIsOn=True, HeaderIsShared=True, FooterIsShared=True))
794    pagestyle(doc, "ps-hdr-left", dict(HeaderIsOn=True, FooterIsOn=True, HeaderIsShared=False, FooterIsShared=False))
795    for k, (hi, fi) in enumerate(((True, False), (False, True))):
796        pagestyle(doc, "ps-hdr-ft-%d" % k, dict(HeaderIsOn=hi, FooterIsOn=fi, HeaderIsShared=bool(k), FooterIsShared=not k))
797    FS = "com.sun.star.drawing.FillStyle"
798    for i, (nm, p) in enumerate(fillprops()[:14]):
799        pagestyle(doc, "ps-fill-%d" % i, dict(p, **{("Header" + k[0:]): v for k, v in p.items()}, HeaderIsOn=True))
800    save(doc, "writer-pagestyles.odt", "writer8")
801    doc.close(True)
802
803
804def doc_writer_tables():
805    doc = new("private:factory/swriter")
806    guard("bits", draw_tables, doc)
807    cur = doc.Text.createTextCursor()
808    cur.gotoEnd(False)
809    BT = "com.sun.star.style.BreakType"
810    cases = []
811    for bt in ("NONE", "COLUMN_BEFORE", "COLUMN_AFTER", "COLUMN_BOTH", "PAGE_BEFORE", "PAGE_AFTER", "PAGE_BOTH"):
812        cases.append(("brk-" + bt, dict(BreakType=E(BT, bt))))
813    for k in (True, False):
814        cases.append(("keep%d" % k, dict(KeepTogether=k, Split=k)))
815    for ho in range(0, 6):
816        cases.append(("hori%d" % ho, dict(HoriOrient=ho, LeftMargin=100, RightMargin=200)))
817    cases.append(("rel", dict(RelativeWidth=60)))
818    cases.append(("abs", dict(Width=8000, IsWidthRelative=False)))
819    cases.append(("margins", dict(LeftMargin=300, RightMargin=300, TopMargin=300, BottomMargin=300, BackColor=0xffffcc, BackTransparent=False)))
820    for loc in ("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT", "NONE"):
821        cases.append(("shadow-" + loc, dict(ShadowFormat=shadow(loc))))
822    for wm in range(5):
823        cases.append(("wm%d" % wm, dict(WritingMode=wm)))
824    cases.append(("collapse", dict(CollapsingBorders=True)))
825    cases.append(("collapse0", dict(CollapsingBorders=False)))
826    cases.append(("pagedesc", dict(PageDescName="Standard", PageNumberOffset=3)))
827    for n, props in cases:
828        doc.Text.insertString(cur, "table " + n, False)
829        doc.Text.insertControlCharacter(cur, 0, False)
830        t = doc.createInstance(WT + "TextTable")
831        t.initialize(3, 3)
832        guard("ins " + n, doc.Text.insertTextContent, cur, t, False)
833        setp(t, "table " + n, **props)
834        for r in range(3):
835            row = t.Rows.getByIndex(r)
836            setp(row, "row %s %d" % (n, r), BackColor=0xddeeff if r == 1 else 0xffffff, BackTransparent=(r != 1),
837                 Height=700 + 100 * r, IsAutoHeight=bool(r % 2), IsSplitAllowed=bool(r % 2))
838        for ci, cn in enumerate(("A1", "B1", "C2", "B3")):
839            c = t.getCellByName(cn)
840            c.String = cn
841            setp(c, "cell " + n + cn, BackColor=0xffeeee, VertOrient=ci, LeftBorder=border(20, 30, 40), RightBorder=border(10, 25, 15),
842                 TopBorder=border(35, 15, 20), BottomBorder=border(5, 20, 10), LeftBorderDistance=100, RightBorderDistance=110,
843                 TopBorderDistance=120, BottomBorderDistance=130, WritingMode=ci, ShadowFormat=shadow("BOTTOM_RIGHT"))
844        doc.Text.insertControlCharacter(cur, 0, False)
845    cols = t.TableColumnSeparators
846    save(doc, "writer-tables.odt", "writer8")
847    doc.close(True)
848
849
850def calc_style(doc, family, name, props):
851    fam = doc.StyleFamilies.getByName(family)
852    s = doc.createInstance("com.sun.star.style.%s" % ("CellStyle" if family == "CellStyles" else "PageStyle"))
853    fam.insertByName(name, s)
854    s = fam.getByName(name)
855    setp(s, family + " " + name, **props)
856    return s
857
858
859def doc_calc_cells():
860    doc = new("private:factory/scalc")
861    sh = doc.Sheets.getByIndex(0)
862    CJ = "com.sun.star.table.CellHoriJustify"
863    CV = "com.sun.star.table.CellVertJustify"
864    cases = []
865    for hj in ("STANDARD", "LEFT", "CENTER", "RIGHT", "BLOCK", "REPEAT"):
866        cases.append(("hj-" + hj, dict(HoriJustify=E(CJ, hj), IsTextWrapped=bool(hj == "BLOCK"))))
867    for rr in ("STANDARD", "TOP", "CENTER", "BOTTOM"):
868        cases.append(("rot-" + rr, dict(RotateReference=E(CV, rr), RotateAngle=4500, VertJustify=1 if rr == "TOP" else 2)))
869    for v in ("STANDARD", "TOP", "CENTER", "BOTTOM"):
870        cases.append(("vj-" + v, dict(VertJustify=("STANDARD", "TOP", "CENTER", "BOTTOM").index(v))))
871    cases.append(("shrink", dict(ShrinkToFit=True)))
872    cases.append(("noshrink", dict(ShrinkToFit=False)))
873    cases.append(("vertical", dict(AsianVerticalMode=True)))
874    cases.append(("vertical0", dict(AsianVerticalMode=False)))
875    for loc in ("TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT", "NONE"):
876        cases.append(("shadow-" + loc, dict(ShadowFormat=shadow(loc))))
877    cp = st("com.sun.star.util.CellProtection")
878    cp.IsLocked, cp.IsFormulaHidden, cp.IsHidden, cp.IsPrintHidden = False, True, True, True
879    cases.append(("prot-print", dict(CellProtection=cp)))
880    cp2 = st("com.sun.star.util.CellProtection")
881    cp2.IsLocked, cp2.IsFormulaHidden, cp2.IsHidden, cp2.IsPrintHidden = True, False, False, False
882    cases.append(("prot-lock", dict(CellProtection=cp2)))
883    cases.append(("diag", dict(DiagonalTLBR=border(20, 30, 40), DiagonalBLTR=border(10, 25, 15))))
884    cases.append(("diag2", dict(DiagonalTLBR=border(0, 20, 0), DiagonalBLTR=border(35, 15, 20))))
885    cases.append(("borders", dict(LeftBorder=border(20, 30, 40), RightBorder=border(10, 25, 15), TopBorder=border(35, 15, 20),
886                                  BottomBorder=border(5, 20, 10), ParaLeftMargin=100, ParaRightMargin=110, ParaTopMargin=120,
887                                  ParaBottomMargin=130)))
888    cases.append(("borders-all", dict(LeftBorder=border(20, 30, 40), RightBorder=border(20, 30, 40), TopBorder=border(20, 30, 40),
889                                      BottomBorder=border(20, 30, 40), ParaLeftMargin=100, ParaRightMargin=100, ParaTopMargin=100,
890                                      ParaBottomMargin=100)))
891    for wm in range(5):
892        cases.append(("wm%d" % wm, dict(WritingMode=wm)))
893    cases.append(("bg", dict(CellBackColor=0xffeecc, IsCellBackgroundTransparent=False, ParaIndent=200, NumberFormat=2,
894                             StandardDecimals=3)))
895    for i, (n, props) in enumerate(cases):
896        guard("cellstyle " + n, calc_style, doc, "CellStyles", "cs-" + n, props)
897        c = sh.getCellByPosition(i % 8, i // 8)
898        c.String = n
899        setp(c, "cell " + n, **props)
900        guard("apply " + n, setattr, c, "CellStyle", "cs-" + n)
901    save(doc, "calc-cells.ods", "calc8")
902    doc.close(True)
903
904
905def doc_calc_sheets():
906    doc = new("private:factory/scalc")
907    sheets = doc.Sheets
908    for i in range(1, 9):
909        sheets.insertNewByName("s%d" % i, i)
910    for i in range(sheets.Count):
911        sh = sheets.getByIndex(i)
912        sh.getCellByPosition(0, 0).String = "sheet %d" % i
913        setp(sh, "sheet %d" % i, TableLayout=i % 6, IsVisible=bool(i % 3), TabColor=0xff0000 + i)
914        cols, rows = sh.Columns, sh.Rows
915        for j in range(4):
916            cs = cols.getByIndex(j)
917            setp(cs, "col %d %d" % (i, j), Width=2000 + 300 * j, OptimalWidth=bool((i + j) % 2), IsVisible=bool((i + j) % 4),
918                 IsManualPageBreak=bool((i + j) % 2), IsStartOfNewPage=bool(j % 2))
919            rw = rows.getByIndex(j)
920            setp(rw, "row %d %d" % (i, j), Height=500 + 100 * j, OptimalHeight=bool((i + j) % 2), IsVisible=bool((i + j) % 4),
921                 IsManualPageBreak=bool((i + j) % 2), IsStartOfNewPage=bool(j % 2), CellBackColor=0xccffcc, IsCellBackgroundTransparent=bool(j % 2))
922    save(doc, "calc-sheets.ods", "calc8")
923    doc.close(True)
924
925
926def doc_calc_pages():
927    doc = new("private:factory/scalc")
928    sh = doc.Sheets.getByIndex(0)
929    sh.getCellByPosition(0, 0).String = "pages"
930    guard("tables", draw_tables, doc)
931    n = 0
932    for pdf in (True, False):
933        for ch, cv in ((True, False), (False, True), (True, True), (False, False)):
934            n += 1
935            calc_style(doc, "PageStyles", "pg-%d" % n, dict(PrintDownFirst=pdf, CenterHorizontally=ch, CenterVertically=cv,
936                       ScaleToPagesX=n, ScaleToPagesY=n + 1, PrintAnnotations=bool(n % 2), PrintCharts=bool(n % 3), PrintDrawing=bool(n % 2),
937                       PrintFormulas=bool(n % 2), PrintGrid=bool(n % 3), PrintHeaders=bool(n % 2), PrintObjects=bool(n % 3),
938                       PrintZeroValues=bool(n % 2), IsLandscape=bool(n % 2)))
939    for k in (1, 2, 5):
940        calc_style(doc, "PageStyles", "pg-scale-pages-%d" % k, dict(ScaleToPages=k))
941        calc_style(doc, "PageStyles", "pg-scale-%d" % k, dict(PageScale=50 + 10 * k))
942    for lay in ("ALL", "LEFT", "RIGHT", "MIRRORED"):
943        calc_style(doc, "PageStyles", "pg-layout-" + lay, dict(PageStyleLayout=E("com.sun.star.style.PageStyleLayout", lay)))
944    for nt in (0, 1, 2, 3, 4, 6, 7):
945        calc_style(doc, "PageStyles", "pg-num-%d" % nt, dict(NumberingType=nt))
946    for wm in range(5):
947        calc_style(doc, "PageStyles", "pg-wm-%d" % wm, dict(WritingMode=wm))
948    for i in range(6):
949        d = page_common(i)
950        d.update(hf_props("Header", i))
951        d.update(hf_props("Footer", i + 1))
952        calc_style(doc, "PageStyles", "pg-hf-%d" % i, d)
953    for i in range(3):
954        calc_style(doc, "PageStyles", "pg-back-%d" % i, dict(BackColor=0xffeecc, BackTransparent=bool(i % 2), HeaderIsOn=True,
955                   HeaderBackColor=0xccddee, HeaderBackTransparent=bool(i % 2)))
956    calc_style(doc, "PageStyles", "pg-hdr-off", dict(HeaderIsOn=False, FooterIsOn=False))
957    for k, (hi, fi, hs, fs_) in enumerate(((True, True, True, True), (True, True, False, False), (False, True, True, False))):
958        calc_style(doc, "PageStyles", "pg-hf-onoff-%d" % k, dict(HeaderIsOn=hi, FooterIsOn=fi, HeaderIsShared=hs, FooterIsShared=fs_))
959    save(doc, "calc-pagestyles.ods", "calc8")
960    doc.close(True)
961
962
963def fill_table(doc, page):
964    t = doc.createInstance("com.sun.star.drawing.TableShape")
965    page.add(t)
966    t.Position = uno.createUnoStruct(PT, 1000, 1000)
967    t.Size = uno.createUnoStruct(SZ, 12000, 6000)
968    m = t.Model
969    m.Columns.insertByIndex(1, 3)
970    m.Rows.insertByIndex(1, 2)
971    for i in range(m.Columns.Count):
972        setp(m.Columns.getByIndex(i), "col %d" % i, Width=2000 + 500 * i, OptimalWidth=bool(i % 2), IsVisible=bool(i % 3),
973             IsStartOfNewPage=bool(i % 2))
974    for i in range(m.Rows.Count):
975        setp(m.Rows.getByIndex(i), "row %d" % i, Height=800 + 100 * i, OptimalHeight=bool(i % 2), IsVisible=bool(i % 3),
976             IsStartOfNewPage=bool(i % 2))
977    FS = "com.sun.star.drawing.FillStyle"
978    for r in range(m.Rows.Count):
979        for c in range(m.Columns.Count):
980            cell = m.getCellByPosition(c, r)
981            cell.String = "c%d%d" % (c, r)
982            setp(cell, "cell", FillStyle=E(FS, "SOLID"), FillColor=0xffcc00 + 17 * (r + c),
983                 TextVerticalAdjust=E("com.sun.star.drawing.TextVerticalAdjust", ("TOP", "CENTER", "BOTTOM", "BLOCK")[(r + c) % 4]),
984                 TextHorizontalAdjust=E("com.sun.star.drawing.TextHorizontalAdjust", ("LEFT", "CENTER", "RIGHT", "BLOCK")[(r + c) % 4]),
985                 LeftBorder=border(20, 30, 40), RightBorder=border(10, 25, 15), TopBorder=border(35, 15, 20),
986                 BottomBorder=border(5, 20, 10), TextLeftDistance=100, TextRightDistance=120, TextUpperDistance=140,
987                 TextLowerDistance=160, ParaAdjust=(r + c) % 4)
988
989
990def doc_impress_tables():
991    doc = new("private:factory/simpress")
992    guard("tables", draw_tables, doc)
993    # releasing a table cell proxy after the document is closed crashes the office
994    fill_table(doc, doc.DrawPages.getByIndex(0))
995    gc.collect()
996    save(doc, "impress-table.odp", "impress8")
997    doc.close(True)
998
999
1000DOCS = [("impress-backgrounds", doc_impress_backgrounds), ("impress-effects", doc_impress_slides),
1001        ("impress-table", doc_impress_tables),
1002        ("impress-transitions", doc_impress_transitions), ("draw-fill", doc_draw_fill), ("draw-text", doc_draw_text),
1003        ("draw-objects", doc_draw_objects), ("draw-3d", doc_draw_3d), ("draw-frames", doc_draw_frames),
1004        ("draw-backgrounds", doc_draw_backgrounds), ("writer-frames-pos", doc_writer_frames),
1005        ("writer-frames-misc", doc_writer_frames2), ("writer-objects", doc_writer_objects),
1006        ("writer-pagestyles", doc_writer_pages), ("writer-tables", doc_writer_tables), ("calc-cells", doc_calc_cells),
1007        ("calc-sheets", doc_calc_sheets), ("calc-pagestyles", doc_calc_pages)]
1008for name, fn in DOCS:
1009    if wanted(name):
1010        guard(name, fn)
1011shutil.rmtree(work, ignore_errors=True)
1012sys.exit(1 if failed else 0)
1013