from FPDF import * class Gradients(FPDF): def __init__(this,orientation='P',unit='mm',format='A4'): FPDF.__init__(this,orientation,unit,format) this.gradients={} def LinearGradient(this,x, y, w, h, col1=[], col2=[], coords=[0.0,0.0,1.0,0.0]): this.Clip(x,y,w,h) this.Gradient(2,col1,col2,coords) def RadialGradient(this,x, y, w, h, col1=[], col2=[], coords=[0.5,0.5,0.5,0.5,1.0]): this.Clip(x,y,w,h) this.Gradient(3,col1,col2,coords) def CoonsPatchMesh(this,x, y, w, h, col1=[], col2=[], col3=[], col4=[], coords=[0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33], coords_min=0.0, coords_max=1.0): this.Clip(x,y,w,h) n = count(this.gradients)+1 this.gradients[n]={} this.gradients[n]['type']=6 #coons patch mesh #check the coords array if it is the simple array or the multi patch array if type(coords[0]) != type({}): #simple array -> convert to multi patch array for L in (col1,col2,col3,col4): if len(L)==1: L+=[L[0],L[0]] patch_array=[{}] patch_array[0]['f']=0 patch_array[0]['points']=coords patch_array[0]['colors']=[{},{},{},{}] patch_array[0]['colors'][0]['r']=col1[0] patch_array[0]['colors'][0]['g']=col1[1] patch_array[0]['colors'][0]['b']=col1[2] patch_array[0]['colors'][1]['r']=col2[0] patch_array[0]['colors'][1]['g']=col2[1] patch_array[0]['colors'][1]['b']=col2[2] patch_array[0]['colors'][2]['r']=col3[0] patch_array[0]['colors'][2]['g']=col3[1] patch_array[0]['colors'][2]['b']=col3[2] patch_array[0]['colors'][3]['r']=col4[0] patch_array[0]['colors'][3]['g']=col4[1] patch_array[0]['colors'][3]['b']=col4[2] else: #multi patch array patch_array=coords bpcd=65535 #16 BitsPerCoordinate #build the data stream this.gradients[n]['stream']='' for i in xrange(0,count(patch_array)): this.gradients[n]['stream']+=chr(patch_array[i]['f']) #start with the edge flag as 8 bit for j in xrange(0,count(patch_array[i]['points'])): #each point as 16 bit patch_array[i]['points'][j]=((patch_array[i]['points'][j]-coords_min)/(coords_max-coords_min))*bpcd if(patch_array[i]['points'][j]<0): patch_array[i]['points'][j]=0 if(patch_array[i]['points'][j]>bpcd): patch_array[i]['points'][j]=bpcd this.gradients[n]['stream']+=chr(floor(patch_array[i]['points'][j]/256.0)) this.gradients[n]['stream']+=chr(floor(patch_array[i]['points'][j]%256.0)) for j in xrange(0,count(patch_array[i]['colors'])): #each color component as 8 bit this.gradients[n]['stream']+=chr(patch_array[i]['colors'][j]['r']) this.gradients[n]['stream']+=chr(patch_array[i]['colors'][j]['g']) this.gradients[n]['stream']+=chr(patch_array[i]['colors'][j]['b']) #paint the gradient this._out('/Sh'+str(n)+' sh') #restore previous Graphic State this._out('Q') def Clip(this,x,y,w,h): #save current Graphic State s='q' #set clipping area s+=sprintf(' %.2f %.2f %.2f %.2f re W n', x*this.k, (this.h-y)*this.k, w*this.k, -h*this.k) #set up transformation matrix for gradient s+=sprintf(' %.3f 0 0 %.3f %.3f %.3f cm', w*this.k, h*this.k, x*this.k, (this.h-(y+h))*this.k) this._out(s) def Gradient(this, type, col1, col2, coords): n = count(this.gradients)+1 this.gradients[n]={} this.gradients[n]['type']=type if len(col1)==1: col1+=[col1[0],col1[0]] this.gradients[n]['col1']=sprintf('%.3f %.3f %.3f',(col1[0]/255.0),(col1[1]/255.0),(col1[2]/255.0)) if len(col2)==1: col2+=[col2[0],col2[0]] this.gradients[n]['col2']=sprintf('%.3f %.3f %.3f',(col2[0]/255.0),(col2[1]/255.0),(col2[2]/255.0)) this.gradients[n]['coords']=coords #paint the gradient this._out('/Sh'+str(n)+' sh') #restore previous Graphic State this._out('Q') def _putshaders(this): for id,grad in this.gradients.iteritems(): if(grad['type']==2 or grad['type']==3): this._newobj() this._out('<<') this._out('/FunctionType 2') this._out('/Domain [0.0 1.0]') this._out('/C0 ['+grad['col1']+']') this._out('/C1 ['+grad['col2']+']') this._out('/N 1') this._out('>>') this._out('endobj') f1=this.n this._newobj() this._out('<<') this._out('/ShadingType '+str(grad['type'])) this._out('/ColorSpace /DeviceRGB') if(grad['type']==2): this._out(sprintf('/Coords [%.3f %.3f %.3f %.3f]',grad['coords'][0],grad['coords'][1],grad['coords'][2],grad['coords'][3])) this._out('/Function '+str(f1)+' 0 R') this._out('/Extend [true true] ') this._out('>>') elif(grad['type']==3): #x0, y0, r0, x1, y1, r1 #at this this time radius of inner circle is 0 this._out(sprintf('/Coords [%.3f %.3f 0 %.3f %.3f %.3f]',grad['coords'][0],grad['coords'][1],grad['coords'][2],grad['coords'][3],grad['coords'][4])) this._out('/Function '+str(f1)+' 0 R') this._out('/Extend [true true] ') this._out('>>') elif(grad['type']==6): this._out('/BitsPerCoordinate 16') this._out('/BitsPerComponent 8') this._out('/Decode[0 1 0 1 0 1 0 1 0 1]') this._out('/BitsPerFlag 8') this._out('/Length '+str(strlen(grad['stream']))) this._out('>>') this._putstream(grad['stream']) this._out('endobj') this.gradients[id]['id']=this.n def _putresourcedict(this): FPDF._putresourcedict(this) this._out('/Shading <<') for id,grad in this.gradients.iteritems(): this._out('/Sh'+str(id)+' '+str(grad['id'])+' 0 R') this._out('>>') def _putresources(this): this._putshaders() FPDF._putresources(this)