FattView/fpdf/attic/Gradients.py


Home Back

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)

Powered by Code, a simple repository browser by Fabio Di Matteo