class ProjBackground (object) : def __init__(self, pid, gid = None) : '''Intitate the whole class and create the object.''' # import pdb; pdb.set_trace() self.pid = pid self.gid = gid self.local = ProjLocal(pid, gid) self.tools = Tools() self.proj_config = Config(pid, gid) self.proj_config.getProjectConfig() self.proj_config.getLayoutConfig() self.projectConfig = self.proj_config.projectConfig self.layoutConfig = self.proj_config.layoutConfig self.log = ProjLog(pid) self.user = UserConfig() self.userConfig = self.user.userConfig self.projHome = os.path.join(os.environ['RAPUMA_PROJECTS'], self.pid) self.mmToPx = 72 / 25.4 # For debugging purposes a switch can be set here for verbose # message output via the terminal self.debugMode = self.tools.str2bool(self.userConfig['System']['debugging']) # Log messages for this module self.errorCodes = { '0000' : ['MSG', 'Placeholder message'], '1110' : ['MSG', 'File exsits: [<<1>>]. Use \"force\" to remove it.'], '1280' : ['ERR', 'Failed to merge background file with command: [<<1>>]. This is the error: [<<2>>]'], '1290' : ['ERR', 'Failed to convert background file [<<1>>]. Error: [<<2>>] The command was: [<<3>>]'], '1300' : ['MSG', 'Background merge operation in process, please wait...'], '1305' : ['MSG', 'Adding document information, please wait...'], '1310' : ['WRN', 'Failed to add background component: [<<1>>] with error: [<<2>>]'], '1320' : ['MSG', 'New background created.'] } ############################################################################### ############################### Basic Functions ############################### ############################################################################### ######################## Error Code Block Series = 1000 ####################### ############################################################################### def turnOnBackground (self) : '''Change the layout config settings to turn on the background.''' if not self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useBackground']) : self.layoutConfig['DocumentFeatures']['useBackground'] = True self.tools.writeConfFile(self.layoutConfig) def turnOffBackground (self) : '''Change the layout config settings to turn off the background.''' if self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useBackground']) : self.layoutConfig['DocumentFeatures']['useBackground'] = False self.tools.writeConfFile(self.layoutConfig) def turnOnDocInfo (self) : '''Change the layout config settings to turn on the doc info in the background.''' if not self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useDocInfo']) : self.layoutConfig['DocumentFeatures']['useDocInfo'] = True self.tools.writeConfFile(self.layoutConfig) def turnOffDocInfo (self) : '''Change the layout config settings to turn off the doc info in the background.''' if self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useDocInfo']) : self.layoutConfig['DocumentFeatures']['useDocInfo'] = False self.tools.writeConfFile(self.layoutConfig) def addBackground (self, target) : '''Add a background (watermark) to a rendered PDF file. This will figure out what the background is to be composed of and create a master background page. Using force will cause it to be remade.''' # Do a quick check if the background needs to be remade # The background normally is not remade if one already exists. # If one is there, it can be remade if regenerate is set to # to True. Obviously, if one is not there, it will be made. if self.tools.str2bool(self.layoutConfig['DocumentFeatures']['regenerateBackground']) : self.createBackground() else : # If there isn't one, make it if not os.path.exists(self.local.backgroundFile) : self.createBackground() # Merge target with the project's background file in the Illustraton folder self.log.writeToLog(self.errorCodes['1300']) # Create a special name for the file with the background # Then merge and save it viewFile = self.tools.alterFileName(target, 'view') shutil.copy(self.tools.mergePdfFilesPdftk(self.centerOnPrintPage(target), self.local.backgroundFile), viewFile) # Not returning a file name would mean it failed if os.path.exists(viewFile) : return viewFile def addDocInfo (self, target) : '''Add (merge) document information to the rendered target doc.''' # Initialize the process docInfoText = self.layoutConfig['DocumentFeatures']['docInfoText'] timestamp = self.tools.tStamp() if self.gid : headerLine = self.pid + ' / ' + self.gid + ' / ' + timestamp else : headerLine = self.pid + ' / ' + timestamp svgFile = tempfile.NamedTemporaryFile().name ## RENDERED PAGE DIMENSIONS (body) # This can be determined with the pyPdf element # "pdf.getPage(0).mediaBox", which returns a # RectangleObject([0, 0, Width, Height]). The # width and height are in points. Hopefully we will # always be safe by measuring the gidPdfFile size. #pdf = PdfFileReader(open(self.local.gidPdfFile,'rb')) #var2 = pdf.getPage(0).mediaBox #trimWidth = float(var2.getWidth()) #trimHeight = float(var2.getHeight()) trimWidth = float(self.layoutConfig['PageLayout']['pageWidth']) trimHeight = float(self.layoutConfig['PageLayout']['pageHeight']) # Printer page size pps = self.printerPageSize() ppsWidth = pps[0] ppsHeight = pps[1] ppsCenter = ppsWidth/2 # Write out SVG document text with codecs.open(svgFile, 'wb') as fbackgr : # open file for writing fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(ppsWidth) + '''" height = "''' + str(ppsHeight) + '''"> <g><text x = "''' + str(ppsCenter) + '''" y = "''' + str(20) + '''" style="font-family:DejaVu Sans;font-style:regular;font-size:8;text-anchor:middle;fill:#000000;fill-opacity:1">''' + headerLine + '''</text></g> <g><text x = "''' + str(ppsCenter) + '''" y = "''' + str(ppsHeight-30) + '''" style="font-family:DejaVu Sans;font-style:regular;font-size:8;text-anchor:middle;fill:#000000;fill-opacity:1">''' + self.tools.fName(target) + '''</text></g> <g><text x = "''' + str(ppsCenter) + '''" y = "''' + str(ppsHeight-20) + '''" style="font-family:DejaVu Sans;font-style:regular;font-size:8;text-anchor:middle;fill:#000000;fill-opacity:1">''' + docInfoText + '''</text></g> </svg>''') # Merge target with the background self.log.writeToLog(self.errorCodes['1305']) # Create a special name for the file with the background viewFile = self.tools.alterFileName(target, 'view') # Compare the new file name with the target to see if we are # already working with a background file if viewFile == target : # If the target is a BG file all we need to do is merge it self.tools.mergePdfFilesPdftk(viewFile, self.tools.convertSvgToPdfRsvg(svgFile)) else : # If not a BG file, we need to be sure the target is the same # size as the print page to merge with pdftk shutil.copy(self.tools.mergePdfFilesPdftk(self.centerOnPrintPage(target), self.tools.convertSvgToPdfRsvg(svgFile)), viewFile) # Not returning a file name would mean it failed if os.path.exists(viewFile) : return viewFile ##### Background Creation Functions ##### def createBackground (self) : '''Create a background file. This will overwrite any existing background file and will add each recognized background type found in the bacgroundComponents config setting.''' self.createBlankBackground() # Add each component to the blank background file for comp in self.layoutConfig['DocumentFeatures']['backgroundComponents'] : try : getattr(self, 'merge' + comp.capitalize())() except Exception as e : self.log.writeToLog(self.errorCodes['1310'],[comp,str(e)]) pass self.log.writeToLog(self.errorCodes['1320']) return True def createBlankBackground (self) : '''Create a blank background page according to the print page size specified.''' # Set the temp svg file name svgFile = tempfile.NamedTemporaryFile().name # Printer page size pps = self.printerPageSize() ppsWidth = pps[0] ppsHeight = pps[1] # Be sure there is an illustrations folder in place if not os.path.isdir(self.local.projIllustrationFolder) : os.mkdir(self.local.projIllustrationFolder) # Write out SVG document text with codecs.open(svgFile, 'wb') as fbackgr : # open file for writing fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(ppsWidth) + '''" height = "''' + str(ppsHeight)+ '''"> </svg>''') shutil.copy(self.tools.convertSvgToPdfRsvg(svgFile), self.local.backgroundFile) def mergeWatermark (self) : '''Create a watermark file and return the file name. Using force will cause any exsiting versions to be recreated.''' # import pdb; pdb.set_trace() # Initialize the process pubProg = "Rapuma" watermarkText = self.layoutConfig['DocumentFeatures']['watermarkText'] svgFile = tempfile.NamedTemporaryFile().name ## RENDERED PAGE DIMENSIONS (body) # Trim page width [px] trimWidth = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageWidth']),1) # Trim page height [px] trimHeight = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageHeight']),1) # Printer page size [px] (ppsWidth, ppsHeight) = self.printerPageSize() pageX = ppsWidth/2 pageY = ppsHeight/2 # Write out SVG document text with codecs.open(svgFile, 'wb') as fbackgr : # open file for writing fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(ppsWidth) + '''" height = "''' + str(ppsHeight) + '''"> <g><text x = "''' + str(pageX-trimWidth*.42) + '''" y = "''' + str(pageY-trimHeight*0.39) + '''" style="font-family:DejaVu Sans;font-style:regular;font-size:32;text-anchor:start;fill:#d5d5f5;fill-opacity:1">''' + str(pubProg) + ''' <tspan x = "''' + str(pageX) + '''" y = "''' + str(pageY - trimHeight*0.22) + '''" style="text-anchor:middle">''' + str(pubProg) + '''</tspan> <tspan x = "''' + str(pageX+trimWidth*0.42)+ '''" y = "''' + str(pageY-trimHeight*0.05) + '''" style="text-anchor:end">''' + str(pubProg) + '''</tspan> <tspan x = "''' + str(pageX) + '''" y = "''' + str(pageY+trimHeight*0.12) + '''" style="text-anchor:middle">''' + str(pubProg) + '''</tspan> <tspan x = "''' + str(pageX-trimWidth*0.42) + '''" y = "''' + str(pageY+trimHeight*0.29) + '''" style="text-anchor:start">''' + str(pubProg) + '''</tspan> <tspan x = "''' + str(pageX+trimWidth*0.49) + '''" y = "''' + str(pageY+trimHeight*0.455) + '''" style="font-weight:bold;font-size:68;text-anchor:end">''' + watermarkText + ''' </tspan> </text></g></svg>''') # Convert the temp svg to pdf and merge into backgroundFile results = self.tools.mergePdfFilesPdftk(self.local.backgroundFile, self.tools.convertSvgToPdfRsvg(svgFile)) if os.path.isfile(results) : return True def mergeCropmarks (self) : '''Merge cropmarks on to the background page.''' # Initialize the process svgFile = tempfile.NamedTemporaryFile().name ## RENDERED PAGE DIMENSIONS (body) # Trim page width [px] trimWidth = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageWidth']),1) # Trim page height [px] trimHeight = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageHeight']),1) # Printer page size [px] pps = self.printerPageSize() ppsWidth = pps[0] ppsHeight = pps[1] with codecs.open(svgFile, 'wb') as fbackgr : # starting lines of SVG xml fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(ppsWidth) + '''" height = "''' + str(ppsHeight) + '''">\n''') # vertical top left fbackgr.write( '''<path d = "m''' + str((ppsWidth - trimWidth)/2) + ''',''' + str((ppsHeight - trimHeight)/2 - 32.0) + ''',v27," style="stroke:#000000;stroke-width:.2"/>\n''') # vertical bottom left fbackgr.write( '''<path d = "m''' + str((ppsWidth - trimWidth)/2) + ''',''' + str((ppsHeight + trimHeight)/2 + 5.0) + ''',v27" style="stroke:#000000;stroke-width:.2" />\n''') # vertical bottom right fbackgr.write( '''<path d = "m''' + str((ppsWidth + trimWidth)/2) + ''',''' + str((ppsHeight - trimHeight)/2 - 32.0) + ''',v27" style="stroke:#000000;stroke-width:.2"/>\n''') # vertical top right fbackgr.write( '''<path d = "m''' + str((ppsWidth + trimWidth)/2) + ''',''' + str((ppsHeight + trimHeight)/2 + 5.0) + ''',v27" style="stroke:#000000;stroke-width:.2" />\n''') # horzontal top left fbackgr.write( '''<path d =" m''' + str((ppsWidth - trimWidth)/2 - 32.0) + ''',''' + str((ppsHeight - trimHeight)/2) + ''',h27" style="stroke:#000000;stroke-width:.2" />\n''') # horzontal top right fbackgr.write( '''<path d =" m''' + str((ppsWidth + trimWidth)/2 + 5.0) + ''',''' + str((ppsHeight - trimHeight)/2) + ''',h27" style="stroke:#000000;stroke-width:.2" />\n''') # horzontal bottom right fbackgr.write( '''<path d =" m''' + str((ppsWidth - trimWidth)/2 - 32.0) + ''',''' + str((ppsHeight + trimHeight)/2) + ''',h27" style="stroke:#000000;stroke-width:.2" />\n''') # horzontal bottom left fbackgr.write( '''<path d =" m''' + str((ppsWidth + trimWidth)/2 +5.0) + ''',''' + str((ppsHeight + trimHeight)/2) + ''',h27" style="stroke:#000000;stroke-width:.2" />\n''') fbackgr.write( '''</svg>''') # Convert the temp svg to pdf and merge into backgroundFile results = self.tools.mergePdfFilesPdftk(self.local.backgroundFile, self.tools.convertSvgToPdfRsvg(svgFile)) if os.path.isfile(results) : return True def mergePagebox (self) : '''Merge a page box with the background page to be used for proof reading.''' # Initialize the process svgFile = tempfile.NamedTemporaryFile().name ## RENDERED PAGE DIMENSIONS (body) # Trim page width [px] trimWidth = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageWidth']),1) # Trim page height [px] trimHeight = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageHeight']),1) # Printer page size [px] pps = self.printerPageSize() ppsWidth = pps[0] ppsHeight = pps[1] with codecs.open(svgFile, 'wb') as fbackgr : # starting lines of SVG xml fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(ppsWidth) + '''" height = "''' + str(ppsHeight) + '''">''') # rectangle fbackgr.write( '''<rect x = "''' + str((ppsWidth - trimWidth)/2) + '''" y= "''' + str((ppsHeight - trimHeight)/2) + '''" height = "''' + str(trimHeight) + '''" width = "''' + str(trimWidth) + '''" style = "fill:none;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:.2"/> </svg>''') # Convert the temp svg to pdf and merge into backgroundFile results = self.tools.mergePdfFilesPdftk(self.local.backgroundFile, self.tools.convertSvgToPdfRsvg(svgFile)) if os.path.isfile(results) : return True # Depricated #def makeBgFileName (self, orgName) : #'''Alter the file name to reflect the fact it has a background #added to it. This assumes the file only has a single extention. #If that's not the case we're hosed.''' #name = orgName.split('.')[0] #ext = orgName.split('.')[1] ## Just in case this is the second pass #name = name.replace('-bg', '') #return name + '-bg.' + ext def centerOnPrintPage (self, contents) : '''Center a PDF file on the printerPageSize page. GhostScript is the only way to do this at this point.''' # import pdb; pdb.set_trace() tmpFile = tempfile.NamedTemporaryFile().name # Get the size of our printer page (ppsWidth, ppsHeight) = self.printerPageSize() (wo, ho) = self.getPageOffset() pageOffset = str(wo) + ' ' + str(ho) # Assemble the GhostScript command cmd = [ 'gs', '-o', tmpFile, '-sDEVICE=pdfwrite', '-dQUIET', '-dDEVICEWIDTHPOINTS=' + str(ppsWidth), '-dDEVICEHEIGHTPOINTS=' + str(ppsHeight), '-dFIXEDMEDIA', '-c', '<</PageOffset [' + str(pageOffset) + ']>>', 'setpagedevice', '-f', contents] if self.debugMode : self.tools.terminal('Debug Mode On: \centerOnPrintPage() command: ' + str(cmd)) # Run the process try: subprocess.call(cmd) # Return the name of the temp PDF return tmpFile except Exception as e : self.log.writeToLog(self.errorCodes['1280'], [str(cmd), str(e)]) # Return the temp file name for further processing def printerPageSize (self) : '''Return the width and height of the printer page size in points. Only US Letter and A4 are supported. If not specified return the page trim size.''' printerPageSizeCode = self.layoutConfig['PageLayout']['printerPageSizeCode'].lower() ## STANDARD PRINTER PAGE SIZES # The output page (printer page) is what the typeset page will be placed on # with a watermark behind it. There are only two page sizes supported. # They are A4 and US Letter. We will determine the size by the ID code # found in the layout.conf file. However, in some cases, for example # during the layout process, the trim size is what is needed. If # one of the two supported pages sizes are not used, this will defult # to the trim size. if printerPageSizeCode == 'a4' : return float(595), float(842) elif printerPageSizeCode == 'letter' : return float(612), float(792) else : # Just default to the page trim size (assumed mm coming in) factor mmToPx = 72 / 25.4 return float(int(self.layoutConfig['PageLayout']['pageWidth']) * self.mmToPx), float(int(self.layoutConfig['PageLayout']['pageHeight']) * self.mmToPx) def getPageOffset (self) : '''Return the amount of horizontal and vertical offset that will enable the page trim size to be centered on the printer page. If something other than A4 or Letter is being used, the offset returned will be zero as this only supports those two sizes. The offset is based on the starting point being the lower-left side corner of the page. ''' # Get the printer page size printerPageSizeCode = self.layoutConfig['PageLayout']['printerPageSizeCode'].lower() # Get the page trim size (assuming mm input)factor mmToPx = 72 / 25.4 trimWidth = int(self.layoutConfig['PageLayout']['pageWidth']) * self.mmToPx trimHeight = int(self.layoutConfig['PageLayout']['pageHeight']) * self.mmToPx # The trim size of the content page can never be bigger than # the printer page size. If so, the offset is 0 if printerPageSizeCode == 'a4' or printerPageSizeCode == 'letter' : (bw, bh) = self.printerPageSize() wo = float((bw/2)-(trimWidth/2)) ho = float((bh/2)-(trimHeight/2)) return wo, ho else : return 0, 0
class ProjDiagnose (object) : def __init__(self, pid, gid = None) : '''Intitate the whole class and create the object.''' # import pdb; pdb.set_trace() self.pid = pid self.gid = gid self.local = ProjLocal(pid, gid) self.tools = Tools() self.proj_config = Config(pid, gid) self.proj_config.getProjectConfig() self.proj_config.getLayoutConfig() self.layoutConfig = self.proj_config.layoutConfig self.user = UserConfig() self.userConfig = self.user.userConfig self.log = ProjLog(pid) # to [px] is 72/25.4 self.mmToPx = 72 / 25.4 # page width [px] self.paperPxWidth = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageWidth']),1) # page height [px] self.paperPxHeight = round(self.mmToPx * float(self.layoutConfig['PageLayout']['pageHeight']),1) # Log messages for this module self.errorCodes = { '0000' : ['MSG', 'Placeholder message'], '1310' : ['WRN', 'Failed to add diagnostic component: [<<1>>] with error: [<<2>>]'] } ############################################################################### ############################### Create Functions ############################## ############################################################################### ######################## Error Code Block Series = 1000 ####################### ############################################################################### def turnOnDiagnostic (self) : '''Change the layout config settings to turn on the diagnostic layer.''' if not self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useDiagnostic']) : self.layoutConfig['DocumentFeatures']['useDiagnostic'] = True self.tools.writeConfFile(self.layoutConfig) def turnOffDiagnostic (self) : '''Change the layout config settings to turn off the diagnostic layer.''' if self.tools.str2bool(self.layoutConfig['DocumentFeatures']['useDiagnostic']) : self.layoutConfig['DocumentFeatures']['useDiagnostic'] = False self.tools.writeConfFile(self.layoutConfig) def addTransparency (self, target, force = False) : '''Add a transparent layer to a rendered PDF file. This will add in diagnosing format issues. Using force will cause any existing layer file to be remade.''' # Do a quick check if the transparency needs to be remade # The transparency normally is not remade if one already exists. # If one is there, it can be remade in two ways, with a force # or a regenerate command. if force : self.createDiagnostic() elif self.tools.str2bool(self.layoutConfig['DocumentFeatures']['regenerateTransparency']) : self.createDiagnostic() else : # If there isn't one, make it if not os.path.exists(self.local.diagnosticFile) : self.createDiagnostic() # Create a special temp named file for the target tmpTarget = tempfile.NamedTemporaryFile().name # Copy the target to the tmpTarget shutil.copy(target, tmpTarget) # Overlay the transparency diagnostic file over the tmpTarget self.tools.mergePdfFilesPdftk(tmpTarget, self.local.diagnosticFile) # Create a special name for the file with the background # Then merge and save it viewFile = self.tools.alterFileName(target, 'view') # Copy the results back to the target (should be done now) shutil.copy(tmpTarget, viewFile) # Not returning a file name would mean it failed if os.path.exists(viewFile) : return viewFile def createDiagnostic (self) : '''Create a diagnostic transparency (file) that will be superimposed over the page contents to help diagnose format issues. This will overwrite any existing transparency file and will add each recognoized diagnostic type found in the diagnosticComponents config setting.''' # import pdb; pdb.set_trace() self.createBlankTransparency() # Add each component to the blank transparency file for comp in self.layoutConfig['DocumentFeatures']['diagnosticComponents'] : try : getattr(self, 'merge' + comp.capitalize())() except Exception as e : self.log.writeToLog(self.errorCodes['1310'],[comp,str(e)]) pass return True def createBlankTransparency (self) : '''Create a blank background page according to the trim size specified.''' # Set the temp svg file name svgFile = tempfile.NamedTemporaryFile().name # Be sure there is an illustrations folder in place if not os.path.isdir(self.local.projIllustrationFolder) : os.mkdir(self.local.projIllustrationFolder) # Write out SVG document text with codecs.open(svgFile, 'wb') as fbackgr : # open file for writing fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(self.paperPxWidth) + '''" height = "''' + str(self.paperPxHeight)+ '''"> </svg>''') shutil.copy(self.tools.convertSvgToPdfRsvg(svgFile), self.local.diagnosticFile) ############################################################################### ############################# Component Functions ############################# ############################################################################### ######################## Error Code Block Series = 2000 ####################### ############################################################################### def mergeLeading (self) : '''Create a diagnostic page component that has lines to indicate the text leading. This will be superimposed over the contents of the trim page, not in the background like a watermark, etc.''' # Initialize the process svgFile = tempfile.NamedTemporaryFile().name # PAGE DIMENSIONS # The page dimensions extracted from layoutConfig are in [mm] and # must be converted to pixels [px], the conversion factor for [mm] # bodyFontSize [px] bodyFontSize = self.layoutConfig['TextElements']['bodyFontSize'] bodyFontPxSize = round(float(bodyFontSize) * 72/72.27,3) # bodyTextLeading [px] bodyTextLeading = self.layoutConfig['TextElements']['bodyTextLeading'] bodyTextPxLeading = round(float(bodyTextLeading) * 72/72.27,3) # top margin [px] topMargin = self.layoutConfig['PageLayout']['topMargin'] topPxMargin = round(self.mmToPx * float(topMargin),1) # outside margin [px] outsideMargin = self.layoutConfig['PageLayout']['outsideMargin'] outsidePxMargin = round(self.mmToPx * float(outsideMargin),1) #inside margin [px] insideMargin = self.layoutConfig['PageLayout']['insideMargin'] insidePxMargin = round(self.mmToPx * float(outsideMargin),1) # bottom margin [px] bottomMargin = self.layoutConfig['PageLayout']['bottomMargin'] bottomPxMargin = round(self.mmToPx * float(bottomMargin),1) # width of the body text textPxWidth = self.paperPxWidth - (outsidePxMargin + insidePxMargin) # Create the svg file with codecs.open(svgFile, 'wb') as fbackgr : # open file for writing # starting lines of SVG xml fbackgr.write( '''<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width = "''' + str(self.paperPxWidth)+ '''" height = "'''+str(self.paperPxHeight) + '''"> \n <!--RECTANGLE OF MARGINS-->\n''') fbackgr.write( '''<rect x = "''' + str(outsidePxMargin) + '''" y= "''' + str(topPxMargin) + '''" height = "''' + str(self.paperPxHeight - topPxMargin - bottomPxMargin) + '''" width = "''' + str(textPxWidth) + '''" style = "fill:none;fill-opacity:1;stroke:#ffc800;stroke-opacity:1;stroke-width:.2"/> \n <!--START OF LINEGRID-->\n''') fbackgr.write( '''<path d= "m ''' + str(outsidePxMargin * 0.75-1) + "," + str(topPxMargin + bodyFontPxSize) + " " + str(textPxWidth + outsidePxMargin * 0.25)+ ''',0''') # filling the space between the top line and bottom margin, starting at distance # counter num = 0 up to the but not including the total of num x leading # equals the distance between top and bottom margin num = 0 while (num < int(round(self.paperPxHeight - bottomPxMargin - topPxMargin)/bodyTextPxLeading)): # lines are drawn in zigzag pattern: RTL when num is even and LTR when odd if num%2 == 0: fbackgr.write( ''' m 0, ''' + str(bodyTextPxLeading) + " -" + str(textPxWidth + outsidePxMargin * 0.25)+ ''',0''') else: fbackgr.write( ''' m 0, ''' + str(bodyTextPxLeading) + " " + str(textPxWidth + outsidePxMargin * 0.25)+ ''',0''') num = num +1 # draw all lines with following style fbackgr.write( '''" style="stroke-width:0.2px;stroke:#ffc800;stroke-opacity:1"/> \n <!--LINE NUMBERS-->\n''') # add line number '1' to top line just left of margin fbackgr.write( '''<text x="''' + str(outsidePxMargin * 0.75-2) + '''" y="''' + str(topPxMargin + bodyFontPxSize-3) + '''" style="font-family: Charis SIL;font-style:italic;font-size:7;fill:#760076"> 1''') # add line numbers to all lines down to bottom margin, starting with line number # counter linecount = 2, the distance counter runs from '0' till one short of # the quotient (distance between top and bottom margin)/bodyTextPxLeading num = 0 # line counter linenumber = 2 # line number while (num < int(round(self.paperPxHeight - bottomPxMargin - topPxMargin)/bodyTextPxLeading)): fbackgr.write( '''<tspan x="''' + str(outsidePxMargin * 0.75-2) + '''" dy="''' + str(bodyTextPxLeading) + '''">''' + str(linenumber) + '''</tspan>''') linenumber = linenumber +1 num = num +1 fbackgr.write('''</text> \n <!--LINEGRID CAPTION--> <text x="36" y="''' + str(self.paperPxHeight - bottomPxMargin+10) + '''" style="font-family: Charis SIL;font-style:italic;font-size:7;fill:#ffc800">page size: ''' + str(int(self.paperPxWidth/72*25.4+.5)) + ''' x ''' + str(int(self.paperPxHeight/72*25.4+.5)) + ''' mm ; font size: ''' + str(bodyFontSize) + ''' pt; leading: ''' + str(bodyTextLeading) + ''' pt</text> \n <!--PURPLE LINES TOP AND BOTTOM MARGINS--> <path d="M ''' + str(outsidePxMargin) + "," + str(topPxMargin) + " " + str(textPxWidth + outsidePxMargin) + "," + str(topPxMargin) + '''" style="fill:#ffffff;fill-opacity:1;stroke-width:0.4px;stroke:#760076;stroke-opacity:1"/> <path d="M ''' + str(outsidePxMargin) + "," + str(self.paperPxHeight - bottomPxMargin) + " " + str(textPxWidth + outsidePxMargin) + "," + str(self.paperPxHeight - bottomPxMargin) + '''" style="fill:#ffffff;fill-opacity:1;stroke-width:0.4px;stroke:#760076;stroke-opacity:1"/> </svg>''') # Convert the lines background component to PDF leadingPdf = self.tools.convertSvgToPdfRsvg(svgFile) # Merge leadingPdf with existing transparency results = self.tools.mergePdfFilesPdftk(self.local.diagnosticFile, leadingPdf) # Test and return if good if os.path.isfile(results) : return True