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