spotcolor.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. // Adapted from http://www.fpdf.org/en/script/script89.php by Olivier PLATHEY
  15. package gofpdf
  16. import (
  17. "fmt"
  18. "strings"
  19. )
  20. func byteBound(v byte) byte {
  21. if v > 100 {
  22. return 100
  23. }
  24. return v
  25. }
  26. // AddSpotColor adds an ink-based CMYK color to the gofpdf instance and
  27. // associates it with the specified name. The individual components specify
  28. // percentages ranging from 0 to 100. Values above this are quietly capped to
  29. // 100. An error occurs if the specified name is already associated with a
  30. // color.
  31. func (f *Fpdf) AddSpotColor(nameStr string, c, m, y, k byte) {
  32. if f.err == nil {
  33. _, ok := f.spotColorMap[nameStr]
  34. if !ok {
  35. id := len(f.spotColorMap) + 1
  36. f.spotColorMap[nameStr] = spotColorType{
  37. id: id,
  38. val: cmykColorType{
  39. c: byteBound(c),
  40. m: byteBound(m),
  41. y: byteBound(y),
  42. k: byteBound(k),
  43. },
  44. }
  45. } else {
  46. f.err = fmt.Errorf("name \"%s\" is already associated with a spot color", nameStr)
  47. }
  48. }
  49. }
  50. func (f *Fpdf) getSpotColor(nameStr string) (clr spotColorType, ok bool) {
  51. if f.err == nil {
  52. clr, ok = f.spotColorMap[nameStr]
  53. if !ok {
  54. f.err = fmt.Errorf("spot color name \"%s\" is not registered", nameStr)
  55. }
  56. }
  57. return
  58. }
  59. // SetDrawSpotColor sets the current draw color to the spot color associated
  60. // with nameStr. An error occurs if the name is not associated with a color.
  61. // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
  62. // is quietly bounded to this range.
  63. func (f *Fpdf) SetDrawSpotColor(nameStr string, tint byte) {
  64. var clr spotColorType
  65. var ok bool
  66. clr, ok = f.getSpotColor(nameStr)
  67. if ok {
  68. f.color.draw.mode = colorModeSpot
  69. f.color.draw.spotStr = nameStr
  70. f.color.draw.str = sprintf("/CS%d CS %.3f SCN", clr.id, float64(byteBound(tint))/100)
  71. if f.page > 0 {
  72. f.out(f.color.draw.str)
  73. }
  74. }
  75. }
  76. // SetFillSpotColor sets the current fill color to the spot color associated
  77. // with nameStr. An error occurs if the name is not associated with a color.
  78. // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
  79. // is quietly bounded to this range.
  80. func (f *Fpdf) SetFillSpotColor(nameStr string, tint byte) {
  81. var clr spotColorType
  82. var ok bool
  83. clr, ok = f.getSpotColor(nameStr)
  84. if ok {
  85. f.color.fill.mode = colorModeSpot
  86. f.color.fill.spotStr = nameStr
  87. f.color.fill.str = sprintf("/CS%d cs %.3f scn", clr.id, float64(byteBound(tint))/100)
  88. f.colorFlag = f.color.fill.str != f.color.text.str
  89. if f.page > 0 {
  90. f.out(f.color.fill.str)
  91. }
  92. }
  93. }
  94. // SetTextSpotColor sets the current text color to the spot color associated
  95. // with nameStr. An error occurs if the name is not associated with a color.
  96. // The value for tint ranges from 0 (no intensity) to 100 (full intensity). It
  97. // is quietly bounded to this range.
  98. func (f *Fpdf) SetTextSpotColor(nameStr string, tint byte) {
  99. var clr spotColorType
  100. var ok bool
  101. clr, ok = f.getSpotColor(nameStr)
  102. if ok {
  103. f.color.text.mode = colorModeSpot
  104. f.color.text.spotStr = nameStr
  105. f.color.text.str = sprintf("/CS%d cs %.3f scn", clr.id, float64(byteBound(tint))/100)
  106. f.colorFlag = f.color.text.str != f.color.text.str
  107. }
  108. }
  109. func (f *Fpdf) returnSpotColor(clr colorType) (name string, c, m, y, k byte) {
  110. var spotClr spotColorType
  111. var ok bool
  112. name = clr.spotStr
  113. if name != "" {
  114. spotClr, ok = f.getSpotColor(name)
  115. if ok {
  116. c = spotClr.val.c
  117. m = spotClr.val.m
  118. y = spotClr.val.y
  119. k = spotClr.val.k
  120. }
  121. }
  122. return
  123. }
  124. // GetDrawSpotColor returns the most recently used spot color information for
  125. // drawing. This will not be the current drawing color if some other color type
  126. // such as RGB is active. If no spot color has been set for drawing, zero
  127. // values are returned.
  128. func (f *Fpdf) GetDrawSpotColor() (name string, c, m, y, k byte) {
  129. return f.returnSpotColor(f.color.draw)
  130. }
  131. // GetTextSpotColor returns the most recently used spot color information for
  132. // text output. This will not be the current text color if some other color
  133. // type such as RGB is active. If no spot color has been set for text, zero
  134. // values are returned.
  135. func (f *Fpdf) GetTextSpotColor() (name string, c, m, y, k byte) {
  136. return f.returnSpotColor(f.color.text)
  137. }
  138. // GetFillSpotColor returns the most recently used spot color information for
  139. // fill output. This will not be the current fill color if some other color
  140. // type such as RGB is active. If no fill spot color has been set, zero values
  141. // are returned.
  142. func (f *Fpdf) GetFillSpotColor() (name string, c, m, y, k byte) {
  143. return f.returnSpotColor(f.color.fill)
  144. }
  145. func (f *Fpdf) putSpotColors() {
  146. for k, v := range f.spotColorMap {
  147. f.newobj()
  148. f.outf("[/Separation /%s", strings.Replace(k, " ", "#20", -1))
  149. f.out("/DeviceCMYK <<")
  150. f.out("/Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0] ")
  151. f.outf("/C1 [%.3f %.3f %.3f %.3f] ", float64(v.val.c)/100, float64(v.val.m)/100,
  152. float64(v.val.y)/100, float64(v.val.k)/100)
  153. f.out("/FunctionType 2 /Domain [0 1] /N 1>>]")
  154. f.out("endobj")
  155. v.objID = f.n
  156. f.spotColorMap[k] = v
  157. }
  158. }
  159. func (f *Fpdf) spotColorPutResourceDict() {
  160. f.out("/ColorSpace <<")
  161. for _, clr := range f.spotColorMap {
  162. f.outf("/CS%d %d 0 R", clr.id, clr.objID)
  163. }
  164. f.out(">>")
  165. }