badgemaker.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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 - badge.font_size),
  82. "height": $badge.height, "rx": radius, "ry": radius,
  83. "style": "fill:" & badge.label_color
  84. }.toXMLAttributes)
  85. main.add newXMLTree(
  86. "rect", [], {
  87. "x": $dif, "y": "0",
  88. "width": $((badge.width - (badge.font_size/2).int) - (dif)),
  89. "height": $badge.height,
  90. "rx": "0", "ry": "0", "style": "fill:" & badge.value_color
  91. }.toXMLAttributes)
  92. main.add newXMLTree(
  93. "rect", [], {
  94. "x": $(badge.width - badge.font_size), "y": "0",
  95. "width": $badge.font_size, "height": $badge.height,
  96. "rx": radius, "ry": radius,
  97. "style": "fill:" & badge.value_color
  98. }.toXMLAttributes)
  99. main.add newXMLTree(
  100. "path", [], {
  101. "fill": "url(#gradient)",
  102. "d": "M0 0h" & $badge.width & "v" & $badge.height & "H0z"
  103. }.toXMLAttributes)
  104. text.add newXMLTree(
  105. "text", [], {
  106. "x": $(image_width + 2 + parseInt(radius)),
  107. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.label_text_color
  108. }.toXMLAttributes)
  109. text.add newXMLTree(
  110. "text", [], {
  111. "x": $(dif + 2),
  112. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.value_text_color
  113. }.toXMLAttributes)
  114. text[0].add newText badge.label
  115. text[1].add newText badge.value
  116. tree.add gradient
  117. tree.add main
  118. tree.add text
  119. if badge.image_path != "":
  120. var
  121. img = newFileStream(badge.image_path, fmRead)
  122. image = img.readAll
  123. img.close
  124. tree.add newXMLTree(
  125. "image", [], {
  126. "xlink:href": "data:image/png;base64," & encode image,
  127. "width": $badge.height, "height": $badge.height,
  128. "x": radius, "y": "0", "fill": badge.image_color
  129. }.toXMLAttributes)
  130. return $tree
  131. proc write*(badge: BadgeRef, filename: string) =
  132. ## Writes SVG image in file.
  133. var strm = newFileStream(filename, fmWrite)
  134. strm.write $badge
  135. strm.close