initial commit
This commit is contained in:
commit
d421c1321b
580 files changed
+115527
No files matched your search
@@ -0,0 +1,158 @@
|
||||
class ViewKind :
|
||||
"""An integer (0-5) that represents the view mode of the document."""
|
||||
|
||||
NONE = 0
|
||||
PageLayout = 1
|
||||
Outline = 2
|
||||
MasterDocument = 3
|
||||
Normal = 4
|
||||
OnlineLayout = 5
|
||||
|
||||
DEFAULT = PageLayout
|
||||
|
||||
def _IsValid( cls, value ) :
|
||||
return value in [ 0, 1, 2, 3, 4, 5 ]
|
||||
IsValid = classmethod( _IsValid )
|
||||
|
||||
class ViewScale :
|
||||
"""Zoom level of the document; the N argument is a value representing a percentage (the default is 100)."""
|
||||
|
||||
def _IsValid( cls, value ) :
|
||||
return value is None or (0 < value < 101)
|
||||
IsValid = classmethod( _IsValid )
|
||||
|
||||
class ViewZoomKind :
|
||||
"""An integer (0 to 2) that represents the zoom kind of the document."""
|
||||
|
||||
NONE = 0
|
||||
FullPage = 1
|
||||
BestFit = 2
|
||||
|
||||
def _IsValid( cls, value ) :
|
||||
return value in [ None, 0, 1, 2 ]
|
||||
IsValid = classmethod( _IsValid )
|
||||
|
||||
|
||||
class Languages :
|
||||
NoLanguage = 1024
|
||||
Albanian = 1052
|
||||
Arabic = 1025
|
||||
Bahasa = 1057
|
||||
BelgianDutch = 2067
|
||||
BelgianFrench = 2060
|
||||
BrazilianPortuguese = 1046
|
||||
Bulgarian = 1026
|
||||
Catalan = 1027
|
||||
CroatoSerbianLatin = 1050
|
||||
Czech = 1029
|
||||
Danish = 1030
|
||||
Dutch = 1043
|
||||
EnglishAustralian = 3081
|
||||
EnglishUK = 2057
|
||||
EnglishUS = 1033
|
||||
Finnish = 1035
|
||||
French = 1036
|
||||
FrenchCanadian = 3084
|
||||
German = 1031
|
||||
Greek = 1032
|
||||
Hebrew = 1037
|
||||
Hungarian = 1038
|
||||
Icelandic = 1039
|
||||
Italian = 1040
|
||||
Japanese = 1041
|
||||
Korean = 1042
|
||||
NorwegianBokmal = 1044
|
||||
NorwegianNynorsk = 2068
|
||||
Polish = 1045
|
||||
Portuguese = 2070
|
||||
RhaetoRomanic = 1047
|
||||
Romanian = 1048
|
||||
Russian = 1049
|
||||
SerboCroatianCyrillic = 2074
|
||||
SimplifiedChinese = 2052
|
||||
Slovak = 1051
|
||||
SpanishCastilian = 1034
|
||||
SpanishMexican = 2058
|
||||
Swedish = 1053
|
||||
SwissFrench = 4108
|
||||
SwissGerman = 2055
|
||||
SwissItalian = 2064
|
||||
Thai = 1054
|
||||
TraditionalChinese = 1028
|
||||
Turkish = 1055
|
||||
Urdu = 1056
|
||||
SesothoSotho = 1072
|
||||
Afrikaans = 1078
|
||||
Zulu = 1077
|
||||
Xhosa = 1076
|
||||
Venda = 1075
|
||||
Tswana = 1074
|
||||
Tsonga = 1073
|
||||
FarsiPersian = 1065
|
||||
|
||||
Codes = [ 1024,
|
||||
1052,
|
||||
1025,
|
||||
1057,
|
||||
2067,
|
||||
2060,
|
||||
1046,
|
||||
1026,
|
||||
1027,
|
||||
1050,
|
||||
1029,
|
||||
1030,
|
||||
1043,
|
||||
3081,
|
||||
2057,
|
||||
1033,
|
||||
1035,
|
||||
1036,
|
||||
3084,
|
||||
1031,
|
||||
1032,
|
||||
1037,
|
||||
1038,
|
||||
1039,
|
||||
1040,
|
||||
1041,
|
||||
1042,
|
||||
1044,
|
||||
2068,
|
||||
1045,
|
||||
2070,
|
||||
1047,
|
||||
1048,
|
||||
1049,
|
||||
2074,
|
||||
2052,
|
||||
1051,
|
||||
1034,
|
||||
2058,
|
||||
1053,
|
||||
4108,
|
||||
2055,
|
||||
2064,
|
||||
1054,
|
||||
1028,
|
||||
1055,
|
||||
1056,
|
||||
1072,
|
||||
1078,
|
||||
1077,
|
||||
1076,
|
||||
1075,
|
||||
1074,
|
||||
1073,
|
||||
1065 ]
|
||||
|
||||
# make it Australian as that is what I use most of the time
|
||||
DEFAULT = EnglishAustralian
|
||||
|
||||
def _IsValid( cls, value ) :
|
||||
return value in cls.Codes
|
||||
IsValid = classmethod( _IsValid )
|
||||
|
||||
if __name__ == '__main__' :
|
||||
PrintHexTable()
|
||||
|
||||
@@ -0,0 +1,757 @@
|
||||
from types import IntType, FloatType, LongType, StringTypes
|
||||
from copy import deepcopy
|
||||
from binascii import hexlify
|
||||
|
||||
from Constants import *
|
||||
from Styles import *
|
||||
|
||||
class UnhandledParamError( Exception ) :
|
||||
def __init__( self, param ) :
|
||||
Exception.__init__( self, "Don't know what to do with param %s" % param )
|
||||
|
||||
# red green blue
|
||||
StandardColours = Colours()
|
||||
StandardColours.append( Colour( 'Black', 0, 0, 0 ) )
|
||||
StandardColours.append( Colour( 'Blue', 0, 0, 255 ) )
|
||||
StandardColours.append( Colour( 'Turquoise', 0, 255, 255 ) )
|
||||
StandardColours.append( Colour( 'Green', 0, 255, 0 ) )
|
||||
StandardColours.append( Colour( 'Pink', 255, 0, 255 ) )
|
||||
StandardColours.append( Colour( 'Red', 255, 0, 0 ) )
|
||||
StandardColours.append( Colour( 'Yellow', 255, 255, 0 ) )
|
||||
StandardColours.append( Colour( 'White', 255, 255, 255 ) )
|
||||
StandardColours.append( Colour( 'Blue Dark', 0, 0, 128 ) )
|
||||
StandardColours.append( Colour( 'Teal', 0, 128, 128 ) )
|
||||
StandardColours.append( Colour( 'Green Dark', 0, 128, 0 ) )
|
||||
StandardColours.append( Colour( 'Violet', 128, 0, 128 ) )
|
||||
StandardColours.append( Colour( 'Red Dark', 128, 0, 0 ) )
|
||||
StandardColours.append( Colour( 'Yellow Dark', 128, 128, 0 ) )
|
||||
StandardColours.append( Colour( 'Grey Dark', 128, 128, 128 ) )
|
||||
StandardColours.append( Colour( 'Grey', 192, 192, 192 ) )
|
||||
|
||||
StandardFonts = Fonts()
|
||||
StandardFonts.append( Font( 'Arial' , 'swiss' , 0, 2, '020b0604020202020204' ) )
|
||||
StandardFonts.append( Font( 'Arial Black' , 'swiss' , 0, 2, '020b0a04020102020204' ) )
|
||||
StandardFonts.append( Font( 'Arial Narrow' , 'swiss' , 0, 2, '020b0506020202030204' ) )
|
||||
StandardFonts.append( Font( 'Bitstream Vera Sans Mono', 'modern', 0, 1, '020b0609030804020204' ) )
|
||||
StandardFonts.append( Font( 'Bitstream Vera Sans' , 'swiss' , 0, 2, '020b0603030804020204' ) )
|
||||
StandardFonts.append( Font( 'Bitstream Vera Serif' , 'roman' , 0, 2, '02060603050605020204' ) )
|
||||
StandardFonts.append( Font( 'Book Antiqua' , 'roman' , 0, 2, '02040602050305030304' ) )
|
||||
StandardFonts.append( Font( 'Bookman Old Style' , 'roman' , 0, 2, '02050604050505020204' ) )
|
||||
StandardFonts.append( Font( 'Castellar' , 'roman' , 0, 2, '020a0402060406010301' ) )
|
||||
StandardFonts.append( Font( 'Century Gothic' , 'swiss' , 0, 2, '020b0502020202020204' ) )
|
||||
StandardFonts.append( Font( 'Comic Sans MS' , 'script', 0, 2, '030f0702030302020204' ) )
|
||||
StandardFonts.append( Font( 'Courier New' , 'modern', 0, 1, '02070309020205020404' ) )
|
||||
StandardFonts.append( Font( 'Franklin Gothic Medium' , 'swiss' , 0, 2, '020b0603020102020204' ) )
|
||||
StandardFonts.append( Font( 'Garamond' , 'roman' , 0, 2, '02020404030301010803' ) )
|
||||
StandardFonts.append( Font( 'Georgia' , 'roman' , 0, 2, '02040502050405020303' ) )
|
||||
StandardFonts.append( Font( 'Haettenschweiler' , 'swiss' , 0, 2, '020b0706040902060204' ) )
|
||||
StandardFonts.append( Font( 'Impact' , 'swiss' , 0, 2, '020b0806030902050204' ) )
|
||||
StandardFonts.append( Font( 'Lucida Console' , 'modern', 0, 1, '020b0609040504020204' ) )
|
||||
StandardFonts.append( Font( 'Lucida Sans Unicode' , 'swiss' , 0, 2, '020b0602030504020204' ) )
|
||||
StandardFonts.append( Font( 'Microsoft Sans Serif' , 'swiss' , 0, 2, '020b0604020202020204' ) )
|
||||
StandardFonts.append( Font( 'Monotype Corsiva' , 'script', 0, 2, '03010101010201010101' ) )
|
||||
StandardFonts.append( Font( 'Palatino Linotype' , 'roman' , 0, 2, '02040502050505030304' ) )
|
||||
StandardFonts.append( Font( 'Papyrus' , 'script', 0, 2, '03070502060502030205' ) )
|
||||
StandardFonts.append( Font( 'Sylfaen' , 'roman' , 0, 2, '010a0502050306030303' ) )
|
||||
StandardFonts.append( Font( 'Symbol' , 'roman' , 2, 2, '05050102010706020507' ) )
|
||||
StandardFonts.append( Font( 'Tahoma' , 'swiss' , 0, 2, '020b0604030504040204' ) )
|
||||
StandardFonts.append( Font( 'Times New Roman' , 'roman' , 0, 2, '02020603050405020304' ) )
|
||||
StandardFonts.append( Font( 'Trebuchet MS' , 'swiss' , 0, 2, '020b0603020202020204' ) )
|
||||
StandardFonts.append( Font( 'Verdana' , 'swiss' , 0, 2, '020b0604030504040204' ) )
|
||||
|
||||
StandardFonts.Castellar.SetAlternate( StandardFonts.Georgia )
|
||||
|
||||
"""
|
||||
Found the following definition at http://www.pbdr.com/vbtips/gen/convtwip.htm
|
||||
|
||||
Twips are screen-independent units used to ensure that the placement and
|
||||
proportion of screen elements in your screen application are the same on all
|
||||
display systems. A twip is a unit of screen measurement equal to 1/20 of a
|
||||
printer's point. The conversion between twips and
|
||||
inches/centimeters/millimeters is as follows:
|
||||
|
||||
There are approximately 1440 twips to a inch (the length of a screen item
|
||||
measuring one inch when printed).
|
||||
|
||||
As there are 2.54 centimeters to 1 inch, then there are approximately 567
|
||||
twips to a centimeter (the length of a screen item measuring one centimeter
|
||||
when printed).
|
||||
|
||||
Or in millimeters, as there are 25.4 millimeters to 1 inch, therefore there
|
||||
are approximately 56.7 twips to a millimeter (the length of a screen item
|
||||
measuring one millimeter when printed)."""
|
||||
|
||||
# Width default is 12240, Height default is 15840
|
||||
StandardPaper = Papers()
|
||||
StandardPaper.append( Paper( 'LETTER' , 1, 'Letter 8 1/2 x 11 in' , 12240, 15840 ) )
|
||||
StandardPaper.append( Paper( 'LETTERSMALL' , 2, 'Letter Small 8 1/2 x 11 in' , 12240, 15840 ) )
|
||||
StandardPaper.append( Paper( 'TABLOID' , 3, 'Tabloid 11 x 17 in' , 15840, 24480 ) )
|
||||
StandardPaper.append( Paper( 'LEDGER' , 4, 'Ledger 17 x 11 in' , 24480, 15840 ) )
|
||||
StandardPaper.append( Paper( 'LEGAL' , 5, 'Legal 8 1/2 x 14 in' , 12240, 20160 ) )
|
||||
StandardPaper.append( Paper( 'STATEMENT' , 6, 'Statement 5 1/2 x 8 1/2 in' , 7920, 12240 ) )
|
||||
StandardPaper.append( Paper( 'EXECUTIVE' , 7, 'Executive 7 1/4 x 10 1/2 in' , 10440, 15120 ) )
|
||||
StandardPaper.append( Paper( 'A3' , 8, 'A3 297 x 420 mm' , 16838, 23811 ) )
|
||||
StandardPaper.append( Paper( 'A4' , 9, 'A4 210 x 297 mm' , 11907, 16838 ) )
|
||||
StandardPaper.append( Paper( 'A4SMALL' , 10, 'A4 Small 210 x 297 mm' , 11907, 16838 ) )
|
||||
StandardPaper.append( Paper( 'A5' , 11, 'A5 148 x 210 mm' , 8391, 11907 ) )
|
||||
StandardPaper.append( Paper( 'B4' , 12, 'B4 (JIS) 250 x 354' , 14175, 20072 ) )
|
||||
StandardPaper.append( Paper( 'B5' , 13, 'B5 (JIS) 182 x 257 mm' , 10319, 14572 ) )
|
||||
StandardPaper.append( Paper( 'FOLIO' , 14, 'Folio 8 1/2 x 13 in' , 12240, 18720 ) )
|
||||
StandardPaper.append( Paper( 'QUARTO' , 15, 'Quarto 215 x 275 mm' , 12191, 15593 ) )
|
||||
StandardPaper.append( Paper( '10X14' , 16, '10x14 in' , 14400, 20160 ) )
|
||||
StandardPaper.append( Paper( '11X17' , 17, '11x17 in' , 15840, 24480 ) )
|
||||
StandardPaper.append( Paper( 'NOTE' , 18, 'Note 8 1/2 x 11 in' , 12240, 15840 ) )
|
||||
StandardPaper.append( Paper( 'ENV_9' , 19, 'Envelope #9 3 7/8 x 8 7/8' , 5580, 12780 ) )
|
||||
StandardPaper.append( Paper( 'ENV_10' , 20, 'Envelope #10 4 1/8 x 9 1/2' , 5940, 13680 ) )
|
||||
StandardPaper.append( Paper( 'ENV_11' , 21, 'Envelope #11 4 1/2 x 10 3/8' , 6480, 14940 ) )
|
||||
StandardPaper.append( Paper( 'ENV_12' , 22, 'Envelope #12 4 3/4 x 11' , 6840, 15840 ) )
|
||||
StandardPaper.append( Paper( 'ENV_14' , 23, 'Envelope #14 5 x 11 1/2' , 7200, 16560 ) )
|
||||
StandardPaper.append( Paper( 'CSHEET' , 24, 'C size sheet 18 x 24 in' , 29520, 34560 ) )
|
||||
StandardPaper.append( Paper( 'DSHEET' , 25, 'D size sheet 22 x 34 in' , 31680, 48960 ) )
|
||||
StandardPaper.append( Paper( 'ESHEET' , 26, 'E size sheet 34 x 44 in' , 48960, 63360 ) )
|
||||
StandardPaper.append( Paper( 'ENV_DL' , 27, 'Envelope DL 110 x 220mm' , 6237, 12474 ) )
|
||||
StandardPaper.append( Paper( 'ENV_C5' , 28, 'Envelope C5 162 x 229 mm' , 9185, 12984 ) )
|
||||
StandardPaper.append( Paper( 'ENV_C3' , 29, 'Envelope C3 324 x 458 mm' , 18371, 25969 ) )
|
||||
StandardPaper.append( Paper( 'ENV_C4' , 30, 'Envelope C4 229 x 324 mm' , 12984, 18371 ) )
|
||||
StandardPaper.append( Paper( 'ENV_C6' , 31, 'Envelope C6 114 x 162 mm' , 6464, 9185 ) )
|
||||
StandardPaper.append( Paper( 'ENV_C65' , 32, 'Envelope C65 114 x 229 mm' , 6464, 12984 ) )
|
||||
StandardPaper.append( Paper( 'ENV_B4' , 33, 'Envelope B4 250 x 353 mm' , 14175, 20015 ) )
|
||||
StandardPaper.append( Paper( 'ENV_B5' , 34, 'Envelope B5 176 x 250 mm' , 9979, 14175 ) )
|
||||
StandardPaper.append( Paper( 'ENV_B6' , 35, 'Envelope B6 176 x 125 mm' , 9979, 7088 ) )
|
||||
StandardPaper.append( Paper( 'ENV_ITALY' , 36, 'Envelope 110 x 230 mm' , 6237, 13041 ) )
|
||||
StandardPaper.append( Paper( 'ENV_MONARCH' , 37, 'Envelope Monarch 3.875 x 7.5 in' , 5580, 10800 ) )
|
||||
StandardPaper.append( Paper( 'ENV_PERSONAL' , 38, '6 3/4 Envelope 3 5/8 x 6 1/2 in' , 5220, 9360 ) )
|
||||
StandardPaper.append( Paper( 'FANFOLD_US' , 39, 'US Std Fanfold 14 7/8 x 11 in' , 21420, 15840 ) )
|
||||
StandardPaper.append( Paper( 'FANFOLD_STD_GERMAN' , 40, 'German Std Fanfold 8 1/2 x 12 in' , 12240, 17280 ) )
|
||||
StandardPaper.append( Paper( 'FANFOLD_LGL_GERMAN' , 41, 'German Legal Fanfold 8 1/2 x 13 in' , 12240, 18720 ) )
|
||||
|
||||
#
|
||||
# Finally a StyleSheet in which all of this stuff is put together
|
||||
#
|
||||
class StyleSheet :
|
||||
def __init__( self, colours=None, fonts=None ) :
|
||||
|
||||
self.Colours = colours or deepcopy( StandardColours )
|
||||
self.Fonts = fonts or deepcopy( StandardFonts )
|
||||
|
||||
self.TextStyles = AttributedList()
|
||||
self.ParagraphStyles = AttributedList()
|
||||
|
||||
class Section( list ) :
|
||||
NONE = 1
|
||||
COLUMN = 2
|
||||
PAGE = 3
|
||||
EVEN = 4
|
||||
ODD = 5
|
||||
BREAK_TYPES = [ NONE, COLUMN, PAGE, EVEN, ODD ]
|
||||
|
||||
def __init__( self, paper=None, margins=None, break_type=None, headery=None, footery=None, landscape=None, first_page_number=None ) :
|
||||
super( Section, self ).__init__()
|
||||
|
||||
self.Paper = paper or StandardPaper.A4
|
||||
self.SetMargins( margins )
|
||||
|
||||
self.Header = []
|
||||
self.Footer = []
|
||||
self.FirstHeader = []
|
||||
self.FirstFooter = []
|
||||
|
||||
self.SetBreakType( break_type or self.NONE )
|
||||
self.SetHeaderY( headery )
|
||||
self.SetFooterY( footery )
|
||||
self.SetLandscape( landscape )
|
||||
self.SetFirstPageNumber( first_page_number )
|
||||
|
||||
def TwipsToRightMargin( self ) :
|
||||
return self.Paper.Width - ( self.Margins.Left + self.Margins.Right )
|
||||
|
||||
def SetMargins( self, value ) :
|
||||
self.Margins = value or MarginsPropertySet( top=1000, left=1200, bottom=1000, right=1200 )
|
||||
self.Width = self.Paper.Width - ( self.Margins.Left + self.Margins.Right )
|
||||
|
||||
def SetBreakType( self, value ) :
|
||||
assert value in self.BREAK_TYPES
|
||||
self.BreakType = value
|
||||
return self
|
||||
|
||||
def SetHeaderY( self, value ) :
|
||||
self.HeaderY = value
|
||||
return self
|
||||
|
||||
def SetFooterY( self, value ) :
|
||||
self.FooterY = value
|
||||
return self
|
||||
|
||||
def SetLandscape( self, value ) :
|
||||
self.Landscape = False
|
||||
if value : self.Landscape = True
|
||||
return self
|
||||
|
||||
def SetFirstPageNumber( self, value ) :
|
||||
self.FirstPageNumber = value
|
||||
return self
|
||||
|
||||
def MakeDefaultStyleSheet( ) :
|
||||
result = StyleSheet()
|
||||
|
||||
NormalText = TextStyle( TextPropertySet( result.Fonts.Arial, 22 ) )
|
||||
|
||||
ps = ParagraphStyle( 'Normal',
|
||||
NormalText.Copy(),
|
||||
ParagraphPropertySet( space_before = 60,
|
||||
space_after = 60 ) )
|
||||
result.ParagraphStyles.append( ps )
|
||||
|
||||
ps = ParagraphStyle( 'Normal Short',
|
||||
NormalText.Copy() )
|
||||
result.ParagraphStyles.append( ps )
|
||||
|
||||
NormalText.TextPropertySet.SetSize( 32 )
|
||||
ps = ParagraphStyle( 'Heading 1',
|
||||
NormalText.Copy(),
|
||||
ParagraphPropertySet( space_before = 240,
|
||||
space_after = 60 ) )
|
||||
result.ParagraphStyles.append( ps )
|
||||
|
||||
NormalText.TextPropertySet.SetSize( 24 ).SetBold( True )
|
||||
ps = ParagraphStyle( 'Heading 2',
|
||||
NormalText.Copy(),
|
||||
ParagraphPropertySet( space_before = 240,
|
||||
space_after = 60 ) )
|
||||
result.ParagraphStyles.append( ps )
|
||||
|
||||
# Add some more in that are based on the normal template but that
|
||||
# have some indenting set that makes them suitable for doing numbered
|
||||
normal_numbered = result.ParagraphStyles.Normal.Copy()
|
||||
normal_numbered.SetName( 'Normal Numbered' )
|
||||
normal_numbered.ParagraphPropertySet.SetFirstLineIndent( TabPropertySet.DEFAULT_WIDTH * -1 )
|
||||
normal_numbered.ParagraphPropertySet.SetLeftIndent ( TabPropertySet.DEFAULT_WIDTH )
|
||||
|
||||
result.ParagraphStyles.append( normal_numbered )
|
||||
|
||||
normal_numbered2 = result.ParagraphStyles.Normal.Copy()
|
||||
normal_numbered2.SetName( 'Normal Numbered 2' )
|
||||
normal_numbered2.ParagraphPropertySet.SetFirstLineIndent( TabPropertySet.DEFAULT_WIDTH * -1 )
|
||||
normal_numbered2.ParagraphPropertySet.SetLeftIndent ( TabPropertySet.DEFAULT_WIDTH * 2 )
|
||||
|
||||
result.ParagraphStyles.append( normal_numbered2 )
|
||||
|
||||
## LIST STYLES
|
||||
for idx, indent in [ (1, TabPS.DEFAULT_WIDTH ),
|
||||
(2, TabPS.DEFAULT_WIDTH * 2),
|
||||
(3, TabPS.DEFAULT_WIDTH * 3) ] :
|
||||
indent = TabPropertySet.DEFAULT_WIDTH
|
||||
ps = ParagraphStyle( 'List %s' % idx,
|
||||
TextStyle( TextPropertySet( result.Fonts.Arial, 22 ) ),
|
||||
ParagraphPropertySet( space_before = 60,
|
||||
space_after = 60,
|
||||
first_line_indent = -indent,
|
||||
left_indent = indent) )
|
||||
result.ParagraphStyles.append( ps )
|
||||
|
||||
return result
|
||||
|
||||
class TAB : pass
|
||||
class LINE : pass
|
||||
|
||||
class RawCode :
|
||||
def __init__( self, data ) :
|
||||
self.Data = data
|
||||
|
||||
PAGE_NUMBER = RawCode( r'{\field{\fldinst page}}' )
|
||||
TOTAL_PAGES = RawCode( r'{\field{\fldinst numpages}}' )
|
||||
SECTION_PAGES = RawCode( r'{\field{\fldinst sectionpages}}' )
|
||||
ARIAL_BULLET = RawCode( r'{\f2\'95}' )
|
||||
|
||||
def _get_jpg_dimensions( fin ):
|
||||
"""
|
||||
converted from: http://dev.w3.org/cvsweb/Amaya/libjpeg/rdjpgcom.c?rev=1.2
|
||||
"""
|
||||
|
||||
M_SOF0 = chr( 0xC0 ) # /* Start Of Frame N */
|
||||
M_SOF1 = chr( 0xC1 ) # /* N indicates which compression process */
|
||||
M_SOF2 = chr( 0xC2 ) # /* Only SOF0-SOF2 are now in common use */
|
||||
M_SOF3 = chr( 0xC3 ) #
|
||||
M_SOF5 = chr( 0xC5 ) # /* NB: codes C4 and CC are NOT SOF markers */
|
||||
M_SOF6 = chr( 0xC6 ) #
|
||||
M_SOF7 = chr( 0xC7 ) #
|
||||
M_SOF9 = chr( 0xC9 ) #
|
||||
M_SOF10 = chr( 0xCA ) #
|
||||
M_SOF11 = chr( 0xCB ) #
|
||||
M_SOF13 = chr( 0xCD ) #
|
||||
M_SOF14 = chr( 0xCE ) #
|
||||
M_SOF15 = chr( 0xCF ) #
|
||||
M_SOI = chr( 0xD8 ) # /* Start Of Image (beginning of datastream) */
|
||||
M_EOI = chr( 0xD9 ) # /* End Of Image (end of datastream) */
|
||||
|
||||
M_FF = chr( 0xFF )
|
||||
|
||||
MARKERS = [ M_SOF0, M_SOF1, M_SOF2, M_SOF3,
|
||||
M_SOF5, M_SOF6, M_SOF7, M_SOF9,
|
||||
M_SOF10,M_SOF11, M_SOF13, M_SOF14,
|
||||
M_SOF15 ]
|
||||
|
||||
def get_length() :
|
||||
b1 = fin.read( 1 )
|
||||
b2 = fin.read( 1 )
|
||||
return (ord(b1) << 8) + ord(b2)
|
||||
|
||||
def next_marker() :
|
||||
# markers come straight after an 0xFF so skip everything
|
||||
# up to the first 0xFF that we find
|
||||
while fin.read(1) != M_FF :
|
||||
pass
|
||||
|
||||
# there can be more than one 0xFF as they can be used
|
||||
# for padding so we are now looking for the first byte
|
||||
# that isn't an 0xFF, this will be the marker
|
||||
while True :
|
||||
result = fin.read(1)
|
||||
if result != M_FF :
|
||||
return result
|
||||
|
||||
raise Exception( 'Invalid JPEG' )
|
||||
|
||||
# BODY OF THE FUNCTION
|
||||
if not ((fin.read(1) == M_FF) and (fin.read(1) == M_SOI)) :
|
||||
raise Exception( 'Invalid Jpeg' )
|
||||
|
||||
while True :
|
||||
marker = next_marker()
|
||||
|
||||
# the marker is always followed by two bytes representing the length of the data field
|
||||
length = get_length ()
|
||||
if length < 2 : raise Exception( "Erroneous JPEG marker length" )
|
||||
|
||||
# if it is a compression process marker then it will contain the dimension of the image
|
||||
if marker in MARKERS :
|
||||
# the next byte is the data precision, just skip it
|
||||
fin.read(1)
|
||||
|
||||
# bingo
|
||||
image_height = get_length()
|
||||
image_width = get_length()
|
||||
return image_width, image_height
|
||||
|
||||
# just skip whatever data it contains
|
||||
fin.read( length - 2 )
|
||||
|
||||
raise Exception( 'Invalid JPEG, end of stream reached' )
|
||||
|
||||
|
||||
_PNG_HEADER = '\x89\x50\x4e'
|
||||
def _get_png_dimensions( data ) :
|
||||
if data[0:3] != _PNG_HEADER :
|
||||
raise Exception( 'Invalid PNG image' )
|
||||
|
||||
width = (ord(data[18]) * 256) + (ord(data[19]))
|
||||
height = (ord(data[22]) * 256) + (ord(data[23]))
|
||||
return width, height
|
||||
|
||||
def _get_emf_dimensions( fin ):
|
||||
import struct
|
||||
def get_DWORD():
|
||||
return struct.unpack("<L",fin.read(4))[0]
|
||||
def get_LONG():
|
||||
return struct.unpack("<l",fin.read(4))[0]
|
||||
def get_WORD():
|
||||
return struct.unpack("<H",fin.read(2))[0]
|
||||
class Empty:
|
||||
pass
|
||||
header = Empty()
|
||||
header.RecordType = get_DWORD() # Record type
|
||||
header.RecordSize = get_DWORD() # Size of the record in bytes
|
||||
header.BoundsLeft = get_LONG() # Left inclusive bounds
|
||||
header.BoundsTop = get_LONG() # Top inclusive bounds
|
||||
header.BoundsRight = get_LONG() # Right inclusive bounds
|
||||
header.BoundsBottom = get_LONG() # Bottom inclusive bounds
|
||||
header.FrameLeft = get_LONG() # Left side of inclusive picture frame
|
||||
header.FrameTop = get_LONG() # Top side of inclusive picture frame
|
||||
header.FrameRight = get_LONG() # Right side of inclusive picture frame
|
||||
header.FrameBottom = get_LONG() # Bottom side of inclusive picture frame
|
||||
header.Signature = get_DWORD() # Signature ID (always 0x464D4520)
|
||||
header.Version = get_DWORD() # Version of the metafile
|
||||
header.Size = get_DWORD() # Size of the metafile in bytes
|
||||
header.NumOfRecords = get_DWORD() # Number of records in the metafile
|
||||
header.NumOfHandles = get_WORD() # Number of handles in the handle table
|
||||
header.Reserved = get_WORD() # Not used (always 0)
|
||||
header.SizeOfDescrip = get_DWORD() # Size of description string in WORDs
|
||||
header.OffsOfDescrip = get_DWORD() # Offset of description string in metafile
|
||||
header.NumPalEntries = get_DWORD() # Number of color palette entries
|
||||
header.WidthDevPixels = get_LONG() # Width of reference device in pixels
|
||||
header.HeightDevPixels = get_LONG() # Height of reference device in pixels
|
||||
header.WidthDevMM = get_LONG() # Width of reference device in millimeters
|
||||
header.HeightDevMM = get_LONG() # Height of reference device in millimeters
|
||||
|
||||
if 0:
|
||||
klist = header.__dict__.keys()
|
||||
klist.sort()
|
||||
for k in klist:
|
||||
print "%20s:%s" % (k,header.__dict__[k])
|
||||
|
||||
dw = header.FrameRight-header.FrameLeft
|
||||
dh = header.FrameBottom-header.FrameTop
|
||||
|
||||
# convert from 0.01mm units to 1/72in units
|
||||
return int(dw * 72.0/2540.0), int(dh * 72.0/2540.0)
|
||||
|
||||
class Image( RawCode ) :
|
||||
|
||||
# Need to add in the width and height in twips as it crashes
|
||||
# word xp with these values. Still working out the most
|
||||
# efficient way of getting these values.
|
||||
# \picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0
|
||||
# picwgoal900\pichgoal281
|
||||
|
||||
PNG_LIB = 'pngblip'
|
||||
JPG_LIB = 'jpegblip'
|
||||
EMF_LIB = 'emfblip'
|
||||
PICT_TYPES = { 'png' : PNG_LIB,
|
||||
'jpg' : JPG_LIB,
|
||||
'emf' : EMF_LIB}
|
||||
|
||||
def __init__( self, infile, **kwargs ) :
|
||||
|
||||
if hasattr( infile, 'read' ):
|
||||
fin = infile
|
||||
if 'datatype' not in kwargs.keys():
|
||||
msg = "If passing in a file object, you must also specify type='xxx' where xxx is one of %s" % self.PICT_TYPES.keys()
|
||||
raise ValueError,msg
|
||||
file_name = kwargs.pop('datatype')
|
||||
else:
|
||||
fin = file( infile, 'rb' )
|
||||
file_name = infile
|
||||
|
||||
pict_type = self.PICT_TYPES[ file_name[ -3 : ].lower() ]
|
||||
if pict_type == self.PNG_LIB :
|
||||
width, height = _get_png_dimensions( fin.read( 100 ) )
|
||||
elif pict_type == self.JPG_LIB :
|
||||
width, height = _get_jpg_dimensions( fin )
|
||||
elif pict_type == self.EMF_LIB :
|
||||
width, height = _get_emf_dimensions( fin )
|
||||
|
||||
|
||||
# if user specified height or width but not both, then
|
||||
# scale unspecified dimension to maintain aspect ratio
|
||||
|
||||
if ('width' in kwargs) and ('height' not in kwargs):
|
||||
height = int(height * float(kwargs['width'])/width)
|
||||
elif ('height' in kwargs) and ('width' not in kwargs):
|
||||
width = int(width * float(kwargs['height'])/height)
|
||||
|
||||
width = kwargs.pop('width',width)
|
||||
height = kwargs.pop('height', height)
|
||||
|
||||
codes = [ pict_type,
|
||||
'picwgoal%s' % (width * 20),
|
||||
'pichgoal%s' % (height * 20) ]
|
||||
# let user specify global scaling
|
||||
scale = kwargs.pop('scale',100)
|
||||
|
||||
for kwarg, code, default in [ ( 'scale_x', 'scalex', scale ),
|
||||
( 'scale_y', 'scaley', scale ),
|
||||
( 'crop_left', 'cropl', '0' ),
|
||||
( 'crop_right', 'cropr', '0' ),
|
||||
( 'crop_top', 'cropt', '0' ),
|
||||
( 'crop_bottom', 'cropb', '0' ) ] :
|
||||
codes.append( 'pic%s%s' % ( code, kwargs.pop( kwarg, default ) ) )
|
||||
|
||||
|
||||
# reset back to the start of the file to get all of it and now
|
||||
# turn it into hex.
|
||||
fin.seek( 0, 0 )
|
||||
image = hexlify( fin.read() )
|
||||
fin.close()
|
||||
data = []
|
||||
for i in range( 0, len( image ), 128 ) :
|
||||
data.append( image[ i : i + 128 ] )
|
||||
|
||||
data = r'{\pict{\%s}%s}' % ( '\\'.join( codes ), '\n'.join( data ) )
|
||||
RawCode.__init__( self, data )
|
||||
|
||||
def ToRawCode( self, var_name ) :
|
||||
return '%s = RawCode( """%s""" )' % ( var_name, self.Data )
|
||||
|
||||
class Text :
|
||||
def __init__( self, *params ) :
|
||||
self.Data = None
|
||||
self.Style = None
|
||||
self.Properties = None
|
||||
self.Shading = None
|
||||
|
||||
for param in params :
|
||||
if isinstance( param, TextStyle ) : self.Style = param
|
||||
elif isinstance( param, TextPS ) : self.Properties = param
|
||||
elif isinstance( param, ShadingPS ) : self.Shading = param
|
||||
else :
|
||||
# otherwise let the rendering custom handler sort it out itself
|
||||
self.Data = param
|
||||
|
||||
def SetData( self, value ) :
|
||||
self.Data = value
|
||||
|
||||
class Inline( list ) :
|
||||
def __init__( self, *params ) :
|
||||
super( Inline, self ).__init__()
|
||||
|
||||
self.Style = None
|
||||
self.Properties = None
|
||||
self.Shading = None
|
||||
|
||||
self._append = super( Inline, self ).append
|
||||
|
||||
for param in params :
|
||||
if isinstance( param, TextStyle ) : self.Style = param
|
||||
elif isinstance( param, TextPS ) : self.Properties = param
|
||||
elif isinstance( param, ShadingPS ) : self.Shading = param
|
||||
else :
|
||||
# otherwise we add to it to our list of elements and let
|
||||
# the rendering custom handler sort it out itself.
|
||||
self.append( param )
|
||||
|
||||
def append( self, *params ) :
|
||||
# filter out any that are explicitly None
|
||||
[ self._append( param ) for param in params if param is not None ]
|
||||
|
||||
class Paragraph( list ) :
|
||||
def __init__( self, *params ) :
|
||||
super( Paragraph, self ).__init__()
|
||||
|
||||
self.Style = None
|
||||
self.Properties = None
|
||||
self.Frame = None
|
||||
self.Shading = None
|
||||
|
||||
self._append = super( Paragraph, self ).append
|
||||
|
||||
for param in params :
|
||||
if isinstance( param, ParagraphStyle ) : self.Style = param
|
||||
elif isinstance( param, ParagraphPS ) : self.Properties = param
|
||||
elif isinstance( param, FramePS ) : self.Frame = param
|
||||
elif isinstance( param, ShadingPS ) : self.Shading = param
|
||||
else :
|
||||
# otherwise we add to it to our list of elements and let
|
||||
# the rendering custom handler sort it out itself.
|
||||
self.append( param )
|
||||
|
||||
def append( self, *params ) :
|
||||
# filter out any that are explicitly None
|
||||
[ self._append( param ) for param in params if param is not None ]
|
||||
|
||||
def insert( self, index, value ) :
|
||||
if value is not None :
|
||||
super( Paragraph, self ).insert( index, value )
|
||||
|
||||
class Table :
|
||||
LEFT = 1
|
||||
RIGHT = 2
|
||||
CENTER = 3
|
||||
ALIGNMENT = [ LEFT, RIGHT, CENTER ]
|
||||
|
||||
NO_WRAPPING = 1
|
||||
WRAP_AROUND = 2
|
||||
WRAPPING = [ NO_WRAPPING, WRAP_AROUND ]
|
||||
|
||||
# trrh height of row, 0 means automatically adjust, use negative for an absolute
|
||||
# trgaph is half of the space between a table cell in width, reduce this one
|
||||
# to get a really tiny column
|
||||
|
||||
def __init__( self, *column_widths, **kwargs ) :
|
||||
|
||||
self.Rows = []
|
||||
|
||||
self.SetAlignment ( kwargs.pop( 'alignment', self.LEFT ) )
|
||||
self.SetLeftOffset ( kwargs.pop( 'left_offset', None ) )
|
||||
self.SetGapBetweenCells( kwargs.pop( 'gap_between_cells', None ) )
|
||||
self.SetColumnWidths ( *column_widths )
|
||||
|
||||
assert not kwargs, 'invalid keyword args %s' % kwargs
|
||||
|
||||
def SetAlignment( self, value ) :
|
||||
assert value is None or value in self.ALIGNMENT
|
||||
self.Alignment = value or self.LEFT
|
||||
return self
|
||||
|
||||
def SetLeftOffset( self, value ) :
|
||||
self.LeftOffset = value
|
||||
return self
|
||||
|
||||
def SetGapBetweenCells( self, value ) :
|
||||
self.GapBetweenCells = value
|
||||
return self
|
||||
|
||||
def SetColumnWidths( self, *column_widths ) :
|
||||
self.ColumnWidths = column_widths
|
||||
self.ColumnCount = len( column_widths )
|
||||
return self
|
||||
|
||||
def AddRow( self, *cells ) :
|
||||
height = None
|
||||
if isinstance( cells[ 0 ], (IntType, FloatType, LongType) ):
|
||||
height = int( cells[ 0 ] )
|
||||
cells = cells[ 1 : ]
|
||||
|
||||
# make sure all of the spans add up to the number of columns
|
||||
# otherwise the table will get corrupted
|
||||
if self.ColumnCount != sum( [ cell.Span for cell in cells ] ) :
|
||||
raise Exception( 'ColumnCount != the total of this row\'s cell.Spans.' )
|
||||
|
||||
self.Rows.append( ( height, cells ) )
|
||||
|
||||
append = AddRow
|
||||
|
||||
class Cell( list ) :
|
||||
|
||||
"""
|
||||
\clvertalt Text is top-aligned in cell (the default).
|
||||
\clvertalc Text is centered vertically in cell.
|
||||
\clvertalb Text is bottom-aligned in cell.
|
||||
\cltxlrtb Vertical text aligned left (direction bottom up).
|
||||
\cltxtbrl Vertical text aligned right (direction top down).
|
||||
"""
|
||||
|
||||
ALIGN_TOP = 1
|
||||
ALIGN_CENTER = 2
|
||||
ALIGN_BOTTOM = 3
|
||||
|
||||
FLOW_LR_TB = 1
|
||||
FLOW_RL_TB = 2
|
||||
FLOW_LR_BT = 3
|
||||
FLOW_VERTICAL_LR_TB = 4
|
||||
FLOW_VERTICAL_TB_RL = 5
|
||||
|
||||
def __init__( self, *params, **kwargs ) :
|
||||
super( Cell, self ).__init__()
|
||||
|
||||
self.SetFrame ( None )
|
||||
self.SetMargins( None )
|
||||
|
||||
self.SetAlignment( kwargs.get( 'alignment', self.ALIGN_TOP ) )
|
||||
self.SetFlow ( kwargs.get( 'flow' , self.FLOW_LR_TB ) )
|
||||
self.SetSpan ( kwargs.get( 'span', 1 ) )
|
||||
|
||||
self.SetStartVerticalMerge( kwargs.get( 'start_vertical_merge', False ) )
|
||||
self.SetVerticalMerge ( kwargs.get( 'vertical_merge', False ) )
|
||||
|
||||
self._append = super( Cell, self ).append
|
||||
|
||||
for param in params :
|
||||
if isinstance( param, StringType ) : self.append ( param )
|
||||
elif isinstance( param, Paragraph ) : self.append ( param )
|
||||
elif isinstance( param, FramePS ) : self.SetFrame ( param )
|
||||
elif isinstance( param, MarginsPS ) : self.SetMargins( param )
|
||||
|
||||
def SetFrame( self, value ) :
|
||||
self.Frame = value
|
||||
return self
|
||||
|
||||
def SetMargins( self, value ) :
|
||||
self.Margins = value
|
||||
return self
|
||||
|
||||
def SetAlignment( self, value ) :
|
||||
assert value in [ self.ALIGN_TOP, self.ALIGN_CENTER, self.ALIGN_BOTTOM ] #, self.ALIGN_TEXT_TOP_DOWN, self.ALIGN_TEXT_BOTTOM_UP ]
|
||||
self.Alignment = value
|
||||
|
||||
def SetFlow( self, value ) :
|
||||
assert value in [ self.FLOW_LR_TB, self.FLOW_RL_TB, self.FLOW_LR_BT, self.FLOW_VERTICAL_LR_TB, self.FLOW_VERTICAL_TB_RL ]
|
||||
self.Flow = value
|
||||
|
||||
def SetSpan( self, value ) :
|
||||
# must be a positive integer
|
||||
self.Span = int( max( value, 1 ) )
|
||||
return self
|
||||
|
||||
def SetStartVerticalMerge( self, value ) :
|
||||
self.StartVerticalMerge = False
|
||||
if value :
|
||||
self.StartVerticalMerge = True
|
||||
return self
|
||||
|
||||
def SetVerticalMerge( self, value ) :
|
||||
self.VerticalMerge = False
|
||||
if value :
|
||||
self.VerticalMerge = True
|
||||
return self
|
||||
|
||||
def append( self, *params ) :
|
||||
[ self._append( param ) for param in params ]
|
||||
|
||||
class Document :
|
||||
def __init__( self, style_sheet=None, default_language=None, view_kind=None, view_zoom_kind=None, view_scale=None ) :
|
||||
self.StyleSheet = style_sheet or MakeDefaultStyleSheet()
|
||||
self.Sections = AttributedList( Section )
|
||||
|
||||
self.SetTitle( None )
|
||||
|
||||
self.DefaultLanguage = default_language or Languages.DEFAULT
|
||||
self.ViewKind = view_kind or ViewKind.DEFAULT
|
||||
self.ViewZoomKind = view_zoom_kind
|
||||
self.ViewScale = view_scale
|
||||
|
||||
def NewSection( self, *params, **kwargs ) :
|
||||
result = Section( *params, **kwargs )
|
||||
self.Sections.append( result )
|
||||
return result
|
||||
|
||||
def SetTitle( self, value ) :
|
||||
self.Title = value
|
||||
return self
|
||||
|
||||
def Copy( self ) :
|
||||
result = Document( style_sheet = self.StyleSheet.Copy(),
|
||||
default_language = self.DefaultLanguage,
|
||||
view_kind = self.ViewKind,
|
||||
view_zoom_kind = self.ViewZoomKind,
|
||||
view_scale = self.ViewScale )
|
||||
result.SetTitle( self.Title )
|
||||
result.Sections = self.Sections.Copy()
|
||||
|
||||
return result
|
||||
|
||||
def TEXT( *params, **kwargs ) :
|
||||
text_props = TextPropertySet()
|
||||
text_props.SetFont ( kwargs.get( 'font', None ) )
|
||||
text_props.SetSize ( kwargs.get( 'size', None ) )
|
||||
text_props.SetBold ( kwargs.get( 'bold', False ) )
|
||||
text_props.SetItalic ( kwargs.get( 'italic', False ) )
|
||||
text_props.SetUnderline( kwargs.get( 'underline', False ) )
|
||||
text_props.SetColour ( kwargs.get( 'colour', None ) )
|
||||
|
||||
if len( params ) == 1 :
|
||||
return Text( params[ 0 ], text_props )
|
||||
|
||||
result = Inline( text_props )
|
||||
apply( result.append, params )
|
||||
return result
|
||||
|
||||
def B( *params ) :
|
||||
text_props = TextPropertySet( bold=True )
|
||||
|
||||
if len( params ) == 1 :
|
||||
return Text( params[ 0 ], text_props )
|
||||
|
||||
result = Inline( text_props )
|
||||
apply( result.append, params )
|
||||
return result
|
||||
|
||||
def I( *params ) :
|
||||
text_props = TextPropertySet( italic=True )
|
||||
|
||||
if len( params ) == 1 :
|
||||
return Text( params[ 0 ], text_props )
|
||||
|
||||
result = Inline( text_props )
|
||||
apply( result.append, params )
|
||||
return result
|
||||
|
||||
def U( *params ) :
|
||||
text_props = TextPropertySet( underline=True )
|
||||
|
||||
if len( params ) == 1 :
|
||||
return Text( params[ 0 ], text_props )
|
||||
|
||||
result = Inline( text_props )
|
||||
apply( result.append, params )
|
||||
return result
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
"""
|
||||
PropertySets group common attributes together, each property set is used to control a specific part of the rendering.
|
||||
|
||||
PropertySets can be used in different elements of the document.
|
||||
|
||||
For example the FramePropertySet is used in paragraphs, tables, cells, etc.
|
||||
|
||||
The TextPropertySet can be used for text or in a Paragraph Style.
|
||||
|
||||
"""
|
||||
|
||||
from types import StringType
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
#
|
||||
# We need some basic Type like fonts, colours and paper definitions
|
||||
#
|
||||
def MakeAttributeName( value ) :
|
||||
assert value and type( value ) is StringType
|
||||
value = value.replace( ' ', '' )
|
||||
return value
|
||||
|
||||
class AttributedList( list ) :
|
||||
def __init__( self, accepted_type=None ) :
|
||||
super( AttributedList, self ).__init__()
|
||||
self.AcceptedType = accepted_type
|
||||
self._append = super( AttributedList, self ).append
|
||||
|
||||
def append( self, *values ) :
|
||||
for value in values :
|
||||
if self.AcceptedType : assert isinstance( value, self.AcceptedType )
|
||||
|
||||
self._append( value )
|
||||
|
||||
name = getattr( value, 'Name', None )
|
||||
if name :
|
||||
name = MakeAttributeName( value.Name )
|
||||
setattr( self, name, value )
|
||||
|
||||
def __deepcopy__( self, memo ) :
|
||||
result = self.__class__()
|
||||
result.append( *self[:] )
|
||||
return result
|
||||
|
||||
class Colour :
|
||||
def __init__( self, name, red, green, blue ) :
|
||||
self.SetName ( name )
|
||||
self.SetRed ( red )
|
||||
self.SetGreen( green )
|
||||
self.SetBlue ( blue )
|
||||
|
||||
def SetName( self, value ) :
|
||||
self.Name = value
|
||||
return self
|
||||
|
||||
def SetRed( self, value ) :
|
||||
self.Red = value
|
||||
return self
|
||||
|
||||
def SetGreen( self, value ) :
|
||||
self.Green = value
|
||||
return self
|
||||
|
||||
def SetBlue( self, value ) :
|
||||
self.Blue = value
|
||||
return self
|
||||
|
||||
class Colours( AttributedList ) :
|
||||
def __init__( self ) :
|
||||
super( Colours, self ).__init__( Colour )
|
||||
|
||||
class Font :
|
||||
def __init__( self, name, family, character_set = 0, pitch = None, panose = None, alternate = None ) :
|
||||
self.SetName ( name )
|
||||
self.SetFamily ( family )
|
||||
self.SetCharacterSet( character_set )
|
||||
self.SetPitch ( pitch )
|
||||
self.SetPanose ( panose )
|
||||
self.SetAlternate ( alternate )
|
||||
|
||||
def SetName( self, value ) :
|
||||
self.Name = value
|
||||
return self
|
||||
|
||||
def SetFamily( self, value ) :
|
||||
self.Family = value
|
||||
return self
|
||||
|
||||
def SetCharacterSet( self, value ) :
|
||||
self.CharacterSet = value
|
||||
return self
|
||||
|
||||
def SetPitch( self, value ) :
|
||||
self.Pitch = value
|
||||
return self
|
||||
|
||||
def SetPanose( self, value ) :
|
||||
self.Panose = value
|
||||
return self
|
||||
|
||||
def SetAlternate( self, value ) :
|
||||
self.Alternate = value
|
||||
return self
|
||||
|
||||
class Fonts( AttributedList ) :
|
||||
def __init__( self ) :
|
||||
super( Fonts, self ).__init__( Font )
|
||||
|
||||
class Paper :
|
||||
def __init__( self, name, code, description, width, height ) :
|
||||
self.SetName ( name )
|
||||
self.SetCode ( code )
|
||||
self.SetDescription( description )
|
||||
self.SetWidth ( width )
|
||||
self.SetHeight ( height )
|
||||
|
||||
def SetName( self, value ) :
|
||||
self.Name = value
|
||||
return self
|
||||
|
||||
def SetCode( self, value ) :
|
||||
self.Code = value
|
||||
return self
|
||||
|
||||
def SetDescription( self, value ) :
|
||||
self.Description = value
|
||||
return self
|
||||
|
||||
def SetWidth( self, value ) :
|
||||
self.Width = value
|
||||
return self
|
||||
|
||||
def SetHeight( self, value ) :
|
||||
self.Height = value
|
||||
return self
|
||||
|
||||
class Papers( AttributedList ) :
|
||||
def __init__( self ) :
|
||||
super( Papers, self ).__init__( Paper )
|
||||
|
||||
#
|
||||
# Then we have property sets which represent different aspects of Styles
|
||||
#
|
||||
class MarginsPropertySet :
|
||||
def __init__( self, top=None, left=None, bottom=None, right=None ) :
|
||||
self.SetTop ( top )
|
||||
self.SetLeft ( left )
|
||||
self.SetBottom( bottom )
|
||||
self.SetRight ( right )
|
||||
|
||||
def SetTop( self, value ) :
|
||||
self.Top = value
|
||||
return self
|
||||
|
||||
def SetLeft( self, value ) :
|
||||
self.Left = value
|
||||
return self
|
||||
|
||||
def SetBottom( self, value ) :
|
||||
self.Bottom = value
|
||||
return self
|
||||
|
||||
def SetRight( self, value ) :
|
||||
self.Right = value
|
||||
return self
|
||||
|
||||
class ShadingPropertySet :
|
||||
HORIZONTAL = 1
|
||||
VERTICAL = 2
|
||||
FORWARD_DIAGONAL = 3
|
||||
BACKWARD_DIAGONAL = 4
|
||||
VERTICAL_CROSS = 5
|
||||
DIAGONAL_CROSS = 6
|
||||
DARK_HORIZONTAL = 7
|
||||
DARK_VERTICAL = 8
|
||||
DARK_FORWARD_DIAGONAL = 9
|
||||
DARK_BACKWARD_DIAGONAL = 10
|
||||
DARK_VERTICAL_CROSS = 11
|
||||
DARK_DIAGONAL_CROSS = 12
|
||||
PATTERNS = [ HORIZONTAL,
|
||||
VERTICAL,
|
||||
FORWARD_DIAGONAL,
|
||||
BACKWARD_DIAGONAL,
|
||||
VERTICAL_CROSS,
|
||||
DIAGONAL_CROSS,
|
||||
DARK_HORIZONTAL,
|
||||
DARK_VERTICAL,
|
||||
DARK_FORWARD_DIAGONAL,
|
||||
DARK_BACKWARD_DIAGONAL,
|
||||
DARK_VERTICAL_CROSS,
|
||||
DARK_DIAGONAL_CROSS ]
|
||||
|
||||
def __init__( self, shading=None, pattern=None, foreground=None, background=None ) :
|
||||
self.SetShading ( shading )
|
||||
self.SetForeground( foreground )
|
||||
self.SetBackground( background )
|
||||
self.SetPattern ( pattern )
|
||||
|
||||
def __deepcopy__( self, memo ) :
|
||||
return ShadingPropertySet( self.Shading,
|
||||
self.Foreground,
|
||||
self.Background,
|
||||
self.Pattern )
|
||||
|
||||
def SetShading( self, value ) :
|
||||
self.Shading = value
|
||||
return self
|
||||
|
||||
def SetPattern( self, value ) :
|
||||
assert value is None or value in self.PATTERNS
|
||||
self.Pattern = value
|
||||
return self
|
||||
|
||||
def SetForeground( self, value ) :
|
||||
assert not value or isinstance( value, Colour )
|
||||
self.Foreground = value
|
||||
return self
|
||||
|
||||
def SetBackground( self, value ) :
|
||||
assert not value or isinstance( value, Colour )
|
||||
self.Background = value
|
||||
return self
|
||||
|
||||
|
||||
class BorderPropertySet :
|
||||
SINGLE = 1
|
||||
DOUBLE = 2
|
||||
SHADOWED = 3
|
||||
DOUBLED = 4
|
||||
DOTTED = 5
|
||||
DASHED = 6
|
||||
HAIRLINE = 7
|
||||
STYLES = [ SINGLE, DOUBLE, SHADOWED, DOUBLED, DOTTED, DASHED, HAIRLINE ]
|
||||
|
||||
def __init__( self, width=None, style=None, colour=None, spacing=None ) :
|
||||
self.SetWidth ( width )
|
||||
self.SetStyle ( style or self.SINGLE )
|
||||
self.SetColour ( colour )
|
||||
self.SetSpacing( spacing )
|
||||
|
||||
def SetWidth( self, value ) :
|
||||
self.Width = value
|
||||
return self
|
||||
|
||||
def SetStyle( self, value ) :
|
||||
assert value is None or value in self.STYLES
|
||||
self.Style = value
|
||||
return self
|
||||
|
||||
def SetColour( self, value ) :
|
||||
assert value is None or isinstance( value, Colour )
|
||||
self.Colour = value
|
||||
return self
|
||||
|
||||
def SetSpacing( self, value ) :
|
||||
self.Spacing = value
|
||||
return self
|
||||
|
||||
class FramePropertySet :
|
||||
def __init__( self, top=None, left=None, bottom=None, right=None ) :
|
||||
self.SetTop ( top )
|
||||
self.SetLeft ( left )
|
||||
self.SetBottom( bottom )
|
||||
self.SetRight ( right )
|
||||
|
||||
def SetTop( self, value ) :
|
||||
assert value is None or isinstance( value, BorderPropertySet )
|
||||
self.Top = value
|
||||
return self
|
||||
|
||||
def SetLeft( self, value ) :
|
||||
assert value is None or isinstance( value, BorderPropertySet )
|
||||
self.Left = value
|
||||
return self
|
||||
|
||||
def SetBottom( self, value ) :
|
||||
assert value is None or isinstance( value, BorderPropertySet )
|
||||
self.Bottom = value
|
||||
return self
|
||||
|
||||
def SetRight( self, value ) :
|
||||
assert value is None or isinstance( value, BorderPropertySet )
|
||||
self.Right = value
|
||||
return self
|
||||
|
||||
class TabPropertySet :
|
||||
DEFAULT_WIDTH = 720
|
||||
|
||||
LEFT = 1
|
||||
RIGHT = 2
|
||||
CENTER = 3
|
||||
DECIMAL = 4
|
||||
ALIGNMENT = [ LEFT, RIGHT, CENTER, DECIMAL ]
|
||||
|
||||
DOTS = 1
|
||||
HYPHENS = 2
|
||||
UNDERLINE = 3
|
||||
THICK_LINE = 4
|
||||
EQUAL_SIGN = 5
|
||||
LEADERS = [ DOTS, HYPHENS, UNDERLINE, THICK_LINE, EQUAL_SIGN ]
|
||||
|
||||
def __init__( self, width=None, alignment=None, leader=None ) :
|
||||
self.SetWidth ( width )
|
||||
self.SetAlignment( alignment or self.LEFT )
|
||||
self.SetLeader ( leader )
|
||||
|
||||
def SetWidth( self, value ) :
|
||||
self.Width = value
|
||||
return self
|
||||
|
||||
def SetAlignment( self, value ) :
|
||||
assert value in self.ALIGNMENT
|
||||
self.Alignment = value
|
||||
return self
|
||||
|
||||
def SetLeader( self, value ) :
|
||||
assert not value or value in self.LEADERS
|
||||
self.Leader = value
|
||||
return self
|
||||
|
||||
class TextPropertySet :
|
||||
|
||||
def __init__( self, font=None, size=None, bold=None, italic=None, underline=None, colour=None, frame=None, expansion=None ) :
|
||||
self.SetFont ( font )
|
||||
self.SetSize ( size )
|
||||
|
||||
self.SetBold ( bold or False )
|
||||
self.SetItalic ( italic or False )
|
||||
self.SetUnderline ( underline or False )
|
||||
|
||||
self.SetColour( colour )
|
||||
self.SetFrame ( frame )
|
||||
|
||||
self.SetStrikeThrough ( False )
|
||||
self.SetDottedUnderline( False )
|
||||
self.SetDoubleUnderline( False )
|
||||
self.SetWordUnderline ( False )
|
||||
self.SetExpansion ( expansion )
|
||||
|
||||
def Copy( self ) :
|
||||
return deepcopy( self )
|
||||
|
||||
def __deepcopy__( self, memo ) :
|
||||
# the font must remain a reference to the same font that we are looking at
|
||||
# so we want to stop the recursiveness at this point and return an object
|
||||
# with the right references.
|
||||
result = TextPropertySet( self.Font,
|
||||
self.Size,
|
||||
self.Bold,
|
||||
self.Italic,
|
||||
self.Underline,
|
||||
self.Colour,
|
||||
deepcopy( self.Frame, memo ) )
|
||||
result.SetStrikeThrough( self.StrikeThrough )
|
||||
return result
|
||||
|
||||
def SetFont( self, value ) :
|
||||
assert not value or isinstance( value, Font )
|
||||
self.Font = value
|
||||
return self
|
||||
|
||||
def SetSize( self, value ) :
|
||||
self.Size = value
|
||||
return self
|
||||
|
||||
def SetBold( self, value ) :
|
||||
self.Bold = False
|
||||
if value : self.Bold = True
|
||||
return self
|
||||
|
||||
def SetItalic( self, value ) :
|
||||
self.Italic = False
|
||||
if value : self.Italic = True
|
||||
return self
|
||||
|
||||
def SetUnderline( self, value ) :
|
||||
self.Underline = False
|
||||
if value : self.Underline = True
|
||||
return self
|
||||
|
||||
def SetColour( self, value ) :
|
||||
assert value is None or isinstance( value, Colour )
|
||||
self.Colour = value
|
||||
return self
|
||||
|
||||
def SetFrame( self, value ) :
|
||||
assert value is None or isinstance( value, BorderPropertySet )
|
||||
self.Frame = value
|
||||
return self
|
||||
|
||||
def SetStrikeThrough( self, value ) :
|
||||
self.StrikeThrough = False
|
||||
if value : self.StrikeThrough = True
|
||||
return self
|
||||
|
||||
def SetDottedUnderline( self, value ) :
|
||||
self.DottedUnderline = False
|
||||
if value : self.DottedUnderline = True
|
||||
return self
|
||||
|
||||
def SetDoubleUnderline( self, value ) :
|
||||
self.DoubleUnderline = False
|
||||
if value : self.DoubleUnderline = True
|
||||
return self
|
||||
|
||||
def SetWordUnderline( self, value ) :
|
||||
self.WordUnderline = False
|
||||
if value : self.WordUnderline = True
|
||||
return self
|
||||
|
||||
def SetExpansion( self, value ) :
|
||||
self.Expansion = value
|
||||
return self
|
||||
|
||||
class ParagraphPropertySet :
|
||||
LEFT = 1
|
||||
RIGHT = 2
|
||||
CENTER = 3
|
||||
JUSTIFY = 4
|
||||
DISTRIBUTE = 5
|
||||
ALIGNMENT = [ LEFT, RIGHT, CENTER, JUSTIFY, DISTRIBUTE ]
|
||||
|
||||
def __init__( self, alignment=None, space_before=None, space_after=None, tabs=None, first_line_indent=None, left_indent=None, right_indent=None, page_break_before=None ) :
|
||||
self.SetAlignment ( alignment or self.LEFT )
|
||||
self.SetSpaceBefore( space_before )
|
||||
self.SetSpaceAfter ( space_after )
|
||||
|
||||
self.Tabs = []
|
||||
if tabs : apply( self.SetTabs, tabs )
|
||||
|
||||
self.SetFirstLineIndent( first_line_indent or None )
|
||||
self.SetLeftIndent ( left_indent or None )
|
||||
self.SetRightIndent ( right_indent or None )
|
||||
|
||||
self.SetPageBreakBefore( page_break_before )
|
||||
|
||||
self.SetSpaceBetweenLines( None )
|
||||
|
||||
def Copy( self ) :
|
||||
return deepcopy( self )
|
||||
|
||||
def SetAlignment( self, value ) :
|
||||
assert not value or value in self.ALIGNMENT
|
||||
self.Alignment = value or self.LEFT
|
||||
return self
|
||||
|
||||
def SetSpaceBefore( self, value ) :
|
||||
self.SpaceBefore = value
|
||||
return self
|
||||
|
||||
def SetSpaceAfter( self, value ) :
|
||||
self.SpaceAfter = value
|
||||
return self
|
||||
|
||||
def SetTabs( self, *params ) :
|
||||
self.Tabs = params
|
||||
return self
|
||||
|
||||
def SetFirstLineIndent( self, value ) :
|
||||
self.FirstLineIndent = value
|
||||
return self
|
||||
|
||||
def SetLeftIndent( self, value ) :
|
||||
self.LeftIndent = value
|
||||
return self
|
||||
|
||||
def SetRightIndent( self, value ) :
|
||||
self.RightIndent = value
|
||||
return self
|
||||
|
||||
def SetSpaceBetweenLines( self, value ) :
|
||||
self.SpaceBetweenLines = value
|
||||
return self
|
||||
|
||||
def SetPageBreakBefore( self, value ) :
|
||||
self.PageBreakBefore = False
|
||||
if value : self.PageBreakBefore = True
|
||||
return self
|
||||
|
||||
# Some short cuts to make the code a bit easier to read
|
||||
MarginsPS = MarginsPropertySet
|
||||
ShadingPS = ShadingPropertySet
|
||||
BorderPS = BorderPropertySet
|
||||
FramePS = FramePropertySet
|
||||
TabPS = TabPropertySet
|
||||
TextPS = TextPropertySet
|
||||
ParagraphPS = ParagraphPropertySet
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
Version 0.46
|
||||
|
||||
Added EMF support.
|
||||
|
||||
Added more sophisticated scaling options.
|
||||
|
||||
See examples2.py for both.
|
||||
|
||||
Grant Edwards, grante@users.sourceforge.net
|
||||
|
||||
|
||||
|
||||
Version 0.45
|
||||
|
||||
Finally, image support!!! Handles PNGs and JPGs.
|
||||
|
||||
See examples2.py for the gory details.
|
||||
|
||||
Simon Cusack, scusack@sourceforge.net
|
||||
@@ -0,0 +1,639 @@
|
||||
from types import StringType, ListType, TupleType
|
||||
from copy import deepcopy
|
||||
from Elements import *
|
||||
|
||||
DEFAULT_TAB_WIDTH = 720
|
||||
|
||||
ParagraphAlignmentMap = { ParagraphPropertySet.LEFT : 'ql',
|
||||
ParagraphPropertySet.RIGHT : 'qr',
|
||||
ParagraphPropertySet.CENTER : 'qc',
|
||||
ParagraphPropertySet.JUSTIFY : 'qj',
|
||||
ParagraphPropertySet.DISTRIBUTE : 'qd' }
|
||||
|
||||
TabAlignmentMap = { TabPropertySet.LEFT : '',
|
||||
TabPropertySet.RIGHT : 'tqr',
|
||||
TabPropertySet.CENTER : 'tqc',
|
||||
TabPropertySet.DECIMAL : 'tqdec' }
|
||||
|
||||
TableAlignmentMap = { Table.LEFT : 'trql',
|
||||
Table.RIGHT : 'trqr',
|
||||
Table.CENTER : 'trqc' }
|
||||
|
||||
CellAlignmentMap = { Cell.ALIGN_TOP : '', # clvertalt
|
||||
Cell.ALIGN_CENTER : 'clvertalc',
|
||||
Cell.ALIGN_BOTTOM : 'clvertalb' }
|
||||
|
||||
CellFlowMap = { Cell.FLOW_LR_TB : '', # cltxlrtb, Text in a cell flows from left to right and top to bottom (default)
|
||||
Cell.FLOW_RL_TB : 'cltxtbrl', # Text in a cell flows right to left and top to bottom
|
||||
Cell.FLOW_LR_BT : 'cltxbtlr', # Text in a cell flows left to right and bottom to top
|
||||
Cell.FLOW_VERTICAL_LR_TB : 'cltxlrtbv', # Text in a cell flows left to right and top to bottom, vertical
|
||||
Cell.FLOW_VERTICAL_TB_RL : 'cltxtbrlv' } # Text in a cell flows top to bottom and right to left, vertical
|
||||
|
||||
ShadingPatternMap = { ShadingPropertySet.HORIZONTAL : 'bghoriz',
|
||||
ShadingPropertySet.VERTICAL : 'bgvert',
|
||||
ShadingPropertySet.FORWARD_DIAGONAL : 'bgfdiag',
|
||||
ShadingPropertySet.BACKWARD_DIAGONAL : 'bgbdiag',
|
||||
ShadingPropertySet.VERTICAL_CROSS : 'bgcross',
|
||||
ShadingPropertySet.DIAGONAL_CROSS : 'bgdcross',
|
||||
ShadingPropertySet.DARK_HORIZONTAL : 'bgdkhoriz',
|
||||
ShadingPropertySet.DARK_VERTICAL : 'bgdkvert',
|
||||
ShadingPropertySet.DARK_FORWARD_DIAGONAL : 'bgdkfdiag',
|
||||
ShadingPropertySet.DARK_BACKWARD_DIAGONAL : 'bgdkbdiag',
|
||||
ShadingPropertySet.DARK_VERTICAL_CROSS : 'bgdkcross',
|
||||
ShadingPropertySet.DARK_DIAGONAL_CROSS : 'bgdkdcross' }
|
||||
|
||||
TabLeaderMap = { TabPropertySet.DOTS : 'tldot',
|
||||
TabPropertySet.HYPHENS : 'tlhyph',
|
||||
TabPropertySet.UNDERLINE : 'tlul',
|
||||
TabPropertySet.THICK_LINE : 'tlth',
|
||||
TabPropertySet.EQUAL_SIGN : 'tleq' }
|
||||
|
||||
BorderStyleMap = { BorderPropertySet.SINGLE : 'brdrs',
|
||||
BorderPropertySet.DOUBLE : 'brdrth',
|
||||
BorderPropertySet.SHADOWED : 'brdrsh',
|
||||
BorderPropertySet.DOUBLED : 'brdrdb',
|
||||
BorderPropertySet.DOTTED : 'brdrdot',
|
||||
BorderPropertySet.DASHED : 'brdrdash',
|
||||
BorderPropertySet.HAIRLINE : 'brdrhair' }
|
||||
|
||||
SectionBreakTypeMap = { Section.NONE : 'sbknone',
|
||||
Section.COLUMN : 'sbkcol',
|
||||
Section.PAGE : 'sbkpage',
|
||||
Section.EVEN : 'sbkeven',
|
||||
Section.ODD : 'sbkodd' }
|
||||
|
||||
class Settings( list ) :
|
||||
def __init__( self ) :
|
||||
super( Settings, self ).__init__()
|
||||
self._append = super( Settings, self ).append
|
||||
|
||||
def append( self, value, mask=None, fallback=None ) :
|
||||
if (value is not 0) and value in [ False, None, '' ] :
|
||||
if fallback : self._append( self, fallback )
|
||||
|
||||
else :
|
||||
if mask :
|
||||
if value is True :
|
||||
value = mask
|
||||
else :
|
||||
value = mask % value
|
||||
self._append( value )
|
||||
|
||||
def Join( self ) :
|
||||
if self : return r'\%s' % '\\'.join( self )
|
||||
return ''
|
||||
|
||||
def __repr__( self ) :
|
||||
return self.Join()
|
||||
|
||||
class Renderer :
|
||||
def __init__( self, write_custom_element_callback=None ) :
|
||||
self.character_style_map = {}
|
||||
self.paragraph_style_map = {}
|
||||
self.WriteCustomElement = write_custom_element_callback
|
||||
|
||||
#
|
||||
# All of the Rend* Functions populate a Settings object with values
|
||||
#
|
||||
def _RendPageProperties( self, section, settings, in_section ) :
|
||||
# this one is different from the others as it takes the settings from a
|
||||
if in_section :
|
||||
#paper_size_code = 'psz%s'
|
||||
paper_width_code = 'pgwsxn%s'
|
||||
paper_height_code = 'pghsxn%s'
|
||||
landscape = 'lndscpsxn'
|
||||
margin_suffix = 'sxn'
|
||||
|
||||
else :
|
||||
#paper_size_code = 'psz%s'
|
||||
paper_width_code = 'paperw%s'
|
||||
paper_height_code = 'paperh%s'
|
||||
landscape = 'landscape'
|
||||
margin_suffix = ''
|
||||
|
||||
#settings.append( section.Paper.Code, paper_size_code )
|
||||
settings.append( section.Paper.Width, paper_width_code )
|
||||
settings.append( section.Paper.Height, paper_height_code )
|
||||
|
||||
if section.Landscape :
|
||||
settings.append( landscape )
|
||||
|
||||
if section.FirstPageNumber :
|
||||
settings.append( section.FirstPageNumber, 'pgnstarts%s' )
|
||||
settings.append( 'pgnrestart' )
|
||||
|
||||
self._RendMarginsPropertySet( section.Margins, settings, margin_suffix )
|
||||
|
||||
def _RendShadingPropertySet( self, shading_props, settings, prefix='' ) :
|
||||
if not shading_props : return
|
||||
|
||||
settings.append( shading_props.Shading, prefix + 'shading%s' )
|
||||
settings.append( ShadingPatternMap.get( shading_props.Pattern, False ) )
|
||||
|
||||
settings.append( self._colour_map.get( shading_props.Foreground, False ), prefix + 'cfpat%s' )
|
||||
settings.append( self._colour_map.get( shading_props.Background, False ), prefix + 'cbpat%s' )
|
||||
|
||||
def _RendBorderPropertySet( self, edge_props, settings ) :
|
||||
settings.append( BorderStyleMap[ edge_props.Style ] )
|
||||
settings.append( edge_props.Width , 'brdrw%s' )
|
||||
settings.append( self._colour_map.get( edge_props.Colour, False ), 'brdrcf%s' )
|
||||
settings.append( edge_props.Spacing or False , 'brsp%s' )
|
||||
|
||||
def _RendFramePropertySet( self, frame_props, settings, tag_prefix='' ) :
|
||||
if not frame_props : return
|
||||
|
||||
if frame_props.Top :
|
||||
settings.append( tag_prefix + 'brdrt' )
|
||||
self._RendBorderPropertySet( frame_props.Top, settings )
|
||||
|
||||
if frame_props.Left :
|
||||
settings.append( tag_prefix + 'brdrl' )
|
||||
self._RendBorderPropertySet( frame_props.Left, settings )
|
||||
|
||||
if frame_props.Bottom :
|
||||
settings.append( tag_prefix + 'brdrb' )
|
||||
self._RendBorderPropertySet( frame_props.Bottom, settings )
|
||||
|
||||
if frame_props.Right :
|
||||
settings.append( tag_prefix + 'brdrr' )
|
||||
self._RendBorderPropertySet( frame_props.Right, settings )
|
||||
|
||||
def _RendMarginsPropertySet( self, margin_props, settings, suffix='' ) :
|
||||
if not margin_props : return
|
||||
|
||||
settings.append( margin_props.Top, 'margt' + suffix + '%s' )
|
||||
settings.append( margin_props.Left, 'margl' + suffix + '%s' )
|
||||
settings.append( margin_props.Bottom, 'margb' + suffix + '%s' )
|
||||
settings.append( margin_props.Right, 'margr' + suffix + '%s' )
|
||||
|
||||
def _RendParagraphPropertySet( self, paragraph_props, settings ) :
|
||||
if not paragraph_props : return
|
||||
settings.append( ParagraphAlignmentMap[ paragraph_props.Alignment ] )
|
||||
|
||||
settings.append( paragraph_props.SpaceBefore, 'sb%s' )
|
||||
settings.append( paragraph_props.SpaceAfter, 'sa%s' )
|
||||
|
||||
# then we have to find out all of the tabs
|
||||
width = 0
|
||||
for tab in paragraph_props.Tabs :
|
||||
settings.append( TabAlignmentMap[ tab.Alignment ] )
|
||||
settings.append( TabLeaderMap.get( tab.Leader, '' ) )
|
||||
|
||||
width += tab.Width or DEFAULT_TAB_WIDTH
|
||||
settings.append( 'tx%s' % width )
|
||||
|
||||
settings.append( paragraph_props.PageBreakBefore, 'pagebb' )
|
||||
|
||||
settings.append( paragraph_props.FirstLineIndent, 'fi%s' )
|
||||
settings.append( paragraph_props.LeftIndent, 'li%s' )
|
||||
settings.append( paragraph_props.RightIndent, 'ri%s' )
|
||||
|
||||
if paragraph_props.SpaceBetweenLines :
|
||||
if paragraph_props.SpaceBetweenLines < 0 :
|
||||
settings.append( paragraph_props.SpaceBetweenLines, r'sl%s\slmult0' )
|
||||
else :
|
||||
settings.append( paragraph_props.SpaceBetweenLines, r'sl%s\slmult1' )
|
||||
|
||||
def _RendTextPropertySet( self, text_props, settings ) :
|
||||
if not text_props : return
|
||||
|
||||
if text_props.Expansion :
|
||||
settings.append( text_props.Expansion, 'expndtw%s' )
|
||||
|
||||
settings.append( text_props.Bold, 'b' )
|
||||
settings.append( text_props.Italic, 'i' )
|
||||
settings.append( text_props.Underline, 'ul' )
|
||||
settings.append( text_props.DottedUnderline, 'uld' )
|
||||
settings.append( text_props.DoubleUnderline, 'uldb' )
|
||||
settings.append( text_props.WordUnderline, 'ulw' )
|
||||
|
||||
settings.append( self._font_map.get( text_props.Font, False ), 'f%s' )
|
||||
settings.append( text_props.Size, 'fs%s' )
|
||||
settings.append( self._colour_map.get( text_props.Colour, False ), 'cf%s' )
|
||||
|
||||
if text_props.Frame :
|
||||
frame = text_props.Frame
|
||||
settings.append( 'chbrdr' )
|
||||
settings.append( BorderStyleMap[ frame.Style ] )
|
||||
settings.append( frame.Width , 'brdrw%s' )
|
||||
settings.append( self._colour_map.get( frame.Colour, False ), 'brdrcf%s' )
|
||||
|
||||
#
|
||||
# All of the Write* functions will write to the internal file object
|
||||
#
|
||||
# the _ ones probably don't need to be used by anybody outside
|
||||
# but the other ones like WriteTextElement could be used in the Custom
|
||||
# callback.
|
||||
def Write( self, document, fout ) :
|
||||
# write all of the standard stuff based upon the first document
|
||||
self._doc = document
|
||||
self._fout = fout
|
||||
self._WriteDocument ()
|
||||
self._WriteColours ()
|
||||
self._WriteFonts ()
|
||||
self._WriteStyleSheet()
|
||||
|
||||
settings = Settings()
|
||||
self._RendPageProperties( self._doc.Sections[ 0 ], settings, in_section=False )
|
||||
self._write( repr( settings ) )
|
||||
|
||||
# handle the simplest case first, we don't need to do anymore mucking around
|
||||
# with section headers, etc we can just rip the document out
|
||||
if len( document.Sections ) == 1 :
|
||||
self._WriteSection( document.Sections[ 0 ],
|
||||
is_first = True,
|
||||
add_header = False )
|
||||
|
||||
else :
|
||||
for section_idx, section in enumerate( document.Sections ) :
|
||||
is_first = section_idx == 0
|
||||
add_header = True
|
||||
self._WriteSection( section, is_first, add_header )
|
||||
|
||||
self._write( '}' )
|
||||
|
||||
del self._fout, self._doc, self._CurrentStyle
|
||||
|
||||
def _write( self, data, *params ) :
|
||||
#----------------------------------
|
||||
# begin modification
|
||||
# by Herbert Weinhandl
|
||||
# to convert accented characters
|
||||
# to their rtf-compatible form
|
||||
#for c in range( 128, 256 ) :
|
||||
# data = data.replace( chr(c), "\'%x" % c)
|
||||
# end modification
|
||||
#
|
||||
# This isn't the right place for this as it is going to do
|
||||
# this loop for all sorts of writes, including settings, control codes, etc.
|
||||
#
|
||||
# I will create a def _WriteText (or something) method that is used when the
|
||||
# actual string that is to be viewed in the document is written, this can then
|
||||
# do the final accented character check.
|
||||
#
|
||||
# I left it here so that I remember to do the right thing when I have time
|
||||
#----------------------------------
|
||||
|
||||
if params : data = data % params
|
||||
self._fout.write( data )
|
||||
|
||||
def _WriteDocument( self ) :
|
||||
settings = Settings()
|
||||
|
||||
assert Languages.IsValid ( self._doc.DefaultLanguage )
|
||||
assert ViewKind.IsValid ( self._doc.ViewKind )
|
||||
assert ViewZoomKind.IsValid( self._doc.ViewZoomKind )
|
||||
assert ViewScale.IsValid ( self._doc.ViewScale )
|
||||
|
||||
settings.append( self._doc.DefaultLanguage, 'deflang%s' )
|
||||
settings.append( self._doc.ViewKind , 'viewkind%s' )
|
||||
settings.append( self._doc.ViewZoomKind , 'viewzk%s' )
|
||||
settings.append( self._doc.ViewScale , 'viewscale%s' )
|
||||
|
||||
self._write( "{\\rtf1\\ansi\\ansicpg1252\\deff0%s\n" % settings )
|
||||
|
||||
def _WriteColours( self ) :
|
||||
self._write( r"{\colortbl ;" )
|
||||
|
||||
self._colour_map = {}
|
||||
offset = 0
|
||||
for colour in self._doc.StyleSheet.Colours :
|
||||
self._write( r'\red%s\green%s\blue%s;', colour.Red, colour.Green, colour.Blue )
|
||||
self._colour_map[ colour ] = offset + 1
|
||||
offset += 1
|
||||
self._write( "}\n" )
|
||||
|
||||
def _WriteFonts( self ) :
|
||||
self._write( r'{\fonttbl' )
|
||||
|
||||
self._font_map = {}
|
||||
offset = 0
|
||||
for font in self._doc.StyleSheet.Fonts :
|
||||
pitch = ''
|
||||
panose = ''
|
||||
alternate = ''
|
||||
if font.Pitch : pitch = r'\fprq%s' % font.Pitch
|
||||
if font.Panose : panose = r'{\*\panose %s}' % font.Panose
|
||||
if font.Alternate : alternate = r'{\*\falt %s}' % font.Alternate.Name
|
||||
|
||||
self._write( r'{\f%s\f%s%s\fcharset%s%s %s%s;}',
|
||||
offset,
|
||||
font.Family,
|
||||
pitch,
|
||||
font.CharacterSet,
|
||||
panose,
|
||||
font.Name,
|
||||
alternate )
|
||||
|
||||
self._font_map[ font ] = offset
|
||||
offset += 1
|
||||
|
||||
self._write( "}\n" )
|
||||
|
||||
def _WriteStyleSheet( self ) :
|
||||
self._write( r"{\stylesheet" )
|
||||
|
||||
# TO DO: character styles, does anybody actually use them?
|
||||
|
||||
offset_map = {}
|
||||
for idx, style in enumerate( self._doc.StyleSheet.ParagraphStyles ) :
|
||||
offset_map[ style ] = idx
|
||||
|
||||
# paragraph styles
|
||||
self.paragraph_style_map = {}
|
||||
for idx, style in enumerate( self._doc.StyleSheet.ParagraphStyles ) :
|
||||
|
||||
if idx == 0 :
|
||||
default = style
|
||||
else :
|
||||
self._write( '\n' )
|
||||
|
||||
settings = Settings()
|
||||
|
||||
# paragraph properties
|
||||
self._RendParagraphPropertySet( style.ParagraphPropertySet, settings )
|
||||
self._RendFramePropertySet ( style.FramePropertySet, settings )
|
||||
self._RendShadingPropertySet ( style.ShadingPropertySet, settings )
|
||||
|
||||
# text properties
|
||||
self._RendTextPropertySet ( style.TextStyle.TextPropertySet, settings )
|
||||
self._RendShadingPropertySet( style.TextStyle.ShadingPropertySet, settings )
|
||||
|
||||
# have to take
|
||||
based_on = '\\sbasedon%s' % offset_map.get( style.BasedOn, 0 )
|
||||
next = '\\snext%s' % offset_map.get( style.Next, 0 )
|
||||
|
||||
inln = '\\s%s%s' % ( idx, settings )
|
||||
self._write( "{%s%s%s %s;}", inln, based_on, next, style.Name )
|
||||
|
||||
self.paragraph_style_map[ style ] = inln
|
||||
|
||||
# if now style is specified for the first paragraph to be written, this one
|
||||
# will be used
|
||||
self._CurrentStyle = self.paragraph_style_map[ default ]
|
||||
|
||||
self._write( "}\n" )
|
||||
|
||||
def _WriteSection( self, section, is_first, add_header ) :
|
||||
|
||||
def WriteHF( hf, rtfword ) :
|
||||
#if not hf : return
|
||||
|
||||
# if we don't have anything in the header/footer then include
|
||||
# a blank paragraph, this stops it from picking up the header/footer
|
||||
# from the previous section
|
||||
# if not hf : hf = [ Paragraph( '' ) ]
|
||||
if not hf : hf = []
|
||||
|
||||
self._write( '{\\%s' % rtfword )
|
||||
self._WriteElements( hf )
|
||||
self._write( '}\n' )
|
||||
|
||||
settings = Settings()
|
||||
|
||||
if not is_first :
|
||||
# we need to finish off the preceding section
|
||||
# and reset all of our defaults back to standard
|
||||
settings.append( 'sect' )
|
||||
|
||||
# reset to our defaults
|
||||
settings.append( 'sectd' )
|
||||
|
||||
if add_header :
|
||||
settings.append( SectionBreakTypeMap[ section.BreakType ] )
|
||||
self._RendPageProperties( section, settings, in_section=True )
|
||||
|
||||
settings.append( section.HeaderY, 'headery%s' )
|
||||
settings.append( section.FooterY, 'footery%s' )
|
||||
|
||||
# write all of these out now as we need to do a write elements in the
|
||||
# next section
|
||||
self._write( repr( settings ) )
|
||||
|
||||
# finally after all that has settled down we can do the
|
||||
# headers and footers
|
||||
if section.FirstHeader or section.FirstFooter :
|
||||
# include the titlepg flag if the first page has a special format
|
||||
self._write( r'\titlepg' )
|
||||
WriteHF( section.FirstHeader, 'headerf' )
|
||||
WriteHF( section.FirstFooter, 'footerf' )
|
||||
|
||||
WriteHF( section.Header, 'header' )
|
||||
WriteHF( section.Footer, 'footer' )
|
||||
|
||||
# and at last the contents of the section that actually appear on the page
|
||||
self._WriteElements( section )
|
||||
|
||||
def _WriteElements( self, elements ) :
|
||||
new_line = ''
|
||||
for element in elements :
|
||||
self._write( new_line )
|
||||
new_line = '\n'
|
||||
|
||||
clss = element.__class__
|
||||
|
||||
if clss == Paragraph :
|
||||
self.WriteParagraphElement( element )
|
||||
|
||||
elif clss == Table :
|
||||
self.WriteTableElement( element )
|
||||
|
||||
elif clss == StringType :
|
||||
self.WriteParagraphElement( Paragraph( element ) )
|
||||
|
||||
elif clss in [ RawCode, Image ] :
|
||||
self.WriteRawCode( element )
|
||||
|
||||
#elif clss == List :
|
||||
# self._HandleListElement( element )
|
||||
|
||||
elif self.WriteCustomElement :
|
||||
self.WriteCustomElement( self, element )
|
||||
|
||||
else :
|
||||
raise Exception( "Don't know how to handle elements of type %s" % clss )
|
||||
|
||||
def WriteParagraphElement( self, paragraph_elem, tag_prefix='', tag_suffix=r'\par', opening='{', closing='}' ) :
|
||||
|
||||
# the tag_prefix and the tag_suffix take care of paragraphs in tables. A
|
||||
# paragraph in a table requires and extra tag at the front (intbl) and we
|
||||
# don't want the ending tag everytime. We want it for all paragraphs but
|
||||
# the last.
|
||||
|
||||
overrides = Settings()
|
||||
self._RendParagraphPropertySet( paragraph_elem.Properties, overrides )
|
||||
self._RendFramePropertySet ( paragraph_elem.Frame, overrides )
|
||||
self._RendShadingPropertySet ( paragraph_elem.Shading, overrides )
|
||||
|
||||
# when writing the RTF the style is carried from the previous paragraph to the next,
|
||||
# so if the currently written paragraph has a style then make it the current one,
|
||||
# otherwise leave it as it was
|
||||
self._CurrentStyle = self.paragraph_style_map.get( paragraph_elem.Style, self._CurrentStyle )
|
||||
|
||||
self._write( r'%s\pard\plain%s %s%s ' % ( opening, tag_prefix, self._CurrentStyle, overrides ) )
|
||||
|
||||
for element in paragraph_elem :
|
||||
|
||||
if isinstance( element, StringType ) :
|
||||
self._write( element )
|
||||
|
||||
elif isinstance( element, RawCode ) :
|
||||
self._write( element.Data )
|
||||
|
||||
elif isinstance( element, Text ) :
|
||||
self.WriteTextElement( element )
|
||||
|
||||
elif isinstance( element, Inline ) :
|
||||
self.WriteInlineElement( element )
|
||||
|
||||
elif element == TAB :
|
||||
self._write( r'\tab ' )
|
||||
|
||||
elif element == LINE :
|
||||
self._write( r'\line ' )
|
||||
|
||||
elif self.WriteCustomElement :
|
||||
self.WriteCustomElement( self, element )
|
||||
|
||||
else :
|
||||
raise Exception( 'Don\'t know how to handle %s' % element )
|
||||
|
||||
self._write( tag_suffix + closing )
|
||||
|
||||
def WriteRawCode( self, raw_elem ) :
|
||||
self._write( raw_elem.Data )
|
||||
|
||||
def WriteTextElement( self, text_elem ) :
|
||||
overrides = Settings()
|
||||
|
||||
self._RendTextPropertySet ( text_elem.Properties, overrides )
|
||||
self._RendShadingPropertySet( text_elem.Shading, overrides, 'ch' )
|
||||
|
||||
# write the wrapper and then let the custom handler have a go
|
||||
if overrides : self._write( '{%s ' % repr( overrides ) )
|
||||
|
||||
# if the data is just a string then we can now write it
|
||||
if isinstance( text_elem.Data, StringType ) :
|
||||
self._write( text_elem.Data or '' )
|
||||
|
||||
elif text_elem.Data == TAB :
|
||||
self._write( r'\tab ' )
|
||||
|
||||
else :
|
||||
self.WriteCustomElement( self, text_elem.Data )
|
||||
|
||||
if overrides : self._write( '}' )
|
||||
|
||||
def WriteInlineElement( self, inline_elem ) :
|
||||
overrides = Settings()
|
||||
|
||||
self._RendTextPropertySet ( inline_elem.Properties, overrides )
|
||||
self._RendShadingPropertySet( inline_elem.Shading, overrides, 'ch' )
|
||||
|
||||
# write the wrapper and then let the custom handler have a go
|
||||
if overrides : self._write( '{%s ' % repr( overrides ) )
|
||||
|
||||
for element in inline_elem :
|
||||
# if the data is just a string then we can now write it
|
||||
if isinstance( element, StringType ) :
|
||||
self._write( element )
|
||||
|
||||
elif isinstance( element, RawCode ) :
|
||||
self._write( element.Data )
|
||||
|
||||
elif element == TAB :
|
||||
self._write( r'\tab ' )
|
||||
|
||||
elif element == LINE :
|
||||
self._write( r'\line ' )
|
||||
|
||||
else :
|
||||
self.WriteCustomElement( self, element )
|
||||
|
||||
if overrides : self._write( '}' )
|
||||
|
||||
def WriteText( self, text ) :
|
||||
self._write( text or '' )
|
||||
|
||||
def WriteTableElement( self, table_elem ) :
|
||||
|
||||
vmerge = [ False ] * table_elem.ColumnCount
|
||||
for height, cells in table_elem.Rows :
|
||||
|
||||
# calculate the right hand edge of the cells taking into account the spans
|
||||
offset = table_elem.LeftOffset or 0
|
||||
cellx = []
|
||||
cell_idx = 0
|
||||
for cell in cells :
|
||||
cellx.append( offset + sum( table_elem.ColumnWidths[ : cell_idx + cell.Span ] ) )
|
||||
cell_idx += cell.Span
|
||||
|
||||
self._write( r'{\trowd' )
|
||||
|
||||
settings = Settings()
|
||||
|
||||
# the spec says that this value is mandatory and I think that 108 is the default value
|
||||
# so I'll take care of it here
|
||||
settings.append( table_elem.GapBetweenCells or 108, 'trgaph%s' )
|
||||
settings.append( TableAlignmentMap[ table_elem.Alignment ] )
|
||||
settings.append( height, 'trrh%s' )
|
||||
settings.append( table_elem.LeftOffset, 'trleft%s' )
|
||||
|
||||
width = table_elem.LeftOffset or 0
|
||||
for idx, cell in enumerate( cells ) :
|
||||
self._RendFramePropertySet ( cell.Frame, settings, 'cl' )
|
||||
|
||||
# cells don't have margins so I don't know why I was doing this
|
||||
# I think it might have an affect in some versions of some WPs.
|
||||
#self._RendMarginsPropertySet( cell.Margins, settings, 'cl' )
|
||||
|
||||
# if we are starting to merge or if this one is the first in what is
|
||||
# probably a series of merges then start the vertical merging
|
||||
if cell.StartVerticalMerge or (cell.VerticalMerge and not vmerge[ idx ]) :
|
||||
settings.append( 'clvmgf' )
|
||||
vmerge[ idx ] = True
|
||||
|
||||
elif cell.VerticalMerge :
|
||||
#..continuing a merge
|
||||
settings.append( 'clvmrg' )
|
||||
|
||||
else :
|
||||
#..no merging going on so make sure that it is off
|
||||
vmerge[ idx ] = False
|
||||
|
||||
# for any cell in the next row that is covered by this span we
|
||||
# need to run off the vertical merging as we don't want them
|
||||
# merging up into this spanned cell
|
||||
for vmerge_idx in range( idx + 1, idx + cell.Span - 1 ) :
|
||||
vmerge[ vmerge_idx ] = False
|
||||
|
||||
settings.append( CellAlignmentMap[ cell.Alignment ] )
|
||||
settings.append( CellFlowMap[ cell.Flow ] )
|
||||
|
||||
# this terminates the definition of a cell and represents the right most edge of the cell from the left margin
|
||||
settings.append( cellx[ idx ], 'cellx%s' )
|
||||
|
||||
self._write( repr( settings ) )
|
||||
|
||||
for cell in cells :
|
||||
if len( cell ) :
|
||||
last_idx = len( cell ) - 1
|
||||
for element_idx, element in enumerate( cell ) :
|
||||
# wrap plain strings in paragraph tags
|
||||
if isinstance( element, StringType ) :
|
||||
element = Paragraph( element )
|
||||
|
||||
# don't forget the prefix or else word crashes and does all sorts of strange things
|
||||
if element_idx == last_idx :
|
||||
self.WriteParagraphElement( element, tag_prefix=r'\intbl', tag_suffix='', opening='', closing='' )
|
||||
|
||||
else :
|
||||
self.WriteParagraphElement( element, tag_prefix=r'\intbl', opening='', closing='' )
|
||||
|
||||
self._write( r'\cell' )
|
||||
|
||||
else :
|
||||
self._write( r'\pard\intbl\cell' )
|
||||
|
||||
self._write( '\\row}\n' )
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
A Styles is a collection of PropertySets that can be applied to a particular RTF element.
|
||||
|
||||
At present there are only two, Text and Paragraph but ListStyles will be added soon too.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from PropertySets import *
|
||||
|
||||
class TextStyle :
|
||||
def __init__( self, text_props, name=None, shading_props=None ) :
|
||||
self.SetTextPropertySet ( text_props )
|
||||
self.SetName ( name )
|
||||
self.SetShadingPropertySet( shading_props )
|
||||
|
||||
def Copy( self ) :
|
||||
return deepcopy( self )
|
||||
|
||||
def SetName( self, value ) :
|
||||
self.Name = value
|
||||
return self
|
||||
|
||||
def SetTextPropertySet( self, value ) :
|
||||
assert isinstance( value, TextPropertySet )
|
||||
self.TextPropertySet = value
|
||||
return self
|
||||
|
||||
def SetShadingPropertySet( self, value ) :
|
||||
assert value is None or isinstance( value, ShadingPropertySet )
|
||||
self.ShadingPropertySet = value or ShadingPropertySet()
|
||||
return self
|
||||
|
||||
class ParagraphStyle :
|
||||
def __init__( self, name, text_style, paragraph_props=None, frame_props=None, shading_props=None ) :
|
||||
|
||||
# A style must have Font and a Font Size but the Text property set doesn't
|
||||
# make these mandatory so that they can be used for overrides so at this point
|
||||
# we need to make sure that that we have these values set
|
||||
if not text_style.TextPropertySet.Font : raise Exception( 'Paragraph Styles must have a Font specified.' )
|
||||
if not text_style.TextPropertySet.Size : raise Exception( 'Paragraph Styles must have a Font Size specified.' )
|
||||
|
||||
self.SetName ( name )
|
||||
self.SetTextStyle ( text_style )
|
||||
self.SetParagraphPropertySet( paragraph_props )
|
||||
self.SetFramePropertySet ( frame_props )
|
||||
self.SetShadingPropertySet ( shading_props )
|
||||
|
||||
self.SetBasedOn( None )
|
||||
self.SetNext ( None )
|
||||
|
||||
def Copy( self ) :
|
||||
return deepcopy( self )
|
||||
|
||||
def SetName( self, value ) :
|
||||
self.Name = value
|
||||
return self
|
||||
|
||||
def SetTextStyle( self, value ) :
|
||||
assert isinstance( value, TextStyle )
|
||||
self.TextStyle = value
|
||||
return self
|
||||
|
||||
def SetParagraphPropertySet( self, value ) :
|
||||
assert value is None or isinstance( value, ParagraphPropertySet )
|
||||
self.ParagraphPropertySet = value or ParagraphPropertySet()
|
||||
return self
|
||||
|
||||
def SetFramePropertySet( self, value ) :
|
||||
assert value is None or isinstance( value, FramePropertySet )
|
||||
self.FramePropertySet = value or FramePropertySet()
|
||||
return self
|
||||
|
||||
def SetShadingPropertySet( self, value ) :
|
||||
"""Set the background shading for the paragraph."""
|
||||
|
||||
assert value is None or isinstance( value, ShadingPropertySet )
|
||||
self.ShadingPropertySet = value or ShadingPropertySet()
|
||||
return self
|
||||
|
||||
def SetBasedOn( self, value ) :
|
||||
"""Set the Paragraph Style that this one is based on."""
|
||||
|
||||
assert not value or isinstance( value, ParagraphStyle )
|
||||
self.BasedOn = value
|
||||
return self
|
||||
|
||||
def SetNext( self, value ) :
|
||||
"""Set the Paragraph Style that should follow this one."""
|
||||
|
||||
assert not value or isinstance( value, ParagraphStyle )
|
||||
self.Next = value
|
||||
return self
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
from PropertySets import *
|
||||
from Elements import *
|
||||
from Styles import *
|
||||
from Renderer import *
|
||||
|
||||
def dumps(doc):
|
||||
import cStringIO
|
||||
s=cStringIO.StringIO()
|
||||
r=Renderer()
|
||||
r.Write(doc,s)
|
||||
return s.getvalue()
|
||||
|
||||
Reference in new issue
Block a user