+++ /dev/null
-# docbook.py: extension module\r
-# $Id: docbook.py 8353 2009-03-17 16:57:50Z mzjn $\r
-\r
-import sys\r
-import string\r
-import libxml2\r
-import libxslt\r
-import re\r
-import math\r
-\r
-# Some globals\r
-pixelsPerInch = 96.0\r
-unitHash = { 'in': pixelsPerInch,\r
- 'cm': pixelsPerInch / 2.54,\r
- 'mm': pixelsPerInch / 25.4,\r
- 'pc': (pixelsPerInch / 72.0) * 12,\r
- 'pt': pixelsPerInch / 72.0,\r
- 'px': 1 }\r
-\r
-# ======================================================================\r
-\r
-def adjustColumnWidths(ctx, nodeset):\r
- #\r
- # Small check to verify the context is correcly accessed\r
- #\r
- try:\r
- pctxt = libxslt.xpathParserContext(_obj=ctx)\r
- ctxt = pctxt.context()\r
- tctxt = ctxt.transformContext()\r
- except:\r
- pass\r
-\r
- # Get the nominal table width\r
- varString = lookupVariable(tctxt, "nominal.table.width", None)\r
- if varString == None:\r
- nominalWidth = 6 * pixelsPerInch;\r
- else:\r
- nominalWidth = convertLength(varString);\r
-\r
- # Get the requested table width\r
- tableWidth = lookupVariable(tctxt, "table.width", "100%")\r
-\r
- foStylesheet = (tctxt.variableLookup("stylesheet.result.type", None) == "fo")\r
-\r
- relTotal = 0\r
- relParts = []\r
-\r
- absTotal = 0\r
- absParts = []\r
-\r
- colgroup = libxml2.xmlNode(_obj = nodeset[0])\r
- # If this is an foStylesheet, we've been passed a list of fo:table-columns.\r
- # Otherwise we've been passed a colgroup that contains a list of cols.\r
- if foStylesheet:\r
- colChildren = colgroup\r
- else:\r
- colChildren = colgroup.children\r
-\r
- col = colChildren\r
- while col != None:\r
- if foStylesheet:\r
- width = col.prop("column-width")\r
- else:\r
- width = col.prop("width")\r
-\r
- if width == None:\r
- width = "1*"\r
-\r
- relPart = 0.0\r
- absPart = 0.0\r
- starPos = string.find(width, "*")\r
- if starPos >= 0:\r
- relPart, absPart = string.split(width, "*", 2)\r
- relPart = float(relPart)\r
- relTotal = relTotal + float(relPart)\r
- else:\r
- absPart = width\r
-\r
- pixels = convertLength(absPart)\r
- absTotal = absTotal + pixels\r
-\r
- relParts.append(relPart)\r
- absParts.append(pixels)\r
-\r
- col = col.next\r
-\r
- # Ok, now we have the relative widths and absolute widths in\r
- # two parallel arrays.\r
- #\r
- # - If there are no relative widths, output the absolute widths\r
- # - If there are no absolute widths, output the relative widths\r
- # - If there are a mixture of relative and absolute widths,\r
- # - If the table width is absolute, turn these all into absolute\r
- # widths.\r
- # - If the table width is relative, turn these all into absolute\r
- # widths in the nominalWidth and then turn them back into\r
- # percentages.\r
-\r
- widths = []\r
-\r
- if relTotal == 0:\r
- for absPart in absParts:\r
- if foStylesheet:\r
- inches = absPart / pixelsPerInch\r
- widths.append("%4.2fin" % inches)\r
- else:\r
- widths.append("%d" % absPart)\r
- elif absTotal == 0:\r
- for relPart in relParts:\r
- rel = relPart / relTotal * 100\r
- widths.append(rel)\r
- widths = correctRoundingError(widths)\r
- else:\r
- pixelWidth = nominalWidth\r
- if string.find(tableWidth, "%") < 0:\r
- pixelWidth = convertLength(tableWidth)\r
-\r
- if pixelWidth <= absTotal:\r
- print "Table is wider than table width"\r
- else:\r
- pixelWidth = pixelWidth - absTotal\r
-\r
- absTotal = 0\r
- for count in range(len(relParts)):\r
- rel = relParts[count] / relTotal * pixelWidth\r
- relParts[count] = rel + absParts[count]\r
- absTotal = absTotal + rel + absParts[count]\r
-\r
- if string.find(tableWidth, "%") < 0:\r
- for count in range(len(relParts)):\r
- if foStylesheet:\r
- pixels = relParts[count]\r
- inches = pixels / pixelsPerInch\r
- widths.append("%4.2fin" % inches)\r
- else:\r
- widths.append(relParts[count])\r
- else:\r
- for count in range(len(relParts)):\r
- rel = relParts[count] / absTotal * 100\r
- widths.append(rel)\r
- widths = correctRoundingError(widths)\r
-\r
- # Danger, Will Robinson! In-place modification of the result tree!\r
- # Side-effect free? We don' need no steenkin' side-effect free!\r
- count = 0\r
- col = colChildren\r
- while col != None:\r
- if foStylesheet:\r
- col.setProp("column-width", widths[count])\r
- else:\r
- col.setProp("width", widths[count])\r
-\r
- count = count+1\r
- col = col.next\r
-\r
- return nodeset\r
-\r
-def convertLength(length):\r
- # Given "3.4in" return the width in pixels\r
- global pixelsPerInch\r
- global unitHash\r
-\r
- m = re.search('([+-]?[\d\.]+)(\S+)', length)\r
- if m != None and m.lastindex > 1:\r
- unit = pixelsPerInch\r
- if unitHash.has_key(m.group(2)):\r
- unit = unitHash[m.group(2)]\r
- else:\r
- print "Unrecognized length: " + m.group(2)\r
-\r
- pixels = unit * float(m.group(1))\r
- else:\r
- pixels = 0\r
-\r
- return pixels\r
-\r
-def correctRoundingError(floatWidths):\r
- # The widths are currently floating point numbers, we have to truncate\r
- # them back to integers and then distribute the error so that they sum\r
- # to exactly 100%.\r
-\r
- totalWidth = 0\r
- widths = []\r
- for width in floatWidths:\r
- width = math.floor(width)\r
- widths.append(width)\r
- totalWidth = totalWidth + math.floor(width)\r
-\r
- totalError = 100 - totalWidth\r
- columnError = totalError / len(widths)\r
- error = 0\r
- for count in range(len(widths)):\r
- width = widths[count]\r
- error = error + columnError\r
- if error >= 1.0:\r
- adj = math.floor(error)\r
- error = error - adj\r
- widths[count] = "%d%%" % (width + adj)\r
- else:\r
- widths[count] = "%d%%" % width\r
-\r
- return widths\r
-\r
-def lookupVariable(tctxt, varName, default):\r
- varString = tctxt.variableLookup(varName, None)\r
- if varString == None:\r
- return default\r
-\r
- # If it's a list, get the first element\r
- if type(varString) == type([]):\r
- varString = varString[0]\r
-\r
- # If it's not a string, it must be a node, get its content\r
- if type(varString) != type(""):\r
- varString = varString.content\r
-\r
- return varString\r
-\r
-# ======================================================================\r
-# Random notes...\r
-\r
-#once you have a node which is a libxml2 python xmlNode wrapper all common\r
-#operations are possible:\r
-# .children .last .parent .next .prev .doc for navigation\r
-# .content .type for introspection\r
-# .prop("attribute_name") to lookup attribute values\r
-\r
-# # Now make a nodeset to return\r
-# # Danger, Will Robinson! This creates a memory leak!\r
-# newDoc = libxml2.newDoc("1.0")\r
-# newColGroup = newDoc.newDocNode(None, "colgroup", None)\r
-# newDoc.addChild(newColGroup)\r
-# col = colgroup.children\r
-# while col != None:\r
-# newCol = newDoc.newDocNode(None, "col", None)\r
-# newCol.copyPropList(col);\r
-# newCol.setProp("width", "4")\r
-# newColGroup.addChild(newCol)\r
-# col = col.next\r