badgemaker.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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" or "plastic"
  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. var tree = newXMLTree(
  45. "svg", [], {
  46. "xmlns": "http://www.w3.org/2000/svg",
  47. "xmlns:xlink": "http://www.w3.org/1999/xlink",
  48. "width": $badge.width,
  49. "height": $badge.height
  50. }.toXMLAttributes)
  51. var gradient = newXMLTree(
  52. "linearGradient", [],
  53. {"id": "gradient",
  54. "x2": "0", "y2": "100%"
  55. }.toXMLAttributes)
  56. gradient.add newXMLTree("stop", [], {
  57. "offset": "0", "stop-color": "#bbb",
  58. "stop-opacity": if "plastic" notin badge.style:
  59. "0"
  60. else:
  61. ".1"
  62. }.toXMLAttributes)
  63. gradient.add newXMLTree("stop", [], {
  64. "offset": "1",
  65. "stop-opacity": if "plastic" notin badge.style:
  66. "0"
  67. else:
  68. ".1"
  69. }.toXMLAttributes)
  70. var
  71. main = newXMLTree("g", [], {"mask": "url(#gradient)"}.toXMLAttributes)
  72. image_width =
  73. if badge.image_path != "":
  74. badge.height
  75. else:
  76. 0
  77. labelw = len(badge.label)*(badge.font_size - 3).int + len(badge.label) + image_width
  78. valuew = len(badge.value)*(badge.font_size - 3).int + len(badge.value) + image_width
  79. dif =
  80. if labelw > valuew:
  81. labelw - valuew
  82. else:
  83. labelw - badge.font_size
  84. radius = if "square" in badge.style: "0" else: "4"
  85. dif += radius.parseInt
  86. main.add newXMLTree(
  87. "rect", [], {
  88. "x": "0", "y": "0", "width": $labelw, "height": $badge.height,
  89. "rx": radius,
  90. "ry": radius,
  91. "style": "fill:" & badge.label_color
  92. }.toXMLAttributes
  93. )
  94. main.add newXMLTree(
  95. "rect", [], {
  96. "x": $dif, "y": "0",
  97. "width": $((badge.width - (badge.font_size/2).int) - (dif)),
  98. "height": $badge.height,
  99. "rx": "0", "ry": "0", "style": "fill:" & badge.value_color
  100. }.toXMLAttributes
  101. )
  102. main.add newXMLTree(
  103. "rect", [], {
  104. "x": $(badge.width - badge.font_size), "y": "0",
  105. "width": $badge.font_size, "height": $badge.height,
  106. "rx": radius,
  107. "ry": radius,
  108. "style": "fill:" & badge.value_color
  109. }.toXMLAttributes
  110. )
  111. main.add newXMLTree(
  112. "path", [], {
  113. "fill": "url(#gradient)",
  114. "d": "M0 0h" & $badge.width & "v" & $badge.height & "H0z"
  115. }.toXMLAttributes
  116. )
  117. var text = newXMLTree("g", [], {
  118. "font-family": badge.font, "font-size": $badge.font_size, "fill": badge.label_color
  119. }.toXMLAttributes)
  120. text.add newXMLTree(
  121. "text", [], {
  122. "x": $(image_width + 2 + parseInt(radius)),
  123. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.label_text_color
  124. }.toXMLAttributes
  125. )
  126. text[0].add newText badge.label
  127. text.add newXMLTree(
  128. "text", [], {
  129. "x": $(dif + 2),
  130. "y": $(badge.height/2 + (badge.font_size/2) - 1.0), "fill": badge.value_text_color
  131. }.toXMLAttributes
  132. )
  133. text[1].add newText badge.value
  134. tree.add gradient
  135. tree.add main
  136. tree.add text
  137. if badge.image_path != "":
  138. var img = newFileStream(badge.image_path, fmRead)
  139. var image = img.readAll
  140. img.close
  141. tree.add newXMLTree(
  142. "image", [], {
  143. "xlink:href": "data:image/png;base64," & encode image,
  144. "width": $badge.height, "height": $badge.height,
  145. "x": radius, "y": "0",
  146. "fill": badge.image_color
  147. }.toXMLAttributes
  148. )
  149. return $tree
  150. proc write*(badge: BadgeRef, filename: string) =
  151. var strm = newFileStream(filename, fmWrite)
  152. strm.write $badge
  153. strm.close