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-text/make.py <port> <outdir> [section ...] 22# Character, paragraph, list, section, ruby and number-format properties set to each enumerated value, in styles and as direct formatting. Saves with the office's configured ODF version: run it against the strict and extended profiles. 23import sys, os, traceback, uno 24from unohelp import connect, desktop, pv 25 26port, out = int(sys.argv[1]), os.path.abspath(sys.argv[2]) 27only = sys.argv[3:] 28os.makedirs(out, exist_ok=True) 29desk = desktop(connect(port)) 30failed = [] 31SECTIONS = [] 32 33 34def section(fn): 35 SECTIONS.append(fn) 36 return fn 37 38 39def new(factory): 40 return desk.loadComponentFromURL(factory, "_blank", 0, (pv("Hidden", True),)) 41 42 43def save(doc, name, filt): 44 try: 45 doc.storeToURL(uno.systemPathToFileUrl(os.path.join(out, name)), (pv("FilterName", filt),)) 46 print("saved", name, filt) 47 except Exception as e: 48 failed.append(name) 49 print("FAIL", name, filt, type(e).__name__, repr(e)[:200], getattr(e, "Message", "")) 50 51 52def setp(obj, name, value, tag=""): 53 try: 54 if isinstance(value, uno.Any): 55 uno.invoke(obj, "setPropertyValue", (name, value)) 56 else: 57 obj.setPropertyValue(name, value) 58 return True 59 except Exception as e: 60 print("WARN", tag, name, repr(value)[:60], type(e).__name__, str(e)[:80].replace("\n", " ")) 61 return False 62 63 64def setall(obj, props, tag=""): 65 for k, v in props.items(): 66 setp(obj, k, v, tag) 67 68 69def const(name): 70 return uno.getConstantByName("com.sun.star.%s" % name) 71 72 73def enum(t, v): 74 return uno.Enum("com.sun.star.%s" % t, v) 75 76 77def consts(prefix, names): 78 return [const("%s.%s" % (prefix, n)) for n in names] 79 80 81def run(name, fn): 82 if only and name not in only: 83 return 84 try: 85 fn() 86 except Exception as e: 87 failed.append(name) 88 print("FAIL", name, type(e).__name__, repr(e)[:300], traceback.format_exc().splitlines()[-4:-1]) 89 90 91def norm(v): 92 if isinstance(v, uno.Enum): 93 return (v.typeName, v.value) 94 if isinstance(v, float): 95 return round(v, 3) 96 if isinstance(v, (tuple, list)): 97 return tuple(norm(x) for x in v) 98 if type(v).__name__ == "pyuno": 99 return repr(v) 100 return v 101 102 103def reload(name): 104 return desk.loadComponentFromURL(uno.systemPathToFileUrl(os.path.join(out, name)), "_blank", 0, (pv("Hidden", True), pv("ReadOnly", True), pv("MacroExecutionMode", 0))) 105 106 107def readback(name, family, specs): 108 try: 109 doc = reload(name) 110 fam = doc.StyleFamilies.getByName(family) 111 bad = tot = 0 112 for sname, props in specs: 113 try: 114 st = fam.getByName(sname) 115 except Exception: 116 print("RT-MISSING", name, sname) 117 continue 118 for k, v in props.items(): 119 if k.startswith("__"): 120 continue 121 tot += 1 122 try: 123 got = st.getPropertyValue(k) 124 except Exception as e: 125 print("RT-NOPROP", name, sname, k) 126 bad += 1 127 continue 128 if norm(got) != norm(v): 129 bad += 1 130 print("RT-DIFF", name, sname, k, "set", norm(v), "got", norm(got)) 131 print("RT-SUMMARY", name, family, "values", tot, "differing", bad) 132 doc.close(True) 133 except Exception as e: 134 print("RT-FAIL", name, type(e).__name__, str(e)[:100]) 135 136 137class Writer: 138 def __init__(self): 139 self.doc = new("private:factory/swriter") 140 self.items = [] 141 self.n = 0 142 self.specs = {"CharacterStyles": [], "ParagraphStyles": []} 143 144 def style(self, family, props, parent=None, tag=""): 145 self.n += 1 146 name = "%s%d" % (tag or family[:1], self.n) 147 s = self.doc.createInstance("com.sun.star.style.%s" % ("CharacterStyle" if family == "CharacterStyles" else "ParagraphStyle")) 148 self.doc.StyleFamilies.getByName(family).insertByName(name, s) 149 if parent: 150 s.ParentStyle = parent 151 setall(s, props, name) 152 self.specs[family].append((name, props)) 153 return name 154 155 def para(self, text, pstyle=None, cstyle=None, props=None): 156 self.items.append((text, pstyle, cstyle, props)) 157 158 def char_style(self, label, props): 159 self.para(label, cstyle=self.style("CharacterStyles", props, tag="C")) 160 161 def par_style(self, label, props, parent=None): 162 self.para(label, pstyle=self.style("ParagraphStyles", props, parent, tag="P")) 163 164 def flush(self): 165 t = self.doc.Text 166 c = t.createTextCursor() 167 for k, i in enumerate(self.items): 168 if k: 169 t.insertControlCharacter(c, const("text.ControlCharacter.PARAGRAPH_BREAK"), False) 170 t.insertString(c, i[0], False) 171 en = t.createEnumeration() 172 for (label, ps, cs, props) in self.items: 173 p = en.nextElement() 174 if ps: 175 p.ParaStyleName = ps 176 if cs: 177 p.CharStyleName = cs 178 if props: 179 setall(p, props, label) 180 return self.doc 181 182 183def W(): 184 return Writer() 185 186 187WEIGHTS = [0, 10, 50, 60, 75, 90, 100, 110, 150, 175, 200, 250] 188SLANTS = ["NONE", "OBLIQUE", "ITALIC", "DONTKNOW", "REVERSE_OBLIQUE", "REVERSE_ITALIC"] 189FAMILIES = ["DONTKNOW", "DECORATIVE", "MODERN", "ROMAN", "SCRIPT", "SWISS", "SYSTEM"] 190PITCHES = ["DONTKNOW", "FIXED", "VARIABLE"] 191CHARSETS = ["DONTKNOW", "ANSI", "MAC", "IBMPC_437", "IBMPC_850", "IBMPC_860", "IBMPC_861", "IBMPC_863", "IBMPC_865", "SYSTEM", "SYMBOL"] 192UNDERLINES = list(range(19)) 193STRIKES = list(range(7)) 194 195 196@section 197def writer_char(): 198 def build(): 199 w = W() 200 for suf in ("", "Asian", "Complex"): 201 for v in WEIGHTS: 202 w.char_style("weight%s %s" % (suf, v), {"CharWeight" + suf: float(v)}) 203 for s in SLANTS: 204 w.char_style("posture%s %s" % (suf, s), {"CharPosture" + suf: enum("awt.FontSlant", s)}) 205 for f in FAMILIES: 206 w.char_style("family%s %s" % (suf, f), {"CharFontFamily" + suf: const("awt.FontFamily." + f)}) 207 for p in PITCHES: 208 w.char_style("pitch%s %s" % (suf, p), {"CharFontPitch" + suf: const("awt.FontPitch." + p)}) 209 for c in CHARSETS: 210 w.char_style("charset%s %s" % (suf, c), {"CharFontCharSet" + suf: const("awt.CharSet." + c)}) 211 for f in FAMILIES: 212 for p in PITCHES[1:]: 213 w.char_style("named%s %s %s" % (suf, f, p), {"CharFontName" + suf: "T12Font%s%s%s" % (suf, f, p), "CharFontFamily" + suf: const("awt.FontFamily." + f), "CharFontPitch" + suf: const("awt.FontPitch." + p), "CharFontStyleName" + suf: "Regular"}) 214 w.char_style("diffheight%s" % suf, {"CharDiffHeight" + suf: 2.0}) 215 w.char_style("propheight%s" % suf, {"CharPropHeight" + suf: 150}) 216 w.char_style("height%s" % suf, {"CharHeight" + suf: 17.5}) 217 for v in UNDERLINES: 218 w.char_style("underline %d" % v, {"CharUnderline": v}) 219 w.char_style("underline-col %d" % v, {"CharUnderline": v, "CharUnderlineHasColor": True, "CharUnderlineColor": 0xFF0000}) 220 w.char_style("underline-word %d" % v, {"CharUnderline": v, "CharWordMode": True}) 221 w.char_style("overline %d" % v, {"CharOverline": v}) 222 w.char_style("overline-col %d" % v, {"CharOverline": v, "CharOverlineHasColor": True, "CharOverlineColor": 0x00FF00}) 223 w.char_style("overline-word %d" % v, {"CharOverline": v, "CharWordMode": True}) 224 for v in STRIKES: 225 w.char_style("strike %d" % v, {"CharStrikeout": v}) 226 w.char_style("strike-word %d" % v, {"CharStrikeout": v, "CharWordMode": True}) 227 for v in range(5): 228 w.char_style("casemap %d" % v, {"CharCaseMap": v}) 229 for v in range(3): 230 w.char_style("relief %d" % v, {"CharRelief": v}) 231 for v in (0, 1, 2, 3, 4, 11, 12, 13, 14): 232 w.char_style("emphasis %d" % v, {"CharEmphasis": v}) 233 for v in (-30, 0, 40): 234 w.char_style("kerning %d" % v, {"CharKerning": v}) 235 for v in (True, False): 236 w.char_style("autokern %s" % v, {"CharAutoKerning": v}) 237 w.char_style("flash %s" % v, {"CharFlash": v}) 238 w.char_style("hidden %s" % v, {"CharHidden": v}) 239 w.char_style("shadowed %s" % v, {"CharShadowed": v}) 240 w.char_style("contoured %s" % v, {"CharContoured": v}) 241 w.char_style("fitline %s" % v, {"CharRotation": 900, "CharRotationIsFitToLine": v}) 242 w.char_style("combine %s" % v, {"CharCombineIsOn": v, "CharCombinePrefix": "<", "CharCombineSuffix": ">"}) 243 w.char_style("transparent-back %s" % v, {"CharBackColor": 0xFFFF00, "CharBackTransparent": v}) 244 for v in (50, 100, 150): 245 w.char_style("scalewidth %d" % v, {"CharScaleWidth": v}) 246 for e, h in ((33, 58), (-33, 58), (101, 100), (0, 100)): 247 w.char_style("escapement %d" % e, {"CharEscapement": e, "CharEscapementHeight": h}) 248 for r in (0, 900, 2700): 249 w.char_style("rotation %d" % r, {"CharRotation": r}) 250 w.char_style("color auto", {"CharColor": -1}) 251 w.char_style("color red", {"CharColor": 0xFF0000}) 252 for lang, c in (("en", "US"), ("de", "DE"), ("fr", "CA"), ("ja", "JP"), ("zh", "CN"), ("ko", "KR"), ("ar", "SA"), ("th", "TH"), ("he", "IL"), ("hi", "IN")): 253 loc = uno.createUnoStruct("com.sun.star.lang.Locale", lang, c, "") 254 w.char_style("locale %s-%s" % (lang, c), {"CharLocale": loc, "CharLocaleAsian": loc, "CharLocaleComplex": loc}) 255 doc = w.flush() 256 save(doc, "writer-char-styles.odt", "writer8") 257 doc.close(True) 258 readback("writer-char-styles.odt", "CharacterStyles", w.specs["CharacterStyles"]) 259 build() 260 261 262def png(name): 263 import zlib, struct 264 d = os.path.join(os.path.dirname(out), "work") 265 os.makedirs(d, exist_ok=True) 266 path = os.path.join(d, name) 267 raw = b"".join(b"\x00" + b"".join(bytes([(x * 30) % 256, (y * 30) % 256, 128]) for x in range(8)) for y in range(8)) 268 269 def chunk(t, b): 270 c = struct.pack(">I", len(b)) + t + b 271 return c + struct.pack(">I", zlib.crc32(t + b) & 0xFFFFFFFF) 272 with open(path, "wb") as f: 273 f.write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 8, 8, 8, 2, 0, 0, 0)) + chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b"")) 274 return uno.systemPathToFileUrl(path) 275 276 277def border(outer, inner=0, dist=0, color=0): 278 return uno.createUnoStruct("com.sun.star.table.BorderLine", color, inner, outer, dist) 279 280 281def tab(pos, align, fill=" ", dec="."): 282 t = uno.createUnoStruct("com.sun.star.style.TabStop") 283 t.Position, t.Alignment, t.FillChar, t.DecimalChar = pos, enum("style.TabAlign", align), uno.Char(fill), uno.Char(dec) 284 return t 285 286 287def tabs(*ts): 288 if len(ts) == 1 and isinstance(ts[0], (tuple, list)) or len(ts) == 1 and hasattr(ts[0], "__next__"): 289 ts = tuple(ts[0]) 290 return uno.Any("[]com.sun.star.style.TabStop", tuple(ts)) 291 292 293def breaks(): 294 return [enum("style.BreakType", n) for n in ("NONE", "COLUMN_BEFORE", "COLUMN_AFTER", "COLUMN_BOTH", "PAGE_BEFORE", "PAGE_AFTER", "PAGE_BOTH")] 295 296 297@section 298def writer_para(): 299 w = W() 300 for v in range(5): 301 w.par_style("adjust %d" % v, {"ParaAdjust": v}) 302 w.par_style("lastline %d" % v, {"ParaAdjust": 3, "ParaLastLineAdjust": v}) 303 w.par_style("vertalign %d" % v, {"ParaVertAlignment": v}) 304 w.par_style("writingmode %d" % v, {"WritingMode": v}) 305 w.para("direct adjust %d" % v, props={"ParaAdjust": v}) 306 w.para("direct writingmode %d" % v, props={"WritingMode": v}) 307 w.para("direct vertalign %d" % v, props={"ParaVertAlignment": v}) 308 for v in (True, False): 309 for p in ("ParaExpandSingleWord", "ParaIsAutoFirstLineIndent", "SnapToGrid", "ParaRegisterModeActive", "ParaIsHyphenation", "ParaIsHangingPunctuation", "ParaIsCharacterDistance", "ParaIsForbiddenRules", "ParaSplit", "ParaKeepTogether", "ParaLineNumberCount", "FontIndependentLineSpacing", "ParaIsConnectBorder"): 310 w.par_style("%s %s" % (p, v), {p: v}) 311 w.para("direct %s %s" % (p, v), props={p: v}) 312 for i, b in enumerate(breaks()): 313 w.par_style("break %d" % i, {"BreakType": b}) 314 w.para("direct break %d" % i, props={"BreakType": b}) 315 w.par_style("pagedesc", {"PageDescName": "Standard", "PageNumberOffset": 3}) 316 w.par_style("pagedesc-break", {"BreakType": enum("style.BreakType", "PAGE_BEFORE"), "PageDescName": "Standard", "PageNumberOffset": 5}) 317 w.par_style("linenumber", {"ParaLineNumberCount": True, "ParaLineNumberStartValue": 7}) 318 w.par_style("hyphen", {"ParaIsHyphenation": True, "ParaHyphenationMaxLeadingChars": 3, "ParaHyphenationMaxTrailingChars": 4, "ParaHyphenationMaxHyphens": 2}) 319 w.par_style("orphans", {"ParaOrphans": 3, "ParaWidows": 4}) 320 w.par_style("tabs-all", {"ParaTabStops": tabs(tab(1000 * (i + 1), a, f, d) for i, (a, f, d) in enumerate((("LEFT", " ", "."), ("CENTER", ".", "."), ("RIGHT", "-", "."), ("DECIMAL", "_", ","), ("DECIMAL", " ", "."), ("DECIMAL", "*", "x"), ("DEFAULT", " ", "."))))}) 321 w.para("direct tabs", props={"ParaTabStops": tabs(tab(1500, "DECIMAL", ".", ","), tab(3000, "RIGHT", "-"))}) 322 w.par_style("tabstopdistance", {"TabStopDistance": 1500}) 323 for mode, h in ((0, 150), (1, 600), (2, 200), (3, 500)): 324 ls = uno.createUnoStruct("com.sun.star.style.LineSpacing", mode, h) 325 w.par_style("linespacing %d" % mode, {"ParaLineSpacing": ls}) 326 w.para("direct linespacing %d" % mode, props={"ParaLineSpacing": ls}) 327 w.par_style("margins", {"ParaLeftMargin": 1000, "ParaRightMargin": 800, "ParaTopMargin": 300, "ParaBottomMargin": 200, "ParaFirstLineIndent": 500}) 328 w.par_style("margins-rel", {"ParaLeftMarginRelative": 10, "ParaRightMarginRelative": 10, "ParaTopMarginRelative": 10, "ParaBottomMarginRelative": 10, "ParaFirstLineIndentRelative": 10}) 329 w.par_style("margins-same", {"ParaLeftMargin": 1000, "ParaRightMargin": 1000, "ParaTopMargin": 1000, "ParaBottomMargin": 1000}) 330 w.par_style("back", {"ParaBackColor": 0x99CCFF}) 331 w.par_style("back-transparent", {"ParaBackTransparent": True}) 332 url = png("para.png") 333 for loc in ("NONE", "LEFT_TOP", "MIDDLE_TOP", "RIGHT_TOP", "LEFT_MIDDLE", "MIDDLE_MIDDLE", "RIGHT_MIDDLE", "LEFT_BOTTOM", "MIDDLE_BOTTOM", "RIGHT_BOTTOM", "AREA", "TILED"): 334 w.par_style("backgraphic %s" % loc, {"ParaBackGraphicURL": url, "ParaBackGraphicLocation": enum("style.GraphicLocation", loc), "ParaBackGraphicFilter": "png"}) 335 w.par_style("backgraphic-nofilter %s" % loc, {"ParaBackGraphicURL": url, "ParaBackGraphicLocation": enum("style.GraphicLocation", loc)}) 336 for i, (o, n, d) in enumerate(((20, 0, 0), (20, 20, 20), (50, 30, 40), (100, 0, 0), (35, 35, 35))): 337 b = border(o, n, d, 0x336699) 338 w.par_style("border-all %d" % i, {"LeftBorder": b, "RightBorder": b, "TopBorder": b, "BottomBorder": b, "LeftBorderDistance": 100, "RightBorderDistance": 100, "TopBorderDistance": 100, "BottomBorderDistance": 100}) 339 w.par_style("border-left-only %d" % i, {"LeftBorder": b, "LeftBorderDistance": 120}) 340 w.par_style("border-lr %d" % i, {"LeftBorder": b, "RightBorder": border(o + 10, n, d)}) 341 w.par_style("border-tb %d" % i, {"TopBorder": b, "BottomBorder": border(o + 10, n, d), "ParaIsConnectBorder": False}) 342 w.par_style("border-distance %d" % i, {"LeftBorder": b, "RightBorder": b, "TopBorder": b, "BottomBorder": b, "LeftBorderDistance": 50 * i, "RightBorderDistance": 60, "TopBorderDistance": 70, "BottomBorderDistance": 80}) 343 w.par_style("border-inner-only", {"LeftBorder": border(0, 20, 0, 0x336699), "TopBorder": border(0, 20, 30, 0x336699)}) 344 for loc in ("NONE", "TOP_LEFT", "TOP_RIGHT", "BOTTOM_LEFT", "BOTTOM_RIGHT"): 345 sh = uno.createUnoStruct("com.sun.star.table.ShadowFormat", enum("table.ShadowLocation", loc), 100, False, 0x808080) 346 w.par_style("shadow %s" % loc, {"ParaShadowFormat": sh}) 347 dc = uno.createUnoStruct("com.sun.star.style.DropCapFormat", 3, 2, 200) 348 cs = w.style("CharacterStyles", {"CharWeight": 150.0}, tag="C") 349 w.par_style("dropcap", {"DropCapFormat": dc, "DropCapWholeWord": False, "DropCapCharStyleName": cs}) 350 w.par_style("dropcap-word", {"DropCapFormat": dc, "DropCapWholeWord": True}) 351 w.par_style("outline", {"OutlineLevel": 2}) 352 w.par_style("defaultoutline", {"OutlineLevel": 0}) 353 w.para("drop cap text word", pstyle="P%d" % w.n) 354 doc = w.flush() 355 save(doc, "writer-para-styles.odt", "writer8") 356 doc.close(True) 357 readback("writer-para-styles.odt", "ParagraphStyles", w.specs["ParagraphStyles"]) 358 359 360def level(rules, i, **kw): 361 cur = {p.Name: p.Value for p in rules.getByIndex(i)} 362 cur.update(kw) 363 uno.invoke(rules, "replaceByIndex", (i, uno.Any("[]com.sun.star.beans.PropertyValue", tuple(pv(k, v) for k, v in cur.items())))) 364 365 366def font(name, family=0, pitch=0, charset=0, style=""): 367 f = uno.createUnoStruct("com.sun.star.awt.FontDescriptor") 368 f.Name, f.StyleName, f.Family, f.Pitch, f.CharSet = name, style, family, pitch, charset 369 return f 370 371 372@section 373def writer_list(): 374 w = W() 375 url = png("bullet.png") 376 n = 0 377 sz = uno.createUnoStruct("com.sun.star.awt.Size", 500, 400) 378 for adj in (3, 1, 2): 379 for typ in (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90) if adj == 3 else (4, 6, 8): 380 try: 381 st = w.doc.createInstance("com.sun.star.style.NumberingStyle") 382 n += 1 383 w.doc.StyleFamilies.getByName("NumberingStyles").insertByName("N%d" % n, st) 384 r = st.NumberingRules 385 for lv in range(3): 386 kw = {"NumberingType": typ, "Adjust": adj, "StartWith": 3 + lv, "ParentNumbering": lv + 1, "Prefix": "(", "Suffix": ")", "PositionAndSpaceMode": lv % 2, "LabelFollowedBy": lv, "IndentAt": 1000 * (lv + 1), "FirstLineIndent": -500, "ListtabStopPosition": 1500 * (lv + 1)} 387 if typ == 6: 388 kw.update({"BulletChar": chr(0x2022 + lv), "BulletFont": font("OpenSymbol", lv, lv % 3, 0, "Regular"), "BulletRelSize": 80, "BulletColor": 0xFF0000}) 389 if typ == 8: 390 kw.update({"GraphicURL": url, "GraphicSize": sz, "VertOrient": (adj * 3 + lv * 4) % 10}) 391 level(r, lv, **kw) 392 st.NumberingRules = r 393 w.para("list style %d type %d adj %d" % (n, typ, adj), props={"NumberingStyleName": "N%d" % n}) 394 except Exception as e: 395 print("WARN list", typ, adj, type(e).__name__, str(e)[:80]) 396 for vo in range(10): 397 st = w.doc.createInstance("com.sun.star.style.NumberingStyle") 398 n += 1 399 w.doc.StyleFamilies.getByName("NumberingStyles").insertByName("N%d" % n, st) 400 r = st.NumberingRules 401 for lv in range(2): 402 level(r, lv, NumberingType=8, GraphicURL=url, GraphicSize=sz, VertOrient=(vo + lv) % 10, PositionAndSpaceMode=lv) 403 st.NumberingRules = r 404 w.para("image bullet vertorient %d" % vo, props={"NumberingStyleName": "N%d" % n}) 405 for vo in range(10): 406 r = w.doc.ChapterNumberingRules 407 for lv in range(10): 408 level(r, lv, NumberingType=(vo + lv) % 8, Adjust=(1, 2, 3)[lv % 3], PositionAndSpaceMode=vo % 2, StartWith=2) 409 doc = w.flush() 410 save(doc, "writer-list-styles.odt", "writer8") 411 doc.close(True) 412 413 414@section 415def writer_ruby(): 416 w = W() 417 for adj in range(5): 418 for above in (True, False): 419 w.para("ruby base %d %s" % (adj, above)) 420 doc = w.flush() 421 en = doc.Text.createEnumeration() 422 k = 0 423 while en.hasMoreElements(): 424 p = en.nextElement() 425 c = doc.Text.createTextCursorByRange(p) 426 adj, above = divmod(k, 2) 427 setp(c, "RubyText", "ru", "ruby") 428 setp(c, "RubyAdjust", adj, "ruby") 429 setp(c, "RubyIsAbove", above == 0, "ruby") 430 k += 1 431 save(doc, "writer-ruby.odt", "writer8") 432 doc.close(True) 433 434 435@section 436def writer_section(): 437 doc = new("private:factory/swriter") 438 url = png("section.png") 439 cnt = 0 440 for wm in (0, 1, 2, 3, 4): 441 for sep in (True, False): 442 for balance in (True, False): 443 cnt += 1 444 sec = doc.createInstance("com.sun.star.text.TextSection") 445 c = doc.Text.createTextCursor() 446 c.gotoEnd(False) 447 doc.Text.insertString(c, "section %d" % cnt, False) 448 c.goLeft(len("section %d" % cnt), True) 449 doc.Text.insertTextContent(c, sec, True) 450 setall(sec, {"WritingMode": wm, "DontBalanceTextColumns": balance, "SectionLeftMargin": 100 * cnt, "SectionRightMargin": 50 * cnt, "EditInReadonly": sep, "BackColor": 0xEEEEEE if sep else -1, "IsProtected": balance and sep}, "section") 451 cols = sec.TextColumns 452 cols.setColumnCount(2 + (cnt % 2)) 453 if sep: 454 setall(cols, {"SeparatorLineIsOn": True, "SeparatorLineWidth": 10 * cnt, "SeparatorLineColor": 0x333333, "SeparatorLineRelativeHeight": 50 + cnt, "SeparatorLineVerticalAlignment": enum("style.VerticalAlignment", ("TOP", "MIDDLE", "BOTTOM")[cnt % 3])}, "cols") 455 sec.TextColumns = cols 456 c.gotoEnd(False) 457 doc.Text.insertControlCharacter(c, const("text.ControlCharacter.PARAGRAPH_BREAK"), False) 458 for loc in ("LEFT_TOP", "AREA", "TILED", "MIDDLE_MIDDLE"): 459 sec = doc.createInstance("com.sun.star.text.TextSection") 460 c = doc.Text.createTextCursor() 461 c.gotoEnd(False) 462 doc.Text.insertString(c, "bg %s" % loc, False) 463 c.goLeft(len("bg %s" % loc), True) 464 doc.Text.insertTextContent(c, sec, True) 465 setall(sec, {"BackGraphicURL": url, "BackGraphicLocation": enum("style.GraphicLocation", loc), "BackGraphicFilter": "png"}, "section") 466 c.gotoEnd(False) 467 doc.Text.insertControlCharacter(c, const("text.ControlCharacter.PARAGRAPH_BREAK"), False) 468 save(doc, "writer-sections.odt", "writer8") 469 doc.close(True) 470 471 472LOCALES = [("en", "US"), ("de", "DE"), ("ja", "JP"), ("ar", "SA"), ("th", "TH"), ("he", "IL"), ("zh", "TW"), ("ko", "KR"), ("fr", "FR")] 473 474FORMATS = [ 475 ("en", "US", ["YYYY-MM-DD", "D.M.YY", "MMM D, YYYY", "MMMM D", "NN, DD MMMM YYYY", "NNN D", "NNNN", "DD/MM/YYYY HH:MM:SS", "MM/DD/YY HH:MM AM/PM", 476 "HH:MM:SS", "[HH]:MM:SS", "HH:MM:SS.00", "HH:MM AM/PM", "[MM]:SS", "[SS]", "[HH]:MM", "MM:SS.0", "YY", "YYYY", "MM", "MMM", "MMMM", "MMMMM", "D", "DD", "NN", "NNN", "NNNN", 477 "Q", "QQ", "\"Q\"Q YYYY", "WW", "\"Week \"WW", "YYYY \"Q\"Q WW", "G", "GG", "GGG", "E", "EE", "R", "RR", "GGGE\"/\"M\"/\"D", "GE.M.D", "RR/MM/DD", 478 "[~buddhist]YYYY-MM-DD", "[~buddhist]D MMMM YYYY NNNN", "[~buddhist]WW", "[~buddhist]Q", "[~buddhist]GGGEE", "[~buddhist]MMM", "[~buddhist]NN", 479 "[~hijri]D/M/YYYY", "[~hijri]D MMMM YYYY NNN", "[~hijri]QQ", "[~hijri]WW", "[~hijri]GGG E", "[~hijri]NNNN", 480 "[~gengou]GGGE.M.D", "[~gengou]GE\"年\"M\"月\"D\"日\"", "[~gengou]EE", "[~gengou]D MMMM", "[~gengou]WW", "[~gengou]Q", 481 "[~jewish]D MMMM YYYY", "[~jewish]WW", "[~jewish]QQ", "[~jewish]NNN D", 482 "[~ROC]RR/MM/DD", "[~ROC]GGG R", "[~ROC]EE", "[~ROC]NNN", "[~ROC]Q", "[~ROC]WW", 483 "[~gregorian]YYYY-MM-DD", "[~julian]YYYY-MM-DD", "[~persian]YYYY/MM/DD", "[~dangi]YYYY-MM-DD", "[~indian]YYYY-MM-DD", "[~coptic]YYYY-MM-DD", "[~ethiopic]YYYY-MM-DD", 484 "[NatNum1]YYYY-MM-DD", "[NatNum2][$-411]YYYY/MM/DD", "[NatNum3]HH:MM", "[DBNum1][$-804]YYYY\"年\"M\"月\"", "[DBNum2][$-804]YYYY", "[DBNum3][$-411]D", "[NatNum1]NNNN", 485 "0", "0.00", "#,##0", "#,##0.00", "0.0000", "00000", "#", "#.##", "0.00E+00", "#,##0.0E+000", "##0.0E+0", "0E+00", "0.0E-00", "0%", "0.00%", "#,##0%", "0.0E+00%", 486 "# ?/?", "# ??/??", "# ???/???", "#,### ?/?", "?/?", "# ?/16", "# ?/8", "# ??/100", "#,##0 ?/4", "0,", "0,,", "#,##0,", "#,##0,,", "0.0,,\"M\"", "0.0,\"k\"", "#,##0.00,", 487 "0\" abc\"", "\"abc \"0", "000-0000", "###\\-####", "0\" x \"0", "00\":\"00", "(000) 000-0000", "0.0\" x \"0", "#\" \"##", "0 ??/??\"x\"", "0.00\" kg\"", "\"#\"0", 488 "000\"-\"##\"-\"0000", "#,##0.00\" EUR \"##", "#\" m\"0.0", "0\"a\"0\"b\"0", 489 "[RED]0;[BLUE]-0", "[>100]0;[<0]-0;0", "[<1]0.00;[>=1]0", "[RED][<0]0;[GREEN][>=0]0.00", "0;-0;\"zero\"", "0;[RED]-0;0;\"text:\"@", "[MAGENTA]#,##0.00;[CYAN]-#,##0.00", "[=1]\"one\";[=2]\"two\";\"many\"", 490 "[$€-407] #,##0.00", "#,##0.00 [$USD]", "[$¥-411] #,##0", "[$$-409]#,##0.00", "[$-409]#,##0.00", "[$-407]0.00", "[$-411]0", "[$-C09]0", "[$-1009]0", "#,##0.00 [$zł-415]", "[$CHF-807] #,##0.00", 491 "[$-F400]HH:MM:SS AM/PM", "[$-F800]DDDD, MMMM DD, YYYY", "[$-411]YYYY\"年\"M\"月\"D\"日\"", "[$-404]YYYY/MM/DD", "[$-41E]D MMMM YYYY", "[$-1000000]YYYY", "[$-1010409]0", "[$-2000409]0", 492 "[NatNum1]0", "[NatNum2]0", "[NatNum3]#,##0", "[NatNum4]0", "[NatNum5]0", "[NatNum6]0", "[NatNum7]0", "[NatNum8]0", "[NatNum9]0", "[NatNum10]0", "[NatNum11]0", "[NatNum12]0", 493 "[NatNum1][$-411]0", "[NatNum2][$-804]0", "[NatNum3][$-404]0", "[NatNum1][$-401]0", "[NatNum1][$-41E]0", "[NatNum1][$-439]0", "[NatNum1][$-412]0", "[DBNum1]0", "[DBNum2]0", "[DBNum3]0", "[DBNum1][$-411]0", "[DBNum2][$-804]0", "[DBNum3][$-404]0", 494 "[NatNum1]0;[NatNum2]-0", "[NatNum1][RED]0", "[NatNum1]0.0E+00", "[NatNum1]0%", "[NatNum1]0 ?/?", 495 "@", "\"Text: \"@", "[RED]@", "@\" suffix\"", "\"<\"@\">\"", "[NatNum1]@", "BOOLEAN", "[RED]BOOLEAN", "General", "General\" x\"", "[BLUE]General", "0.00\" \"[$EUR]", 496 "[<0.5]0%;[>=0.5]0.00%", "[>1]0.0%;[<-1]-0.0%;0.00%", "0%;[RED]-0%;0.0%", "[NatNum1][$€-407] #,##0.00", "[NatNum2][$¥-411]#,##0", "[NatNum1]BOOLEAN", "[NatNum1]0.00%", "[NatNum1]0%;[NatNum2]-0%", 497 "[DBNum1][$-804]0%", "[>5]0.00;[NatNum1]0"] + ["[NatNum%d]YYYY-MM-DD" % n for n in range(1, 13)] + ["[NatNum%d][$-411]YYYY\"/\"MM\"/\"DD" % n for n in range(1, 13)] 498 + ["[DBNum%d][$-804]YYYY-MM-DD" % n for n in range(1, 4)] + ["[NatNum%d]HH:MM:SS" % n for n in (1, 2, 3, 4)] + ["[NatNum%d][$-411]HH:MM" % n for n in (1, 2, 3)]), 499] 500 501 502@section 503def calc_numbers(): 504 doc = new("private:factory/scalc") 505 sh = doc.Sheets.getByIndex(0) 506 nf = doc.NumberFormats 507 row = 0 508 seen = {} 509 locs = [(l, c) for l, c in LOCALES] 510 ok = bad = 0 511 expect = [] 512 for (l0, c0, codes) in FORMATS: 513 for (l, c) in ([(l0, c0)] + locs): 514 loc = uno.createUnoStruct("com.sun.star.lang.Locale", l, c, "") 515 for code in codes: 516 if (l, c) != (l0, c0) and not any(t in code for t in ("[~", "GG", "NN", "[NatNum", "[DBNum", "Q", "WW", "[$")): 517 continue 518 try: 519 key = nf.queryKey(code, loc, False) 520 if key == -1: 521 key = nf.addNew(code, loc) 522 except Exception as e: 523 bad += 1 524 print("WARN numfmt", l, c, code, type(e).__name__) 525 continue 526 if key in seen: 527 continue 528 seen[key] = 1 529 ok += 1 530 cell = sh.getCellByPosition(0, row) 531 cell.Value = 44197.4375 + row if ("Q" in code or "W" in code or "Y" in code or "D" in code or "G" in code or "H" in code or "E" in code or "R" in code or "N" in code or "M" in code) and "0" not in code[:1] else 1234.5678 - row 532 if "@" in code: 533 cell.String = "text %d" % row 534 if "BOOLEAN" in code: 535 cell.Value = 1 536 cell.NumberFormat = key 537 sh.getCellByPosition(1, row).String = "%s %s" % (l + "-" + c, code) 538 expect.append((row, code, l, c)) 539 row += 1 540 print("numfmt ok", ok, "bad", bad) 541 for t in (1, 2, 4, 8, 16, 32, 64, 128, 256, 1024): 542 for (l, c) in locs: 543 try: 544 loc = uno.createUnoStruct("com.sun.star.lang.Locale", l, c, "") 545 key = nf.getStandardFormat(t, loc) 546 cell = sh.getCellByPosition(2, row) 547 cell.Value = 44197.4375 + row 548 cell.NumberFormat = key 549 row += 1 550 except Exception as e: 551 print("WARN stdfmt", t, l, type(e).__name__) 552 for fmt in range(0, 60): 553 try: 554 loc = uno.createUnoStruct("com.sun.star.lang.Locale", "en", "US", "") 555 cell = sh.getCellByPosition(3, fmt) 556 cell.Value = 44197.4375 + fmt 557 cell.NumberFormat = fmt 558 except Exception: 559 pass 560 save(doc, "calc-numberformats.ods", "calc8") 561 doc.close(True) 562 try: 563 d2 = reload("calc-numberformats.ods") 564 sh2 = d2.Sheets.getByIndex(0) 565 nf2 = d2.NumberFormats 566 diff = 0 567 for (r, code, l, c) in expect: 568 try: 569 ps = nf2.getByKey(sh2.getCellByPosition(0, r).NumberFormat) 570 got, gl = ps.getPropertyValue("FormatString"), ps.getPropertyValue("Locale") 571 except Exception as e: 572 diff += 1 573 print("RT-NUMFMT", l, c, code, "-> exception", type(e).__name__) 574 continue 575 if got != code or (gl.Language, gl.Country) != (l, c): 576 diff += 1 577 print("RT-NUMFMT", l, c, code, "->", got, gl.Language, gl.Country) 578 print("RT-SUMMARY calc-numberformats.ods formats", len(expect), "differing", diff) 579 d2.close(True) 580 except Exception as e: 581 print("RT-FAIL calc-numberformats", type(e).__name__, str(e)[:100]) 582 583 584def char_cases(): 585 c = [] 586 for suf in ("", "Asian", "Complex"): 587 c += [("weight%s %s" % (suf, v), {"CharWeight" + suf: float(v)}) for v in WEIGHTS] 588 c += [("posture%s %s" % (suf, v), {"CharPosture" + suf: enum("awt.FontSlant", v)}) for v in SLANTS] 589 c += [("family%s %s" % (suf, v), {"CharFontFamily" + suf: const("awt.FontFamily." + v)}) for v in FAMILIES] 590 c += [("pitch%s %s" % (suf, v), {"CharFontPitch" + suf: const("awt.FontPitch." + v)}) for v in PITCHES] 591 c += [("charset%s %s" % (suf, v), {"CharFontCharSet" + suf: const("awt.CharSet." + v)}) for v in CHARSETS] 592 c += [("named%s %s" % (suf, f), {"CharFontName" + suf: "T12Face%s%s" % (suf, f), "CharFontFamily" + suf: const("awt.FontFamily." + f), "CharFontPitch" + suf: const("awt.FontPitch.FIXED"), "CharFontStyleName" + suf: "Bold"}) for f in FAMILIES] 593 c += [("height%s" % suf, {"CharHeight" + suf: 17.5}), ("propheight%s" % suf, {"CharPropHeight" + suf: 150}), ("diffheight%s" % suf, {"CharDiffHeight" + suf: 2.0})] 594 for v in UNDERLINES: 595 c += [("underline %d" % v, {"CharUnderline": v}), ("underline-col %d" % v, {"CharUnderline": v, "CharUnderlineHasColor": True, "CharUnderlineColor": 0xFF0000}), ("underline-word %d" % v, {"CharUnderline": v, "CharWordMode": True}), 596 ("overline %d" % v, {"CharOverline": v}), ("overline-col %d" % v, {"CharOverline": v, "CharOverlineHasColor": True, "CharOverlineColor": 0x00FF00}), ("overline-word %d" % v, {"CharOverline": v, "CharWordMode": True})] 597 for v in STRIKES: 598 c += [("strike %d" % v, {"CharStrikeout": v}), ("strike-word %d" % v, {"CharStrikeout": v, "CharWordMode": True}), ("crossed %d" % v, {"CharCrossedOut": bool(v)})] 599 c += [("casemap %d" % v, {"CharCaseMap": v}) for v in range(5)] 600 c += [("relief %d" % v, {"CharRelief": v}) for v in range(3)] 601 c += [("emphasis %d" % v, {"CharEmphasis": v}) for v in (0, 1, 2, 3, 4, 11, 12, 13, 14)] 602 c += [("kerning %d" % v, {"CharKerning": v}) for v in (-30, 0, 40)] 603 for v in (True, False): 604 c += [("autokern %s" % v, {"CharAutoKerning": v}), ("flash %s" % v, {"CharFlash": v}), ("shadowed %s" % v, {"CharShadowed": v}), ("contoured %s" % v, {"CharContoured": v}), 605 ("fitline %s" % v, {"CharRotation": 900, "CharRotationIsFitToLine": v}), ("combine %s" % v, {"CharCombineIsOn": v, "CharCombinePrefix": "<", "CharCombineSuffix": ">"}), 606 ("hidden %s" % v, {"CharHidden": v})] 607 c += [("scalewidth %d" % v, {"CharScaleWidth": v}) for v in (50, 100, 150)] 608 c += [("escapement %d" % e, {"CharEscapement": e, "CharEscapementHeight": h}) for e, h in ((33, 58), (-33, 58), (101, 100), (0, 100))] 609 c += [("rotation %d" % r, {"CharRotation": r}) for r in (0, 900, 2700)] 610 c += [("color auto", {"CharColor": -1}), ("color red", {"CharColor": 0xFF0000}), ("back", {"CharBackColor": 0xFFFF00})] 611 for lang, cc in (("ja", "JP"), ("ar", "SA"), ("th", "TH"), ("zh", "CN"), ("he", "IL"), ("ko", "KR")): 612 loc = uno.createUnoStruct("com.sun.star.lang.Locale", lang, cc, "") 613 c.append(("locale %s" % lang, {"CharLocale": loc, "CharLocaleAsian": loc, "CharLocaleComplex": loc})) 614 return c 615 616 617def para_cases(): 618 c = [] 619 for v in range(5): 620 c += [("adjust %d" % v, {"ParaAdjust": v}), ("lastline %d" % v, {"ParaAdjust": 3, "ParaLastLineAdjust": v}), ("vertalign %d" % v, {"ParaVertAlignment": v}), ("writingmode %d" % v, {"WritingMode": v})] 621 for v in (True, False): 622 for p in ("ParaExpandSingleWord", "ParaIsAutoFirstLineIndent", "SnapToGrid", "ParaRegisterModeActive", "ParaIsHyphenation", "ParaIsHangingPunctuation", "ParaIsCharacterDistance", "ParaIsForbiddenRules", "ParaSplit", "ParaKeepTogether", "FontIndependentLineSpacing", "ParaIsConnectBorder"): 623 c.append(("%s %s" % (p, v), {p: v})) 624 c.append(("tabs", {"ParaTabStops": tabs(tab(1500, "DECIMAL", ".", ","), tab(3000, "RIGHT", "-"), tab(4000, "CENTER", "."), tab(5000, "LEFT", "_"))})) 625 for mode, h in ((0, 150), (1, 600), (2, 200), (3, 500)): 626 c.append(("linespacing %d" % mode, {"ParaLineSpacing": uno.createUnoStruct("com.sun.star.style.LineSpacing", mode, h)})) 627 c += [("margins", {"ParaLeftMargin": 1000, "ParaRightMargin": 800, "ParaTopMargin": 300, "ParaBottomMargin": 200, "ParaFirstLineIndent": 500}), 628 ("margins-rel", {"ParaLeftMarginRelative": 10, "ParaTopMarginRelative": 10, "ParaBottomMarginRelative": 10, "ParaFirstLineIndentRelative": 10}), 629 ("hyphen", {"ParaIsHyphenation": True, "ParaHyphenationMaxLeadingChars": 3, "ParaHyphenationMaxTrailingChars": 4, "ParaHyphenationMaxHyphens": 2}), 630 ("orphans", {"ParaOrphans": 3, "ParaWidows": 4}), ("tabdist", {"TabStopDistance": 1500}), ("outline", {"NumberingLevel": 2}), 631 ("back", {"ParaBackColor": 0x99CCFF}), ("regmode", {"ParaRegisterModeActive": True})] 632 return c 633 634 635def apply_text(doc, shape, label, props): 636 shape.String = label 637 chars = {k: v for k, v in props.items() if k.startswith("Char")} 638 others = {k: v for k, v in props.items() if k not in chars} 639 setall(shape, others, label) 640 if chars: 641 cur = shape.createTextCursor() 642 cur.gotoStart(False) 643 cur.goRight(len(label) - 1, True) 644 setall(cur, chars, label) 645 646 647def shapes_page(doc, page, cases, cols=6): 648 for k, (label, props) in enumerate(cases): 649 sh = doc.createInstance("com.sun.star.drawing.TextShape") 650 page.add(sh) 651 sh.setSize(uno.createUnoStruct("com.sun.star.awt.Size", 3000, 800)) 652 sh.setPosition(uno.createUnoStruct("com.sun.star.awt.Point", 500 + (k % cols) * 3300, 500 + (k // cols) * 900)) 653 apply_text(doc, sh, label, props) 654 655 656def style_cases(doc, family, svc, cases, tag): 657 fam = doc.StyleFamilies.getByName(family) 658 names = [] 659 for k, (label, props) in enumerate(cases): 660 st = fam.createInstance() if svc is None else doc.createInstance(svc) 661 name = "%s%d" % (tag, k) 662 fam.insertByName(name, st) 663 setall(st, props, name) 664 names.append(name) 665 return names 666 667 668@section 669def draw_text(): 670 doc = new("private:factory/sdraw") 671 page = doc.DrawPages.getByIndex(0) 672 cases = char_cases() + para_cases() 673 shapes_page(doc, page, cases) 674 names = style_cases(doc, "graphics", None, cases, "G") 675 page2 = doc.DrawPages.insertNewByIndex(1) 676 for k, n in enumerate(names): 677 sh = doc.createInstance("com.sun.star.drawing.TextShape") 678 page2.add(sh) 679 sh.setSize(uno.createUnoStruct("com.sun.star.awt.Size", 3000, 800)) 680 sh.setPosition(uno.createUnoStruct("com.sun.star.awt.Point", 500 + (k % 6) * 3300, 500 + (k // 6) * 900)) 681 sh.String = cases[k][0] 682 sh.Style = doc.StyleFamilies.getByName("graphics").getByName(n) 683 save(doc, "draw-text.odg", "draw8") 684 doc.close(True) 685 686 687@section 688def impress_text(): 689 doc = new("private:factory/simpress") 690 page = doc.DrawPages.getByIndex(0) 691 cases = char_cases() + para_cases() 692 shapes_page(doc, page, cases) 693 names = style_cases(doc, "graphics", None, cases[:120], "G") 694 page2 = doc.DrawPages.insertNewByIndex(1) 695 for k, n in enumerate(names): 696 sh = doc.createInstance("com.sun.star.drawing.TextShape") 697 page2.add(sh) 698 sh.setSize(uno.createUnoStruct("com.sun.star.awt.Size", 3000, 800)) 699 sh.setPosition(uno.createUnoStruct("com.sun.star.awt.Point", 500 + (k % 6) * 3300, 500 + (k // 6) * 900)) 700 sh.String = cases[k][0] 701 sh.Style = doc.StyleFamilies.getByName("graphics").getByName(n) 702 save(doc, "impress-text.odp", "impress8") 703 doc.close(True) 704 705 706@section 707def calc_text(): 708 doc = new("private:factory/scalc") 709 sh = doc.Sheets.getByIndex(0) 710 cases = char_cases() + para_cases() 711 names = style_cases(doc, "CellStyles", "com.sun.star.style.CellStyle", cases, "S") 712 for k, (label, props) in enumerate(cases): 713 a = sh.getCellByPosition(0, k) 714 a.String = label 715 setp(a, "CellStyle", names[k], label) 716 b = sh.getCellByPosition(1, k) 717 b.String = label 718 setall(b, {kk: v for kk, v in props.items() if kk.startswith("Char") or kk.startswith("Para")}, label) 719 cur = sh.getCellByPosition(2, k) 720 cur.String = label 721 cc = cur.createTextCursor() 722 cc.gotoStart(False) 723 cc.goRight(len(label) - 1, True) 724 setall(cc, {kk: v for kk, v in props.items() if kk.startswith("Char")}, label) 725 save(doc, "calc-text.ods", "calc8") 726 doc.close(True) 727 728 729@section 730def writer_page(): 731 doc = new("private:factory/swriter") 732 url = png("page.png") 733 pages = doc.StyleFamilies.getByName("PageStyles") 734 cases = [{"BackGraphicURL": url, "BackGraphicLocation": enum("style.GraphicLocation", loc), "BackGraphicFilter": "png", "BackGraphicTransparency": 30} for loc in ("LEFT_TOP", "AREA", "TILED", "RIGHT_BOTTOM", "NONE")] 735 cases += [{"BackColor": 0xCCCCCC, "BackTransparent": False}] 736 cases += [{"WritingMode": w} for w in range(5)] 737 for sepw, al in ((10, "TOP"), (30, "MIDDLE"), (50, "BOTTOM")): 738 cases.append({"__cols": (2, {"SeparatorLineIsOn": True, "SeparatorLineWidth": sepw, "SeparatorLineColor": 0x884400, "SeparatorLineRelativeHeight": 70, "SeparatorLineVerticalAlignment": enum("style.VerticalAlignment", al)})}) 739 for k, props in enumerate(cases): 740 st = doc.createInstance("com.sun.star.style.PageStyle") 741 pages.insertByName("T12Page%d" % k, st) 742 props = dict(props) 743 cols = props.pop("__cols", None) 744 setall(st, props, "page%d" % k) 745 if cols: 746 tc = st.TextColumns 747 tc.setColumnCount(cols[0]) 748 setall(tc, cols[1], "pagecols") 749 st.TextColumns = tc 750 c = doc.Text.createTextCursor() 751 c.gotoEnd(False) 752 doc.Text.insertString(c, "page style %d" % k, False) 753 setp(c, "PageDescName", "T12Page%d" % k, "page") 754 doc.Text.insertControlCharacter(c, const("text.ControlCharacter.PARAGRAPH_BREAK"), False) 755 save(doc, "writer-page-styles.odt", "writer8") 756 doc.close(True) 757 758 759# --- end of sections 760for _fn in SECTIONS: 761 run(_fn.__name__, _fn) 762sys.exit(1 if failed else 0) 763