badgemaker.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. # author: Ethosa
  2. import streams
  3. import xmltree
  4. import strutils
  5. from base64 import encode
  6. type
  7. BadgeRef* = ref object
  8. style: string ## egg "flat", "square", "plastic" etc.
  9. label: string ## left text.
  10. value: string ## right text.
  11. label_text_color: string ## left text color
  12. value_text_color: string ## right text color
  13. label_color: string ## left color.
  14. value_color: string ## right color.
  15. font: string
  16. font_size: int
  17. width, height: int
  18. image_path: string
  19. image_color: string
  20. proc newBadge*(label="", value="", style="flat", label_color="#212121",
  21. value_color="#e0e0e0", label_text_color="white",
  22. value_text_color="black", width=120, height=20): BadgeRef =
  23. ## Creates a new Badge object.
  24. BadgeRef(label: label, value: value, style: style,
  25. label_text_color: label_text_color, value_text_color: value_text_color,
  26. label_color: label_color, value_color: value_color,
  27. font: "DejaVu Sans,Verdana,Geneva,sans-serif",
  28. width: width, height: height, image_path: "", image_color: "",
  29. font_size: 12)
  30. proc setFont*(badge: BadgeRef, font: string) =
  31. ## Sets badge font.
  32. badge.font = font
  33. proc setFontSize*(badge: BadgeRef, size: int) =
  34. ## Sets badge font size.
  35. badge.font_size = size
  36. proc setIcon*(badge: BadgeRef, image_path: string) =
  37. ## Sets icon for badge.
  38. badge.image_path = image_path
  39. proc setIcon*(badge: BadgeRef, image_path, color: string) =
  40. ## Sets icon with fill color.
  41. badge.image_path = image_path
  42. badge.image_color = color
  43. proc `$`*(badge: BadgeRef): string =
  44. let
  45. # start variables
  46. image_width = if badge.image_path != "": badge.height else: 0
  47. labell = len(badge.label)
  48. valuel = len(badge.value)
  49. labelw = labell*(badge.font_size - 3).int + labell + image_width
  50. valuew = valuel*(badge.font_size - 3).int + valuel + image_width
  51. radius = if "square" in badge.style: "0" else: "4"
  52. dif =
  53. if labelw > valuew:
  54. labelw - valuew + radius.parseInt
  55. else:
  56. labelw - badge.font_size + radius.parseInt
  57. stop_opacity = if "plastic" notin badge.style: "0" else: ".1"
  58. var
  59. # trees
  60. tree = newXMLTree(
  61. "svg", [], {
  62. "xmlns": "http://www.w3.org/2000/svg",
  63. "xmlns:xlink": "http://www.w3.org/1999/xlink",
  64. "width": $badge.width, "height": $badge.height
  65. }.toXMLAttributes)
  66. main = newXMLTree("g", [], {"mask": "url(#gradient)"}.toXMLAttributes)
  67. text = newXMLTree("g", [], {
  68. "font-family": badge.font, "font-size": $badge.font_size, "fill": badge.label_color
  69. }.toXMLAttributes)
  70. gradient = newXMLTree(
  71. "linearGradient", [],
  72. {"id": "gradient", "x2": "0", "y2": "100%"}.toXMLAttributes)
  73. gradient.add newXMLTree("stop", [], {
  74. "offset": "0", "stop-color": "#bbb", "stop-opacity": stop_opacity
  75. }.toXMLAttributes)
  76. gradient.add newXMLTree("stop", [], {
  77. "offset": "1", "stop-opacity": stop_opacity
  78. }.toXMLAttributes)
  79. main.add newXMLTree(
  80. "rect", [], {
  81. "x": "0", "y": "0", "width": $labelw, "height": $badge.height,
  82. "rx": radius,
  83. "ry": radius,
  84. "style": "fill:" & badge.label_color
  85. }.toXMLAttributes)
  86. main.add newXMLTree(
  87. "rect", [], {
  88. "x": $dif, "y": "0",
  89. "width": $((badge.width - (badge.font_size/2).int) - (dif)),
  90. "height": $badge.height,
  91. "rx": "0", "ry": "0", "style": "fill:" & badge.value_color
  92. }.toXMLAttributes)
  93. main.add newXMLTree(
  94. "rect", [], {
  95. "x": $(badge.width - badge.font_size), "y": "0",
  96. "width": $badge.font_size, "height": $badge.height,
  97. "rx": radius, "ry": radius,
  98. "style": "fill:" & badge.value_color
  99. }.toXMLAttributes)
  100. main.add newXMLTree(
  101. "path", [], {
  102. "fill": "url(#gradient)",
  103. "d": "M0 0h" & $badge.width & "v" & $badge.height & "H0z"
  104. }.toXMLAttributes)
  105. text.add newXMLTree(
  106. "text", [], {
  107. "x": $(image_width + 2 + parseInt(radius)),
  108. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.label_text_color
  109. }.toXMLAttributes)
  110. text.add newXMLTree(
  111. "text", [], {
  112. "x": $(dif + 2),
  113. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.value_text_color
  114. }.toXMLAttributes)
  115. text[0].add newText badge.label
  116. text[1].add newText badge.value
  117. tree.add gradient
  118. tree.add main
  119. tree.add text
  120. if badge.image_path != "":
  121. var
  122. img = newFileStream(badge.image_path, fmRead)
  123. image = img.readAll
  124. img.close
  125. tree.add newXMLTree(
  126. "image", [], {
  127. "xlink:href": "data:image/png;base64," & encode image,
  128. "width": $badge.height, "height": $badge.height,
  129. "x": radius, "y": "0", "fill": badge.image_color
  130. }.toXMLAttributes)
  131. return $tree
  132. proc write*(badge: BadgeRef, filename: string) =
  133. ## Writes SVG image in file.
  134. var strm = newFileStream(filename, fmWrite)
  135. strm.write $badge
  136. strm.close