Index: /pykota/trunk/conf/pykota.conf.sample
===================================================================
--- /pykota/trunk/conf/pykota.conf.sample (revision 3025)
+++ /pykota/trunk/conf/pykota.conf.sample (revision 3036)
@@ -597,4 +597,21 @@
 # Software accounting unfortunately may overcharge users in case of paper
 # jams.
+#
+# Ink computes the price of a print job by parsing the job's datas
+# through pkpgcounter, and using the percents of ink coverage returned
+# for each color in the specified colorspace.
+
+# Supported colorspaces for ink accounting currently are :
+#
+#       bw      ===> Black & White
+#       cmyk    ===> Cyan, Magenta, Yellow, Black
+#       cmy     ===> Cyan, Magenta, Yellow
+#       rgb     ===> Red, Green, Blue
+#
+# Supported resolutions for ink accounting are any number of dots
+# per inch comprised between 72 and 1200. 
+# IMPORTANT : increasing the resolution increases precision, but
+# increase CPU load a lot at the same time. The default resolution
+# if unset is 72, for 72 dpi.
 # 
 # You can get hints on which configuration is best for your printers by
@@ -619,4 +636,8 @@
 # accounter : software(/usr/bin/pkpgcounter) 
 # accounter : software()
+# accounter : ink(cmyk, 150)
+# accounter : ink(bw, 300)
+# accounter : ink(bw)
+# accounter : ink(cmy, 72)
 #         
 # This directive can be set either globally or per printer or both.
@@ -648,4 +669,5 @@
 #  preaccounter: software()       
 #  preaccounter: software(/path/to/your/script)
+#  preaccounter: ink(colorspace, resolution)
 #
 # NB : the preaccounter directive doesn't support hardware() for obvious 
@@ -657,4 +679,17 @@
 # in the case your printer supports an hardware accounter but pkpgcounter
 # can't parse your printer driver's datas.
+#
+# Supported colorspaces for ink accounting currently are :
+#
+#       bw      ===> Black & White
+#       cmyk    ===> Cyan, Magenta, Yellow, Black
+#       cmy     ===> Cyan, Magenta, Yellow
+#       rgb     ===> Red, Green, Blue
+#
+# Supported resolutions for ink accounting are any number of dots
+# per inch comprised between 72 and 1200. 
+# IMPORTANT : increasing the resolution increases precision, but
+# increase CPU load a lot at the same time. The default resolution
+# if unset is 72, for 72 dpi.
 #
 # This value can be set either globally or on a per printer basis
Index: /pykota/trunk/README
===================================================================
--- /pykota/trunk/README (revision 3015)
+++ /pykota/trunk/README (revision 3036)
@@ -119,4 +119,7 @@
         - Price per page and per job can be set differently  
           on any printer.
+        
+        - Price depending on ink/toner usage is supported
+          with many printer drivers.
         
         - Low level of page quota or account balance are
Index: /pykota/trunk/TODO
===================================================================
--- /pykota/trunk/TODO (revision 3033)
+++ /pykota/trunk/TODO (revision 3036)
@@ -59,6 +59,4 @@
           files at run time.
         
-        - Ink accounting ala PrintBill.
-        
         - Price and statistics per page format.
         
Index: /pykota/trunk/pykota/accounters/ink.py
===================================================================
--- /pykota/trunk/pykota/accounters/ink.py (revision 3034)
+++ /pykota/trunk/pykota/accounters/ink.py (revision 3036)
@@ -42,7 +42,11 @@
             # know the result.
             self.filter.logdebug("Precomputing pass told us that job is %s pages long." % self.filter.softwareJobSize)
-            return self.filter.softwareJobSize   # Optimize : already computed !
+            self.inkUsage = self.filter.preaccounter.inkUsage   # Optimize : already computed !
+            return self.filter.softwareJobSize                  # Optimize : already computed !
             
-        (colorspace, resolution) = [p.strip() for p in self.arguments.split(',')]
+        parameters = [p.strip() for p in self.arguments.split(',')]
+        if len(parameters) == 1 :
+            parameters.append("72")
+        (colorspace, resolution) = parameters
         colorspace = colorspace.lower()
         if colorspace not in ("cmyk", "bw", "cmy", "rgb") :
@@ -57,5 +61,4 @@
         
         jobsize = 0
-        self.inkUsage = []
         if self.filter.JobSizeBytes :
             try :
Index: /pykota/trunk/pykota/accounter.py
===================================================================
--- /pykota/trunk/pykota/accounter.py (revision 3000)
+++ /pykota/trunk/pykota/accounter.py (revision 3036)
@@ -45,4 +45,5 @@
         self.isSoftware = 1 # by default software accounting
         self.isPreAccounter = ispreaccounter 
+        self.inkUsage = []
         
     def getLastPageCounter(self) :    
