def draw_rectangles_for_solution(self, f_in, f_out, solution, points): """Drawing green filled rectangles near the correct answers for every problem, in order to indicate the correct solution. It calculates and writes the total score achieved too. Parameters: f_in (str): Path to the input PDF file. f_out (str): Path to the output PDF file. solution (dict): The solution (correct answers) corresponding to the input PDF file (f_in). points (float): Total points achieved. """ pr = PdfFileReader(f_in) dest = pr.getNamedDestinations() fields = pr.getFields() # """IT IS NOT WORKING IF THIS COMES FIRST:""" # a = PdfAnnotator(f_in) # for p in range(pr.getNumPages()): # for dk, dv in dest.items(): # if pr.getDestinationPageNumber(dv) == p and dk.startswith('ht_'): # inds = [int(ind) for ind in dk[3:].split(':')] # # if inds[2] in solution[inds[1]][1]: # if inds[4] in solution[inds[1]][1]: # # using some hard-coded values: # a.add_annotation('square', # Location(x1=float(dv['/Left']), y1=float(dv['/Top']), x2=float(dv['/Left'])+5, y2=float(dv['/Top'])+5, page=p), # Appearance(stroke_color=(0, 1, 0), stroke_width=5),) # a.write(f_out) pw = PdfFileWriter() # pr = PdfFileReader(f_out, strict=False) pr = PdfFileReader(f_in, strict=False) pw.appendPagesFromReader(pr) pw._root_object.update( {NameObject("/AcroForm"): pr.trailer["/Root"]["/AcroForm"]}) pw._root_object["/AcroForm"].update( {NameObject("/NeedAppearances"): BooleanObject(True)}) for p in range(pr.getNumPages()): self._update_page_form_checkbox_values(pw.getPage(p), { fk: fv['/V'] for fk, fv in fields.items() if '/V' in fv.keys() }) # sometimes '/V' disappears from the keys self._update_page_form_checkbox_values(pw.getPage(0), {'points': str(points)}) f = codecs.open(f_out, 'wb') pw.write(f) f.close() a = PdfAnnotator(f_out) for p in range(pr.getNumPages()): for dk, dv in dest.items(): if pr.getDestinationPageNumber(dv) == p and dk.startswith( 'ht_'): inds = [int(ind) for ind in dk[3:].split(':')] # if inds[2] in solution[inds[1]][1]: if inds[4] in solution[inds[1]][1]: # using some hard-coded values: a.add_annotation( 'square', Location(x1=float(dv['/Left']), y1=float(dv['/Top']), x2=float(dv['/Left']) + 5, y2=float(dv['/Top']) + 5, page=p), Appearance(stroke_color=(0, 1, 0), stroke_width=5), ) a.write(f_out)
def annotate(fp_in, annotations): reader = PdfFileReader(fp_in) pdf = PdfFileWriter() for page in reader.pages: pdf.addPage(page) for annotation in annotations: page = annotation.get('page', 0) try: pdfpage = pdf.getPage(page) except IndexError: print >> sys.stderr, 'Page %d not found in pdf, not adding annotations %r' % ( page, annotation) continue size = pdfpage.mediaBox angle = int(pdfpage.get('/Rotate', 0)) x = annotation['x'] y = annotation['y'] if angle == 0: x = float(x) y = size[3] - float(y) - 20 elif angle == 90: x, y = float(y) - 2, float(x) - 15 else: x = float(x) y = float(y) print >> sys.stderr, 'Page rotated by %d degrees not implemented yet' % ( angle) color = annotation.get('color', None) if isinstance(color, basestring): if color[:1] != '#': print >> sys.stderr, 'Unsupported color format: %s' % (color) color = None else: # Assume HTML color with format "#RRGGBB". try: color = int(color[1:], 16) except ValueError as e: print >> sys.stderr, 'Unsupported color format: %s (%s)' % ( color, e) color = None if color is not None: r, g, b = color >> 16, (color >> 8) & 0xff, color & 0xff color = (r * BYTE_TO_COLOR, g * BYTE_TO_COLOR, b * BYTE_TO_COLOR) else: color = None pages = pdf.getObject(pdf._pages) pageref = pages["/Kids"][page] anno = DictionaryObject() anno.update({ NameObject('/Type'): NameObject('/Annot'), NameObject('/Subtype'): NameObject('/Text'), NameObject('/P'): pageref, NameObject('/Rect'): RectangleObject([x, y, x + 18, y + 20]), NameObject('/Contents'): TextStringObject(annotation['text']), NameObject('/C'): ArrayObject([FloatObject(x) for x in color]), NameObject('/Open'): BooleanObject(True), }) author = annotation.get('author', None) if author: anno[NameObject('/T')] = TextStringObject(author) modified = annotation.get('modified', None) if modified: modified = time.strftime('%Y%m%d%H%M%SZ', time.gmtime(modified)) anno[NameObject('/M')] = TextStringObject(modified) annoRef = pdf._addObject(anno) annots = pdfpage.get('/Annots', None) if annots is None: annots = pdfpage[NameObject('/Annots')] = ArrayObject([annoRef]) else: annots.append(annoRef) fp_out = StringIO() pdf.write(fp_out) return fp_out.getvalue()