github.com/phpdave11/gofpdf@v1.4.2/spotcolor.go (about)

     1  // Copyright (c) Kurt Jung (Gmail: kurt.w.jung)
     2  //
     3  // Permission to use, copy, modify, and distribute this software for any
     4  // purpose with or without fee is hereby granted, provided that the above
     5  // copyright notice and this permission notice appear in all copies.
     6  //
     7  // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     8  // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     9  // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
    10  // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    11  // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
    12  // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
    13  // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    14  
    15  // Adapted from http://www.fpdf.org/en/script/script89.php by Olivier PLATHEY
    16  
    17  package gofpdf
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  )
    23  
    24  func byteBound(v byte) byte {
    25  	if v > 100 {
    26  		return 100
    27  	}
    28  	return v
    29  }
    30  
    31  // AddSpotColor adds an ink-based CMYK color to the gofpdf instance and
    32  // associates it with the specified name. The individual components specify
    33  // percentages ranging from 0 to 100. Values above this are quietly capped to
    34  // 100. An error occurs if the specified name is already associated with a
    35  // color.
    36  func (f *Fpdf) AddSpotColor(nameStr string, c, m, y, k byte) {
    37  	if f.err == nil {
    38  		_, ok := f.spotColorMap[nameStr]
    39  		if !ok {
    40  			id := len(f.spotColorMap) + 1
    41  			f.spotColorMap[nameStr] = spotColorType{
    42  				id: id,
    43  				val: cmykColorType{
    44  					c: byteBound(c),
    45  					m: byteBound(m),
    46  					y: byteBound(y),
    47  					k: byteBound(k),
    48  				},
    49  			}
    50  		} else {
    51  			f.err = fmt.Errorf("name \"%s\" is already associated with a spot color", nameStr)
    52  		}
    53  	}
    54  }
    55  
    56  func (f *Fpdf) getSpotColor(nameStr string) (clr spotColorType, ok bool) {
    57  	if f.err == nil {
    58  		clr, ok = f.spotColorMap[nameStr]
    59  		if !ok {
    60  			f.err = fmt.Errorf("spot color name \"%s\" is not registered", nameStr)
    61  		}
    62  	}
    63  	return
    64  }
    65  
    66  // SetDrawSpotColor sets the current draw color to the spot color associated
    67  // with nameStr. An error occurs if the name is not associated with a color.
    68  // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
    69  // is quietly bounded to this range.
    70  func (f *Fpdf) SetDrawSpotColor(nameStr string, tint byte) {
    71  	var clr spotColorType
    72  	var ok bool
    73  
    74  	clr, ok = f.getSpotColor(nameStr)
    75  	if ok {
    76  		f.color.draw.mode = colorModeSpot
    77  		f.color.draw.spotStr = nameStr
    78  		f.color.draw.str = sprintf("/CS%d CS %.3f SCN", clr.id, float64(byteBound(tint))/100)
    79  		if f.page > 0 {
    80  			f.out(f.color.draw.str)
    81  		}
    82  	}
    83  }
    84  
    85  // SetFillSpotColor sets the current fill color to the spot color associated
    86  // with nameStr. An error occurs if the name is not associated with a color.
    87  // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
    88  // is quietly bounded to this range.
    89  func (f *Fpdf) SetFillSpotColor(nameStr string, tint byte) {
    90  	var clr spotColorType
    91  	var ok bool
    92  
    93  	clr, ok = f.getSpotColor(nameStr)
    94  	if ok {
    95  		f.color.fill.mode = colorModeSpot
    96  		f.color.fill.spotStr = nameStr
    97  		f.color.fill.str = sprintf("/CS%d cs %.3f scn", clr.id, float64(byteBound(tint))/100)
    98  		f.colorFlag = f.color.fill.str != f.color.text.str
    99  		if f.page > 0 {
   100  			f.out(f.color.fill.str)
   101  		}
   102  	}
   103  }
   104  
   105  // SetTextSpotColor sets the current text color to the spot color associated
   106  // with nameStr. An error occurs if the name is not associated with a color.
   107  // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
   108  // is quietly bounded to this range.
   109  func (f *Fpdf) SetTextSpotColor(nameStr string, tint byte) {
   110  	var clr spotColorType
   111  	var ok bool
   112  
   113  	clr, ok = f.getSpotColor(nameStr)
   114  	if ok {
   115  		f.color.text.mode = colorModeSpot
   116  		f.color.text.spotStr = nameStr
   117  		f.color.text.str = sprintf("/CS%d cs %.3f scn", clr.id, float64(byteBound(tint))/100)
   118  		f.colorFlag = f.color.text.str != f.color.text.str
   119  	}
   120  }
   121  
   122  func (f *Fpdf) returnSpotColor(clr colorType) (name string, c, m, y, k byte) {
   123  	var spotClr spotColorType
   124  	var ok bool
   125  
   126  	name = clr.spotStr
   127  	if name != "" {
   128  		spotClr, ok = f.getSpotColor(name)
   129  		if ok {
   130  			c = spotClr.val.c
   131  			m = spotClr.val.m
   132  			y = spotClr.val.y
   133  			k = spotClr.val.k
   134  		}
   135  	}
   136  	return
   137  }
   138  
   139  // GetDrawSpotColor returns the most recently used spot color information for
   140  // drawing. This will not be the current drawing color if some other color type
   141  // such as RGB is active. If no spot color has been set for drawing, zero
   142  // values are returned.
   143  func (f *Fpdf) GetDrawSpotColor() (name string, c, m, y, k byte) {
   144  	return f.returnSpotColor(f.color.draw)
   145  }
   146  
   147  // GetTextSpotColor returns the most recently used spot color information for
   148  // text output. This will not be the current text color if some other color
   149  // type such as RGB is active. If no spot color has been set for text, zero
   150  // values are returned.
   151  func (f *Fpdf) GetTextSpotColor() (name string, c, m, y, k byte) {
   152  	return f.returnSpotColor(f.color.text)
   153  }
   154  
   155  // GetFillSpotColor returns the most recently used spot color information for
   156  // fill output. This will not be the current fill color if some other color
   157  // type such as RGB is active. If no fill spot color has been set, zero values
   158  // are returned.
   159  func (f *Fpdf) GetFillSpotColor() (name string, c, m, y, k byte) {
   160  	return f.returnSpotColor(f.color.fill)
   161  }
   162  
   163  func (f *Fpdf) putSpotColors() {
   164  	for k, v := range f.spotColorMap {
   165  		f.newobj()
   166  		f.outf("[/Separation /%s", strings.Replace(k, " ", "#20", -1))
   167  		f.out("/DeviceCMYK <<")
   168  		f.out("/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ")
   169  		f.outf("/C1 [%.3f %.3f %.3f %.3f] ", float64(v.val.c)/100, float64(v.val.m)/100,
   170  			float64(v.val.y)/100, float64(v.val.k)/100)
   171  		f.out("/FunctionType 2 /Domain [0 1] /N 1>>]")
   172  		f.out("endobj")
   173  		v.objID = f.n
   174  		f.spotColorMap[k] = v
   175  	}
   176  }
   177  
   178  func (f *Fpdf) spotColorPutResourceDict() {
   179  	f.out("/ColorSpace <<")
   180  	for _, clr := range f.spotColorMap {
   181  		f.outf("/CS%d %d 0 R", clr.id, clr.objID)
   182  	}
   183  	f.out(">>")
   184  }