You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kpresenter/magicpoint/mgp2kpr.py

418 lines
14 KiB

#!/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 <lukas@kde.org>, 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(): #<23>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 <lukas@kde.org>, 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:])