Index: /pykota/trunk/pykota/storage.py
===================================================================
--- /pykota/trunk/pykota/storage.py (revision 3033)
+++ /pykota/trunk/pykota/storage.py (revision 3036)
@@ -308,5 +308,5 @@
         self.isDirty = True
         
-    def computeJobPrice(self, jobsize) :    
+    def computeJobPrice(self, jobsize, inkusage=[]) :    
         """Computes the job price as the sum of all parent printers' prices + current printer's ones."""
         totalprice = 0.0    
@@ -314,16 +314,33 @@
             if self.User.OverCharge != 0.0 :    # optimization, but TODO : beware of rounding errors
                 for upq in [ self ] + self.ParentPrintersUserPQuota :
-                    price = (float(upq.Printer.PricePerPage or 0.0) * jobsize) + float(upq.Printer.PricePerJob or 0.0)
-                    totalprice += price
+                    totalprice += float(upq.Printer.PricePerJob or 0.0)
+                    pageprice = float(upq.Printer.PricePerPage or 0.0)
+                    if not inkusage :
+                        totalprice += (jobsize * pageprice)
+                    else :    
+                        for pageindex in range(jobsize) :
+                            try :
+                                usage = inkusage[pageindex]
+                            except IndexError :    
+                                self.parent.tool.logdebug("No ink usage information. Using base cost of %f credits for page %i." % (pageprice, pageindex+1))
+                                totalprice += pageprice
+                            else :    
+                                coefficients = self.Printer.Coefficients
+                                for (ink, value) in usage.items() :
+                                    coefvalue = coefficients.get(ink, 1.0)
+                                    coefprice = (coefvalue * pageprice) / 100.0
+                                    inkprice = coefprice * value
+                                    self.parent.tool.logdebug("Applying coefficient %f for color %s (used at %f%% on page %i) to base cost %f gives %f" % (coefvalue, ink, value, pageindex+1, pageprice, inkprice))
+                                    totalprice += coefprice
         if self.User.OverCharge != 1.0 : # TODO : beware of rounding errors
             overcharged = totalprice * self.User.OverCharge        
-            self.parent.tool.logdebug("Overcharging %s by a factor of %s ===> User %s will be charged for %s units." % (totalprice, self.User.OverCharge, self.User.Name, overcharged))
+            self.parent.tool.logdebug("Overcharging %s by a factor of %s ===> User %s will be charged for %s credits." % (totalprice, self.User.OverCharge, self.User.Name, overcharged))
             return overcharged
         else :    
             return totalprice
             
-    def increasePagesUsage(self, jobsize) :
+    def increasePagesUsage(self, jobsize, inkusage=[]) :
         """Increase the value of used pages and money."""
-        jobprice = self.computeJobPrice(jobsize)
+        jobprice = self.computeJobPrice(jobsize, inkusage)
         if jobsize :
             if jobprice :
Index: /pykota/trunk/pykota/version.py
===================================================================
--- /pykota/trunk/pykota/version.py (revision 3025)
+++ /pykota/trunk/pykota/version.py (revision 3036)
@@ -22,5 +22,5 @@
 #
 
-__version__ = "1.25alpha13_unofficial"
+__version__ = "1.25alpha14_unofficial"
 
 __doc__ = "PyKota : a complete Printing Quota Solution for CUPS."
Index: /pykota/trunk/bin/cupspykota
===================================================================
--- /pykota/trunk/bin/cupspykota (revision 3023)
+++ /pykota/trunk/bin/cupspykota (revision 3036)
@@ -574,5 +574,5 @@
         """Precomputes the job price with a software method."""
         self.logdebug("Precomputing job's price...")
-        self.softwareJobPrice = self.UserPQuota.computeJobPrice(self.softwareJobSize)
+        self.softwareJobPrice = self.UserPQuota.computeJobPrice(self.softwareJobSize, self.preaccounter.inkUsage)
         self.logdebug("Precomputed job's price is %.3f credits." \
                                    % self.softwareJobPrice)
@@ -1270,5 +1270,5 @@
                 # update the quota for the current user on this printer 
                 self.printInfo(_("Updating user %s's quota on printer %s") % (self.UserName, self.PrinterName))
-                self.JobPrice = self.UserPQuota.increasePagesUsage(self.JobSize)
+                self.JobPrice = self.UserPQuota.increasePagesUsage(self.JobSize, self.accounter.inkUsage)
             
             # adds the current job to history    
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 3032)
+++ /pykota/trunk/NEWS (revision 3036)
@@ -22,4 +22,11 @@
 PyKota NEWS :
        
+    - 1.25alpha14 (2006-10-13) :
+      
+        - First useable release with the computation of ink
+          usage, through the introduction of the 'ink(cspace, resolution)'
+          value for the 'preaccounter' and 'accounter' directives in
+          pykota.conf
+          
     - 1.25alpha13 (2006-10-04) :
      
