summaryrefslogtreecommitdiffstats
path: root/filters/kpresenter/magicpoint/mgp2kpr.py
blob: 9752747106dace0c666045effaec878cae4887be (plain)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
#!/usr/bin/env python

"""This script converts a Magicpoint presentation and outputs
a KPresenter document (XML).

Magicpoint's homepage: http://www.mew.org/mgp/
KPresenter's homepage: http://www.koffice.org/kpresenter

This is free software, released under GPL v2.
Author: Lukas Tinkl <[email protected]>, 2002

TODO (in order of priority):
DONE: support linespacing
DONE: support bullets
DONE: support bold/italic faces
- support parsing the document defaults (%default and %tab)
- support horizontal bars (hard to position them properly)
- make it use the ZIP store instead of a plain XML file (needed for images below)
- support images
- support for MNG animations (KPresenter doesn't know about them ATM)

$Id: mgp2kpr.py 186390 2002-10-29 15:39:40Z lukas $
"""

import os, sys
import fileinput
import string
from xml.dom.DOMImplementation import implementation
from xml.dom import Document
from xml.dom import Element
from xml.dom.ext import PrettyPrint

def getYDpi():
  """Utility function; parses xdpyinfo output and returns the vertical DPI of the X display.
  Needed to transform the %-like font size into real font point size.
  """
  pipe=os.popen("(xdpyinfo | grep dot | cut -b21-22) 2>/dev/null", "r")
  if pipe:
    dpi=pipe.read().strip()
    if dpi:
      return dpi
  return 75

PAGE_WIDTH=680
Y_OFFSET=510

