1 # docbook.py: extension module
\r
2 # $Id: docbook.py 8353 2009-03-17 16:57:50Z mzjn $
\r
12 pixelsPerInch = 96.0
\r
13 unitHash = { 'in': pixelsPerInch,
\r
14 'cm': pixelsPerInch / 2.54,
\r
15 'mm': pixelsPerInch / 25.4,
\r
16 'pc': (pixelsPerInch / 72.0) * 12,
\r
17 'pt': pixelsPerInch / 72.0,
\r
20 # ======================================================================
\r
22 def adjustColumnWidths(ctx, nodeset):
\r
24 # Small check to verify the context is correcly accessed
\r
27 pctxt = libxslt.xpathParserContext(_obj=ctx)
\r
28 ctxt = pctxt.context()
\r
29 tctxt = ctxt.transformContext()
\r
33 # Get the nominal table width
\r
34 varString = lookupVariable(tctxt, "nominal.table.width", None)
\r
35 if varString == None:
\r
36 nominalWidth = 6 * pixelsPerInch;
\r
38 nominalWidth = convertLength(varString);
\r
40 # Get the requested table width
\r
41 tableWidth = lookupVariable(tctxt, "table.width", "100%")
\r
43 foStylesheet = (tctxt.variableLookup("stylesheet.result.type", None) == "fo")
\r
51 colgroup = libxml2.xmlNode(_obj = nodeset[0])
\r
52 # If this is an foStylesheet, we've been passed a list of fo:table-columns.
\r
53 # Otherwise we've been passed a colgroup that contains a list of cols.
\r
55 colChildren = colgroup
\r
57 colChildren = colgroup.children
\r
62 width = col.prop("column-width")
\r
64 width = col.prop("width")
\r
71 starPos = string.find(width, "*")
\r
73 relPart, absPart = string.split(width, "*", 2)
\r
74 relPart = float(relPart)
\r
75 relTotal = relTotal + float(relPart)
\r
79 pixels = convertLength(absPart)
\r
80 absTotal = absTotal + pixels
\r
82 relParts.append(relPart)
\r
83 absParts.append(pixels)
\r
87 # Ok, now we have the relative widths and absolute widths in
\r
88 # two parallel arrays.
\r
90 # - If there are no relative widths, output the absolute widths
\r
91 # - If there are no absolute widths, output the relative widths
\r
92 # - If there are a mixture of relative and absolute widths,
\r
93 # - If the table width is absolute, turn these all into absolute
\r
95 # - If the table width is relative, turn these all into absolute
\r
96 # widths in the nominalWidth and then turn them back into
\r
102 for absPart in absParts:
\r
104 inches = absPart / pixelsPerInch
\r
105 widths.append("%4.2fin" % inches)
\r
107 widths.append("%d" % absPart)
\r
108 elif absTotal == 0:
\r
109 for relPart in relParts:
\r
110 rel = relPart / relTotal * 100
\r
112 widths = correctRoundingError(widths)
\r
114 pixelWidth = nominalWidth
\r
115 if string.find(tableWidth, "%") < 0:
\r
116 pixelWidth = convertLength(tableWidth)
\r
118 if pixelWidth <= absTotal:
\r
119 print "Table is wider than table width"
\r
121 pixelWidth = pixelWidth - absTotal
\r
124 for count in range(len(relParts)):
\r
125 rel = relParts[count] / relTotal * pixelWidth
\r
126 relParts[count] = rel + absParts[count]
\r
127 absTotal = absTotal + rel + absParts[count]
\r
129 if string.find(tableWidth, "%") < 0:
\r
130 for count in range(len(relParts)):
\r
132 pixels = relParts[count]
\r
133 inches = pixels / pixelsPerInch
\r
134 widths.append("%4.2fin" % inches)
\r
136 widths.append(relParts[count])
\r
138 for count in range(len(relParts)):
\r
139 rel = relParts[count] / absTotal * 100
\r
141 widths = correctRoundingError(widths)
\r
143 # Danger, Will Robinson! In-place modification of the result tree!
\r
144 # Side-effect free? We don' need no steenkin' side-effect free!
\r
149 col.setProp("column-width", widths[count])
\r
151 col.setProp("width", widths[count])
\r
158 def convertLength(length):
\r
159 # Given "3.4in" return the width in pixels
\r
160 global pixelsPerInch
\r
163 m = re.search('([+-]?[\d\.]+)(\S+)', length)
\r
164 if m != None and m.lastindex > 1:
\r
165 unit = pixelsPerInch
\r
166 if unitHash.has_key(m.group(2)):
\r
167 unit = unitHash[m.group(2)]
\r
169 print "Unrecognized length: " + m.group(2)
\r
171 pixels = unit * float(m.group(1))
\r
177 def correctRoundingError(floatWidths):
\r
178 # The widths are currently floating point numbers, we have to truncate
\r
179 # them back to integers and then distribute the error so that they sum
\r
184 for width in floatWidths:
\r
185 width = math.floor(width)
\r
186 widths.append(width)
\r
187 totalWidth = totalWidth + math.floor(width)
\r
189 totalError = 100 - totalWidth
\r
190 columnError = totalError / len(widths)
\r
192 for count in range(len(widths)):
\r
193 width = widths[count]
\r
194 error = error + columnError
\r
196 adj = math.floor(error)
\r
197 error = error - adj
\r
198 widths[count] = "%d%%" % (width + adj)
\r
200 widths[count] = "%d%%" % width
\r
204 def lookupVariable(tctxt, varName, default):
\r
205 varString = tctxt.variableLookup(varName, None)
\r
206 if varString == None:
\r
209 # If it's a list, get the first element
\r
210 if type(varString) == type([]):
\r
211 varString = varString[0]
\r
213 # If it's not a string, it must be a node, get its content
\r
214 if type(varString) != type(""):
\r
215 varString = varString.content
\r
219 # ======================================================================
\r
222 #once you have a node which is a libxml2 python xmlNode wrapper all common
\r
223 #operations are possible:
\r
224 # .children .last .parent .next .prev .doc for navigation
\r
225 # .content .type for introspection
\r
226 # .prop("attribute_name") to lookup attribute values
\r
228 # # Now make a nodeset to return
\r
229 # # Danger, Will Robinson! This creates a memory leak!
\r
230 # newDoc = libxml2.newDoc("1.0")
\r
231 # newColGroup = newDoc.newDocNode(None, "colgroup", None)
\r
232 # newDoc.addChild(newColGroup)
\r
233 # col = colgroup.children
\r
234 # while col != None:
\r
235 # newCol = newDoc.newDocNode(None, "col", None)
\r
236 # newCol.copyPropList(col);
\r
237 # newCol.setProp("width", "4")
\r
238 # newColGroup.addChild(newCol)
\r