# -*- coding: utf-8 -*- GlobalPVersion='1.6' import os,os.path,sys,time def getdimension(fichierimage): import ctypes BOOL = ctypes.c_int class GdiplusStartupInput(ctypes.Structure): _fields_ = [ ('GdiplusVersion', ctypes.c_uint32), ('DebugEventCallback', ctypes.c_void_p), ('SuppressBackgroundThread', BOOL), ('SuppressExternalCodecs', BOOL) ] class GdiplusStartupOutput(ctypes.Structure): _fields = [ ('NotificationHookProc', ctypes.c_void_p), ('NotificationUnhookProc', ctypes.c_void_p) ] i = GdiplusStartupInput() o = GdiplusStartupOutput() token = ctypes.c_ulong() i.GdiplusVersion = 1 ctypes.windll.gdiplus.GdiplusStartup(ctypes.byref(token), ctypes.byref(i), ctypes.byref(o)) data = open(fichierimage,"rb").read() # Create a HGLOBAL with image data GMEM_MOVEABLE = ctypes.c_int(2) hglob = ctypes.windll.kernel32.GlobalAlloc(GMEM_MOVEABLE, len(data)) ptr = ctypes.windll.kernel32.GlobalLock(hglob) ctypes.memmove(ptr, data, len(data)) ctypes.windll.kernel32.GlobalUnlock(hglob) stream = ctypes.c_void_p() ctypes.windll.ole32.CreateStreamOnHGlobal(hglob, True, ctypes.byref(stream)) bitmap = ctypes.c_void_p() status = ctypes.windll.gdiplus.GdipCreateBitmapFromStream(stream, ctypes.byref(bitmap)) if status != 0: raise "GDI+ probleme sur l'image " width = ctypes.c_uint() height = ctypes.c_uint() ctypes.windll.gdiplus.GdipGetImageWidth(bitmap, ctypes.byref(width)) ctypes.windll.gdiplus.GdipGetImageHeight(bitmap, ctypes.byref(height)) #print "Width", width.value #print "Height", height.value return width.value,height.value class minipdf(object): ccm=28.3464566929 def __init__(self): #self.fond=open("squ1.pdf","r").read() self.fond=ur"""%PDF-1.3 %“Œ‹ž Ponx % 'BasicFonts': class PDFDictionary 1 0 obj % The standard fonts dictionary << /F1 2 0 R /F10 11 0 R /F11 12 0 R /F12 13 0 R /F13 14 0 R /F14 15 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R /F5 6 0 R /F6 7 0 R /F7 8 0 R /F8 9 0 R /F9 10 0 R >> endobj % 'F1': class PDFType1Font 2 0 obj % Font Helvetica << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> endobj % 'F2': class PDFType1Font 3 0 obj % Font Symbol << /BaseFont /Symbol /Encoding /SymbolEncoding /Name /F2 /Subtype /Type1 /Type /Font >> endobj % 'F3': class PDFType1Font 4 0 obj % Font ZapfDingbats << /BaseFont /ZapfDingbats /Encoding /ZapfDingbatsEncoding /Name /F3 /Subtype /Type1 /Type /Font >> endobj % 'F4': class PDFType1Font 5 0 obj % Font Courier << /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font >> endobj % 'F5': class PDFType1Font 6 0 obj % Font Courier-Bold << /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font >> endobj % 'F6': class PDFType1Font 7 0 obj % Font Courier-BoldOblique << /BaseFont /Courier-BoldOblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font >> endobj % 'F7': class PDFType1Font 8 0 obj % Font Courier-Oblique << /BaseFont /Courier-Oblique /Encoding /WinAnsiEncoding /Name /F7 /Subtype /Type1 /Type /Font >> endobj % 'F8': class PDFType1Font 9 0 obj % Font Helvetica-Bold << /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F8 /Subtype /Type1 /Type /Font >> endobj % 'F9': class PDFType1Font 10 0 obj % Font Helvetica-BoldOblique << /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F9 /Subtype /Type1 /Type /Font >> endobj % 'F10': class PDFType1Font 11 0 obj % Font Helvetica-Oblique << /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F10 /Subtype /Type1 /Type /Font >> endobj % 'F11': class PDFType1Font 12 0 obj % Font Times-Bold << /BaseFont /Times-Bold /Encoding /WinAnsiEncoding /Name /F11 /Subtype /Type1 /Type /Font >> endobj % 'F12': class PDFType1Font 13 0 obj % Font Times-BoldItalic << /BaseFont /Times-BoldItalic /Encoding /WinAnsiEncoding /Name /F12 /Subtype /Type1 /Type /Font >> endobj % 'F13': class PDFType1Font 14 0 obj % Font Times-Italic << /BaseFont /Times-Italic /Encoding /WinAnsiEncoding /Name /F13 /Subtype /Type1 /Type /Font >> endobj % 'F14': class PDFType1Font 15 0 obj % Font Times-Roman << /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Name /F14 /Subtype /Type1 /Type /Font >> endobj ...BUFFERPAGES... ...TEXTE... endstream endobj """ self.standardfontes={ 'Helvetica': [1, '_fontdata_widths_helvetica','_fontdata_enc_winansi'], 'Helvetica-Bold': [8, '_fontdata_widths_helveticabold','_fontdata_enc_winansi'], 'Helvetica-BoldOblique': [9, '_fontdata_widths_helveticaboldoblique','_fontdata_enc_winansi'], 'Helvetica-Oblique': [10,'_fontdata_widths_helveticaoblique','_fontdata_enc_winansi'], 'Courier': [4, '_fontdata_widths_courier','_fontdata_enc_winansi'], 'Courier-Bold': [5, '_fontdata_widths_courierbold','_fontdata_enc_winansi'], 'Courier-BoldOblique': [6, '_fontdata_widths_courierboldoblique','_fontdata_enc_winansi'], 'Courier-Oblique': [7, '_fontdata_widths_courieroblique','_fontdata_enc_winansi'], 'Times-Bold': [11,'_fontdata_widths_timesbold','_fontdata_enc_winansi'], 'Times-BoldItalic': [12,'_fontdata_widths_timesbolditalic','_fontdata_enc_winansi'], 'Times-Italic': [13,'_fontdata_widths_timesitalic','_fontdata_enc_winansi'], 'Times-Roman': [14,'_fontdata_widths_timesroman','_fontdata_enc_winansi'], 'Symbol': [2, '_fontdata_widths_symbol','_fontdata_enc_symbol'], 'ZapfDingbats': [3, '_fontdata_widths_zapfdingbats','_fontdata_enc_zapfdingbats'], } self._fontdata_code = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] self._fontdata_larg = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] import _fontdata_enc_winansi import _fontdata_widths_helvetica self._fontdata_code[1] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[1] = _fontdata_widths_helvetica.widths import _fontdata_widths_helveticabold self._fontdata_code[8] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[8] = _fontdata_widths_helveticabold.widths import _fontdata_widths_helveticaboldoblique self._fontdata_code[9] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[9] = _fontdata_widths_helveticaboldoblique.widths import _fontdata_widths_helveticaoblique self._fontdata_code[10] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[10] = _fontdata_widths_helveticaoblique.widths import _fontdata_widths_courier self._fontdata_code[4] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[4] = _fontdata_widths_courier.widths import _fontdata_widths_courierbold self._fontdata_code[5] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[5] = _fontdata_widths_courierbold.widths import _fontdata_widths_courierboldoblique self._fontdata_code[6] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[6] = _fontdata_widths_courierboldoblique.widths import _fontdata_widths_courieroblique self._fontdata_code[7] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[7] = _fontdata_widths_courieroblique.widths import _fontdata_widths_timesbold self._fontdata_code[11] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[11] = _fontdata_widths_timesbold.widths import _fontdata_widths_timesbolditalic self._fontdata_code[12] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[12] = _fontdata_widths_timesbolditalic.widths import _fontdata_widths_timesitalic self._fontdata_code[13] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[13] = _fontdata_widths_timesitalic.widths import _fontdata_widths_timesroman self._fontdata_code[14] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[14] = _fontdata_widths_timesroman.widths import _fontdata_widths_symbol self._fontdata_code[2] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[2] = _fontdata_widths_symbol.widths import _fontdata_widths_zapfdingbats self._fontdata_code[3] = _fontdata_enc_winansi.WinAnsiEncoding self._fontdata_larg[3] = _fontdata_widths_zapfdingbats.widths self.fonte=self.standardfontes['Helvetica'][0] self.buffer="" self.bufferpages="" self.taille=12 self.fichier=os.getcwd()+"\\exemple.pdf" self.numobj=15 self.prempage=self.numobj+1 self.parent=19 self.pagecourante=0 self.nbpages=0 self.mem={} def cm(self,val): if val: rval=val*self.ccm else: rval=0 return rval def cmx(self,val): if val: if self.orientation=="PAYSAGE": rval=(val-self.hauteur)*self.ccm else: rval=val*self.ccm else: rval=0 return rval def cmy(self,val): if val: if self.orientation=="PAYSAGE": rval=(self.largeur-val)*self.ccm else: rval=(self.hauteur-val)*self.ccm else: rval=0 return rval def anticm(self,val): if val: rval=val/self.ccm else: rval=0 return rval def gettextwidth(self, txt="Texte d'essai.", fontnum=None, fontsize=None): # retourne la largeur d'un texte if fontnum: fn=fontnum else: fn=self.standardfontes[self.fontname][0] if fontsize: fs=fontsize else: fs=self.fontsize numfont=fn largeur=0 for i in txt: try: cod=self._fontdata_code[numfont][ord(i)] except: cod='E' largeur += self._fontdata_larg[numfont][cod] return self.anticm(largeur/10.0*fs/100.0) def addpages(self, nbpages=1): buffer="" n=0 self.nbpages=nbpages nparent=self.numobj+nbpages+3 self.parent=nparent for i in range(nbpages): self.numobj+=1 n+=1 buffer+=""" % 'Page"""+str(n)+"""': class PDFPage """+str(self.numobj)+""" 0 obj % Page dictionary << /Contents """+str(nparent+n)+""" 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent """+str(nparent)+""" 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj """ self.numobj+=1 buffer += """% 'R"""+str(self.numobj)+"""': class PDFCatalog """+str(self.numobj)+""" 0 obj % Document Root << /Outlines """+str(self.parent+2)+""" 0 R /PageMode /UseNone /Pages """+str(self.parent)+""" 0 R /Type /Catalog >> endobj """ self.numobj+=1 buffer += """% 'R"""+str(self.numobj)+"""': class PDFInfo """+str(self.numobj)+""" 0 obj << /Author (anonymous) /CreationDate (D:...DATETIME...'00') /Creator (Ponx - pxminipdf) /Keywords () /Producer (Ponx) /Subject (unspecified) /Title (untitled) >> endobj """ tmp="" for j in range(nbpages): tmp+=" "+str(self.prempage+j)+""" 0 R """ self.numobj+=1 buffer += """% 'R"""+str(self.numobj)+"""': class PDFPages """+str(self.numobj)+""" 0 obj % page tree << /Count """+str(nbpages)+""" /Kids ["""+tmp+""" ] /Type /Pages >> endobj """ # supprimé self.bufferpages=buffer def color(self,col=(0,0,0)): r=str(col[0]/255.0) v=str(col[1]/255.0) b=str(col[2]/255.0) return r+" "+v+" "+b+" " def mem_texte(self, x=1,y=1,taille=12,text="TEXTE.", colortext=(255,255,255), colorcontour=(0,0,0), colorfond=(255,255,255), rotation=0, align='LEFT', fonte=None, page=None): """ Trace un texte text en position x,y de taille taille. La couleur du texte est colortext ; la couleur de contour colorcontour ; la couleur de fond colorfond. Si colorcontour=(0,0,0) ==> pas de contour rotation : uniquement 0 ou 45 ou -45 (en degrés) Les textes sont des objets tracés dans l'ordre de l'instanciation (Z-order) Attention : tous les textes sont en Arial. Exemple : opdf.texte(9,4,24, text="AZERTYUIOP") opdf.texte(12,12, taille=32, colortext=(127,255,127), colorcontour=(0,0,0), rotation=45, text="ZZZZZZZZZZ") """ if fonte is not None: try: self.fonte=self.standardfontes[fonte][0] except: self.fonte=self.standardfontes['Helvetica'][0] if self.taille != taille: self.taille = taille if align.startswith("PIVOT"): carpivot=align[-1] i=text.find(carpivot) if i<0: txtgauche=text else: txtgauche=text[:i] largeurtxt = self.gettextwidth(txt=txtgauche, fontnum=self.fonte, fontsize=self.taille) xx=str((x-largeurtxt)*28.34646)[:8] elif align=="RIGHT": largeurtxt = self.gettextwidth(txt=text, fontnum=self.fonte, fontsize=self.taille) xx=str((x-largeurtxt)*28.34646)[:8] elif align=="CENTER": largeurtxt = self.gettextwidth(txt=text, fontnum=self.fonte, fontsize=self.taille) xx=str((x-largeurtxt/2.0)*28.34646)[:8] else: xx=str(x*28.34646)[:8] yy=str(841.88976-(y*28.34646))[:8] item="" if page is None: if self.pagecourante==0: page=1 else: page = self.pagecourante if (page != self.pagecourante) and (page>1): item += """EI Q endstream endobj """ if self.pagecourante != page: self.pagecourante=page self.numobj+=1 item += """% 'R"""+str(self.numobj)+"""': class PDFStream """+str(page+self.parent)+""" 0 obj % page stream << /Length 1 >> stream """ if colorcontour!=(0,0,0): item += "2 Tr\n" item += self.color(colorcontour)+" RG\n" if colortext!=(255,255,255): item += self.color(colortext)+" rg\n" item += "/F"+str(self.fonte)+" "+str(taille)+" Tf\n" if rotation==90: item += "0 1 -1 0 0 0 cm\nBT 1 0 0 1 "+xx+" "+yy+" Tm ("+text+") Tj T* ET\n0 -1 1 0 0 0 cm\n" elif rotation==45: item += "BT 0.900 0.400 -0.400 0.900 "+xx+" "+yy+" Tm ("+text+") Tj T* ET\n" elif rotation==-45: item += "BT 0.900 -0.400 0.400 0.900 "+xx+" "+yy+" Tm ("+text+") Tj T* ET\n" else: item += "BT 1 0 0 1 "+xx+" "+yy+" Tm ("+text+") Tj T* ET\n" self.buffer += item def mem_ligne(self, lxy, epaisseur=2, colorline=(255,255,255), colorfill=(255,255,32)): """ Trace une polyligne reliant un ensemble de points lxy (*(x,y)) avec une épaisseur epaisseur, une ligne de contour colorline, un remplissage colorfill au coin haut gauche de la page. Les polylignes sont des objets tracés dans l'ordre de l'instanciation (Z-order) Exemple : opdf.ligne(((2,2), (8,6), (7,12), (18,20)), epaisseur=4, colorfill=(255,255,192), colorline=(0,0,128)) """ item = "" item += str(epaisseur)+" w\n" if colorline!=(0,0,0): item += self.color(colorline)+" RG\n" if colorfill!=(0,0,0): item += self.color(colorfill)+" rg\n" x=str(lxy[0][0]*28.34646)[:8] y=str(841.88976-(lxy[0][1]*28.34646))[:8] item += x+" "+y+" m\n" for xy in lxy[1:]: x=str(xy[0]*28.34646)[:8] y=str(841.88976-(xy[1]*28.34646))[:8] item += x+" "+y+" l\n" item += """b 0 J 0 w 0 G [ ] 0 d """ self.buffer += item def mem_rectangle(self, lxy, epaisseur=2, colorline=(255,255,255), colorfill=(255,255,32)): """ Trace un rectangle plein positionné et de taille lxy ((x,y),(l,h)) avec une épaisseur epaisseur, une ligne de contour colorline, un remplissage colorfill Le point x,y correspond au point haut gauche de l'image, par rapport au coin haut gauche de la page Les rectangles sont des objets tracés dans l'ordre de l'instanciation (Z-order) Exemple : opdf.rectangle(((4,12), (10,20)), epaisseur=4, colorfill=(233,255,255), colorline=(0,128,0)) """ item = "" if epaisseur==0: item += "0.1 w\n" else: item += str(epaisseur)+" w\n" if colorline!=(0,0,0): """ if epaisseur==0: item += self.color((255,255,255))+" RG\n" else: item += self.color(colorline)+" RG\n" """ item += self.color(colorline)+" RG\n" if colorfill!=(0,0,0): item += self.color(colorfill)+" rg\n" x=str(lxy[0][0]*28.34646)[:8] y=str(841.88976-(lxy[0][1]*28.34646))[:8] xx=str(lxy[1][0]*28.34646)[:8] yy=str(841.88976-(lxy[1][1]*28.34646))[:8] item += x+" "+y+" m\n" item += xx+" "+y+" l\n" item += xx+" "+yy+" l\n" item += x+" "+yy+" l\n" item += """b 0 J 0 w 0 G [ ] 0 d """ self.buffer += item def mem_image(self, x=1,y=1,zoom=1, fichier="L:\\vodka.jpg"): """ Positionne l'image en X,Y avec un zoom zoom, à partir du fichier fichier Le point x,y correspond au point bas gauche de l'image, par rapport au coin haut gauche de la page Attn: une seule image par page... L'image est toujours tracée par dessus les autres objets. Exemple : opdf.image( 4,7,28,1.25, os.getcwd()+"\\vodka.jpg") """ isize=getdimension(fichier) xx=str(x*28.34646)[:8] yy=str(841.88976-y*28.34646)[:8] ll=str(int(isize[0]*zoom)) hh=str(int(isize[1]*zoom)) def _AsciiBase85Encode(input): """Encodes input using ASCII-Base85 coding. This is a compact encoding used for binary data within a PDF file. Four bytes of binary data become five bytes of ASCII. This is the default method used for encoding images. """ # special rules apply if not a multiple of four bytes. whole_word_count, remainder_size = divmod(len(input), 4) cut = 4 * whole_word_count body, lastbit = input[0:cut], input[cut:] out = [].append for i in xrange(whole_word_count): offset = i*4 b1 = ord(body[offset]) b2 = ord(body[offset+1]) b3 = ord(body[offset+2]) b4 = ord(body[offset+3]) if b1<128: num = (((((b1<<8)|b2)<<8)|b3)<<8)|b4 else: num = 16777216L * b1 + 65536 * b2 + 256 * b3 + b4 if num == 0: #special case out('z') else: #solve for five base-85 numbers temp, c5 = divmod(num, 85) temp, c4 = divmod(temp, 85) temp, c3 = divmod(temp, 85) c1, c2 = divmod(temp, 85) assert ((85**4) * c1) + ((85**3) * c2) + ((85**2) * c3) + (85*c4) + c5 == num, 'dodgy code!' out(chr(c1+33)) out(chr(c2+33)) out(chr(c3+33)) out(chr(c4+33)) out(chr(c5+33)) # now we do the final bit at the end. I repeated this separately as # the loop above is the time-critical part of a script, whereas this # happens only once at the end. #encode however many bytes we have as usual if remainder_size > 0: while len(lastbit) < 4: lastbit = lastbit + '\000' b1 = ord(lastbit[0]) b2 = ord(lastbit[1]) b3 = ord(lastbit[2]) b4 = ord(lastbit[3]) num = 16777216L * b1 + 65536 * b2 + 256 * b3 + b4 #solve for c1..c5 temp, c5 = divmod(num, 85) temp, c4 = divmod(temp, 85) temp, c3 = divmod(temp, 85) c1, c2 = divmod(temp, 85) #print 'encoding: %d %d %d %d -> %d -> %d %d %d %d %d' % ( # b1,b2,b3,b4,num,c1,c2,c3,c4,c5) lastword = chr(c1+33) + chr(c2+33) + chr(c3+33) + chr(c4+33) + chr(c5+33) #write out most of the bytes. out(lastword[0:remainder_size + 1]) #terminator code for ascii 85 out('~>') return ''.join(out.__self__) def _chunker(src,dst=[],chunkSize=60): for i in xrange(0,len(src),chunkSize): dst.append(src[i:i+chunkSize]) return dst data=open(fichier,"rb").read() imagedata = ["q %s 0 0 %s " % (ll,hh) +xx+" "+yy+" cm"] imagedata.append('BI /W %d /H %d /BPC 8 /CS /%s /F [%s/DCT] ID' % (isize[0], isize[1],'DeviceRGB','/A85 ')) #data = fp.read() data = _AsciiBase85Encode(data) _chunker(data,imagedata) imagedata.append('EI\r\nQ\r\n') self.buffer += '\n'.join(imagedata) def mem_genere(self, fichier=os.getcwd()+"\\exemple1.pdf", voir=False): self.numobj+=1 sfin=ur""" % 'R"""+str(self.numobj)+ur"""': class PDFOutlines """+str(self.numobj)+ur""" 0 obj << /Count 0 /Type /Outlines >> endobj xref 0 """+str(self.parent+self.nbpages+2)+ur""" 0000000000 65535 f 0000000113 00000 n 0000000376 00000 n 0000000541 00000 n 0000000699 00000 n 0000000875 00000 n 0000001036 00000 n 0000001207 00000 n 0000001392 00000 n 0000001569 00000 n 0000001744 00000 n 0000001935 00000 n 0000002119 00000 n 0000002289 00000 n 0000002471 00000 n 0000002645 00000 n 0000002814 00000 n 0000003095 00000 n 0000003233 00000 n 0000003517 00000 n 0000003625 00000 n 0000016588 00000 n trailer << /ID % Ponx [(\3724,\347\311\3418\012\(;\330\027l3\030\376) (\3724,\347\311\3418\012\(;\330\027l3\030\376)] /Info """+str(self.parent-1)+ur""" 0 R /Root """+str(self.parent-2)+ur""" 0 R /Size """+str(self.parent+self.nbpages+2)+ur""" >> startxref 16640 %%EOF """ pdf=self.fond pdf=pdf.replace("...BUFFERPAGES...",self.bufferpages) pdf=pdf.replace("...TEXTE...",self.buffer) pdf=pdf.replace("...DATETIME...",time.strftime("%Y%m%d%H%M%S", time.localtime())) pdf += sfin open(fichier,"w").write(pdf.encode('cp1252','ignore')) self.fichier=fichier if voir: self.show() def show(self): # affiche le fichier .pdf avec le lecteure PDF par défaut. time.sleep(0.0250) if sys.platform.upper().startswith("WIN"): if self.fichier[1]==':': os.startfile(self.fichier) else: os.startfile(os.getcwd()+'\\'+self.fichier) else: if self.fichier[1]==':': os.system('xdg-open ' + self.fichier) else: os.system('xdg-open ' + os.getcwd()+'/'+self.fichier) def texte(self, *lpar, **dpar): if self.pagecourante==0: self.pagecourante=1 if "page" in dpar: page=dpar["page"] else: page=self.pagecourante if self.pagecourante != page: self.pagecourante = page if self.nbpages