class MgpImporter:
  def __init__(self):
    "Constructor"
    self.charset="iso8859-1"
    self.pageCount=-1        #page counter
    self.defFonts={}         #default (symbolic) font names
    self.useDefaults=1       #use page default values?
    self.ydpi=int(getYDpi()) #Y DPI

    self.__reset()           #init properties

  def __reset(self):
    self.alignment="1"       #text alignment, left
    self.vgap=1              #line spacing

    #font properties
    self.fontName="standard"
    self.fontItalic=0
    self.fontBold=0
    self.fontSize=24         #default (approximated) font size (5%)
    self.textColor="white"

    # background properties
    self.backtype="0"
    self.backview="0"
    self.bctype="0"          #single color (0) or gradient (>0)
    self.color1="black"
    self.color2="white"

  def __setFontSize(self, command):
    tokens=string.split(command,' ')
    self.fontSize=int(Y_OFFSET/self.ydpi*72*float(tokens[1].strip())/100)
    #print self.fontSize

  def __setLineSpacing(self, command):
    tokens=string.split(command,' ')
    self.vgap=int(tokens[1].strip())

  def __setupDefaultFonts(self,command):
    tokens=string.split(command,' ')
    _key=string.replace(tokens[1], '"', '')
    _val=string.replace(tokens[3], '"', '')
    self.defFonts[_key]=_val
    #print self.defFonts

  def __setFontIndirect(self,command):
    tokens=string.split(command,' ')
    _font=string.replace(tokens[1], '"', '')
    if _font in self.defFonts.keys():        #�we have a "default" font, find it in the map
      self.__setFont(None,self.defFonts[_font])
      #print self.defFonts[_font]

  def __setFont(self,command,font=""):
    if command:
      tokens=string.split(command,' ')
      font=string.replace(tokens[1], '"', '').strip() #XLFD-like, eg: mincho-medium-r (family-weight-slant)
    
    _numDash=string.find(font,"-")           #find dashes

    if (_numDash==-1):                       #mincho
      self.fontName=font
      return
    else:                                    #mincho-medium-r
      _xlfd=string.split(font, "-")
      self.fontName=_xlfd[0]
      if (_xlfd[1]=="bold" or _xlfd[1]=="semibold" or _xlfd[1]=="demibold" or _xlfd[1]=="demi bold"): #this sucks :)
        self.fontBold=1
      else:
        self.fontBold=0

      if (_xlfd[2]=="i"):
        self.fontItalic=1
      else:
        self.fontItalic=0
        
    #print self.fontName

  def __setBgColor(self, command):
    tokens=string.split(command,' ')
    self.bctype="0"
    self.color1=string.replace(tokens[1].strip(),'"', '') #strip quotes and \n    

  def __setBgGradient(self, command):
    tokens=string.split(command,' ')
    #xsize=tokens[1]
    #ysize=tokens[2]
    #numcolors=tokens[3] or "256"
    #zoomflag=tokens[5] or "0"
    
    try:
      dir=tokens[4]
      self.color1=string.replace(tokens[6].strip(),'"', '') #strip quotes and \n
      self.color2=string.replace(tokens[7].strip(),'"', '')
    except:
      self.bctype="0"
      self.color1="black"
      self.color2="white"
      return

    if (dir=="0"): #vertical
      value="1"
    elif (dir=="90"): #horizontal
      value="2"
    elif (dir=="180"): #vertical, swapped colors
      value="1"
      self.color1,self.color2=self.color2,self.color1
    elif (dir=="270"): #horizontal, swapped colors
      value="2"
      self.color1,self.color2=self.color2,self.color1
    elif (dir=="45"): #diagonal 1 
      value="3"
    elif (dir=="135"): #diagonal 2
      value="4" #TODO swap colors for diagonals too?
    elif (dir=="-45"): #circular, what an easter egg ;)
      value="5"
    else:
      value="1"

    self.bctype=value
    
  def __setAlign(self,command):
    tokens=string.split(command,' ')
    if (tokens[0]=='leftfill'): #justify
      self.alignment="8"
    elif (tokens[0]=='right'):
      self.alignment="2"
    elif (tokens[0]=='center'):
      self.alignment="4"
    else:
      self.alignment="1" #left
    #print self.alignment

  def __setBackground(self,parent):
    pageElem=self.document.createElement("PAGE")

    elem=self.document.createElement("BACKTYPE")   #color
    elem.setAttribute("value", self.backtype)
    pageElem.appendChild(elem)

    elem=self.document.createElement("BACKVIEW")   #always zoomed
    elem.setAttribute("value", self.backview)
    pageElem.appendChild(elem)

    elem=self.document.createElement("BCTYPE")     #single color
    elem.setAttribute("value", self.bctype)
    pageElem.appendChild(elem)

    elem=self.document.createElement("BACKCOLOR1") #1st color
    elem.setAttribute("color", self.color1)
    pageElem.appendChild(elem)

    if (self.bctype!="0"):
      elem=self.document.createElement("BACKCOLOR2") #2nd color
      elem.setAttribute("color", self.color2)
      pageElem.appendChild(elem)

    parent.appendChild(pageElem)

  def __handlePage(self,parent,bgParent):
    if (self.pageCount!=-1):
      self.__setBackground(bgParent) #set the background for this page
      
    self.pageCount=self.pageCount+1
    objElem=self.document.createElement("OBJECT") #KPresenter text object
    objElem.setAttribute("type", "4")

    elem=self.document.createElement("ORIG") #object position
    elem.setAttribute("x", "30")
    elem.setAttribute("y", str(self.pageCount*Y_OFFSET+30))
    objElem.appendChild(elem)

    elem=self.document.createElement("SIZE") #object size
    elem.setAttribute("width", "610")
    elem.setAttribute("height", "440")
    objElem.appendChild(elem)

    self.textElem=self.document.createElement("TEXTOBJ") #text object
    ### para comes here
      
    objElem.appendChild(self.textElem)
    parent.appendChild(objElem)

    self.useDefaults=1
    self.__reset()

  def __handleText(self,line):
    indent=-1
    
    pElem=self.document.createElement("P")          #paragraph
    pElem.setAttribute("align", self.alignment) 

    elem=self.document.createElement("NAME")        #style name
    elem.setAttribute("value", "Standard")          ###is this needed at all?
    pElem.appendChild(elem)

    if (self.useDefaults==0):
      elem=self.document.createElement("LINESPACING") #linespacing
      elem.setAttribute("type", "custom")
      elem.setAttribute("spacingvalue", str(self.fontSize * self.vgap / 100.0))
      pElem.appendChild(elem)

    if (line.startswith('\t\t\t\t')):               #bullets
      indent=85
      type=8
    elif (line.startswith('\t\t\t')):
      indent=56.6
      type=11
    elif (line.startswith('\t\t')):
      indent=28.3
      type=9
    elif (line.startswith('\t')):
      indent=0
      type=10

    if not indent==-1:
      line=string.lstrip(line)
      
      elem=self.document.createElement("INDENTS")   #indentation (for bullet)
      elem.setAttribute("left", str(indent))
      pElem.appendChild(elem)

      elem=self.document.createElement("COUNTER")   #counter (for bullet)
      elem.setAttribute("numberingtype", "0")       #bullet numbering
      elem.setAttribute("type", str(type))          #bullet type
      #elem.setAttribute("depth", "0")               #???
      pElem.appendChild(elem)
      
    elem=self.document.createElement("TEXT")        #paragraph text
    #elem.setAttribute("VERTALIGN", "0")
    elem.setAttribute("family", self.fontName)
    elem.setAttribute("pointSize", str(self.fontSize))
    elem.setAttribute("color", self.textColor)

    if (self.fontBold!=0):
      elem.setAttribute("bold", "1")

    if (self.fontItalic!=0):
      elem.setAttribute("italic", "1")
    
    text=self.document.createTextNode(unicode(line, self.charset, 'ignore'))
    elem.appendChild(text)
    pElem.appendChild(elem)
    self.textElem.appendChild(pElem)
    
    #print "*** text: " + line

  def __setCharset(self,command):
    tokens=string.split(command,' ')
    self.charset=tokens[1].strip()

  def __setTextColor(self,command):
    tokens=string.split(command,' ')
    self.textColor=string.replace(tokens[1].strip(),'"', '') #strip quotes
    #print self.textColor

  def __handleBar(self,command):
    tokens=string.split(command,' ')

    try:
      color=string.replace(tokens[1].strip(),'"', '') #strip quotes and \n
      width=tokens[2].strip()/1000*Y_OFFSET           #in per mils of display height
      start=tokens[3].strip()/100*PAGE_WIDTH          #start position percent of display width
      length=tokens[4].strip()/100*PAGE_WIDTH         #length percent of display width
    except:                                           #default values
      color=self.textColor
      width=0.01*Y_OFFSET
      start=0
      length=PAGE_WIDTH
      

  def __setPaper(self,parent):
    paperElem=self.document.createElement("PAPER")
    paperElem.setAttribute("ptWidth", str(PAGE_WIDTH))
    paperElem.setAttribute("ptHeight", str(Y_OFFSET))
    paperElem.setAttribute("orientation", "0") #landscape
    paperElem.setAttribute("format", "5")      #screen
    paperElem.setAttribute("unit", "0")        #mm

    borderElem=self.document.createElement("PAPERBORDERS")
    borderElem.setAttribute("ptLeft","0")
    borderElem.setAttribute("ptRight","0")
    borderElem.setAttribute("ptTop","0")
    borderElem.setAttribute("ptBottom","0")

    paperElem.appendChild(borderElem)
    
    parent.appendChild(paperElem)

  def convert(self, fileIn, fileOut=None):
    """Parses the Magicpoint document and returns a KPresenter XML document.

    fileIn: path to the input file
    fileOut: path to the output file, or sys.stdout if omitted
    """
    doctype=implementation.createDocumentType("DOC", "-//KDE//DTD kpresenter 1.2//EN",
                                              "http://www.koffice.org/DTD/kpresenter-1.2.dtd")
    self.document=implementation.createDocument("http://www.koffice.org/DTD/kpresenter", "DOC", doctype)
    
    rootElem=self.document.documentElement                #the root "DOC" element
    rootElem.setAttribute("mime", "application/x-kpresenter")
    rootElem.setAttribute("syntaxVersion", "2")
    rootElem.setAttribute("editor", "mgp2kpr import filter, (c) Lukas Tinkl, 2002")
    
    self.__setPaper(rootElem)
    bgElem=self.document.createElement("BACKGROUND")
    objsElem=self.document.createElement("OBJECTS")

    self.textElem=self.document.createElement("TEXTOBJ")  #default text object
    
    for line in fileinput.input(fileIn):
      if (line.startswith('#') or line.startswith('%%')): #skip comments
          continue
      elif (line.startswith('%')):                        #commands
        commands=string.split(string.replace(line, '%', ''),',') #list of commands, comma separated, remove '%'
        for command in commands:
          command=command.strip().lower()
          #print command
          if (command.lower().startswith('page')):        #new page
            self.__handlePage(objsElem, bgElem)
          elif (command.startswith('bgrad')):             #background gradient
            self.__setBgGradient(command)
          elif (command.startswith('deffont')):           #default fonts
            self.__setupDefaultFonts(command)
          elif (command.startswith('default')):           #document defaults TODO!!!
            pass
          elif (command.startswith('xfont')):             #font
            self.__setFont(command)
          elif (command.startswith('font')):              #font from default fonts
            self.__setFontIndirect(command)
          elif (command.startswith('size')):              #font size
            self.__setFontSize(command)
          elif (command.startswith('left') or
                command.startswith('center') or
                command.startswith('right')):             #text alignment
            self.__setAlign(command)
          elif (command.startswith('charset')):           #charset
            self.__setCharset(command)
          elif (command.startswith('fore')):              #font color
            self.__setTextColor(command)
          elif (command.startswith('back')):              #background color
            self.__setBgColor(command)
          elif (command.startswith('bar')):               #horizontal line
            self.__handleBar(command)
          elif (command.startswith('vgap')):              #line spacing
            self.__setLineSpacing(command)
          elif (command.startswith('nodefault')):         #use default page values?
            self.useDefaults=0
          else:
            continue
      else:
        self.__handleText(line)                           #text

    self.__setBackground(bgElem)                          #flush the background

    rootElem.appendChild(bgElem)
    rootElem.appendChild(objsElem)
    self.document.appendChild(rootElem)

    if fileOut:
      PrettyPrint(self.document, open(fileOut[0], "w"))
    else:
      PrettyPrint(self.document, sys.stdout)

if __name__ == '__main__':
  if (len(sys.argv)==1 or len(sys.argv)>3):
    print """Magicpoint to KPresenter converter, (c) Lukas Tinkl <[email protected]>, 2002
    Usage: mgp2kpr infile.mgp [outfile.kpr]
    If you give only one parameter, it will output to stdout."""
  else:
    importer=MgpImporter()
    importer.convert(sys.argv[1], sys.argv[2:])