You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

setdotlabelwidth 3.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #!/usr/bin/env python3
  2. # encoding: utf-8
  3. # Copyright 2020 Huawei Technologies Co., Ltd
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. # ============================================================================
  17. import sys
  18. import math
  19. MIN_CHARS_PER_ROW = 20 # minimal number of chars on one line
  20. COLS_TO_ROWS_RATIO = 4 # ratio of # columns to # rows (unit is char)
  21. MAX_LABEL_LENGTH = 1000 # maximal number of chars of a label
  22. # for specified number of chars, calculate a suitable number for how many chars per row
  23. # Num Total Chars : n
  24. # Num Chars Per Row : m
  25. # Num Rows : k
  26. # (k - 1) * m < n <= k * m
  27. # suppose: m / k = u
  28. # ==> sqrt(u * n) <= m < u / 2 + sqrt(u * n + u * u / 4)
  29. # m = max(20, m)
  30. # parameters:
  31. # @total_chars number of total chars
  32. # @ratio ratio of # columns to # rows (unit is char)
  33. def calc_num_chars_per_row(total_chars, ratio):
  34. chars_per_row = math.ceil(math.sqrt(total_chars * ratio))
  35. return max(MIN_CHARS_PER_ROW, chars_per_row)
  36. def process_label_text(text):
  37. label_len = min(len(text), MAX_LABEL_LENGTH)
  38. chars_per_row = calc_num_chars_per_row(label_len, COLS_TO_ROWS_RATIO)
  39. if label_len <= MIN_CHARS_PER_ROW:
  40. return text
  41. beg_idx = 0
  42. texts = []
  43. while beg_idx < label_len:
  44. end_idx = beg_idx + chars_per_row
  45. if end_idx >= label_len:
  46. texts.append(text[beg_idx:label_len])
  47. else:
  48. texts.append(text[beg_idx:end_idx])
  49. beg_idx = end_idx
  50. return "\\n".join(texts)
  51. # insert '\n' to labels which are too long
  52. def process_file(f):
  53. line_text = f.readline()
  54. beg_idx = -1 # label begin index, index of 'label="'
  55. end_idx = -1 # label end index, index of '"'
  56. label_text = ""
  57. label_prefix = ""
  58. label_postfix = ""
  59. while line_text:
  60. line_text = line_text.rstrip()
  61. if beg_idx < 0:
  62. beg_idx = line_text.find('label="')
  63. if beg_idx >= 0:
  64. end_idx = line_text.find('"', beg_idx + len('label="'))
  65. if end_idx >= 0: # the full label text is on one line
  66. label = line_text[beg_idx + len('label="'):end_idx]
  67. print('%slabel="%s"%s' % (line_text[0:beg_idx], process_label_text(label), line_text[end_idx + 1:]))
  68. beg_idx = -1 # reset to initial conditions
  69. else: # the label text is distributed on multiple lines
  70. label_prefix = line_text[0:beg_idx]
  71. label_text = line_text[beg_idx + len('label="'):]
  72. else:
  73. print(line_text)
  74. else:
  75. end_idx = line_text.find('"')
  76. if end_idx >= 0:
  77. label_text = label_text + line_text[0:end_idx]
  78. label_postfix = line_text[end_idx + 1:]
  79. print('%slabel="%s"%s' % (label_prefix, process_label_text(label_text), label_postfix))
  80. beg_idx = -1 # reset to initial conditions
  81. else:
  82. label_text += line_text
  83. # print(f'{len(line_text)} - {line_text}')
  84. line_text = f.readline()
  85. if __name__ == "__main__":
  86. if len(sys.argv) > 1 and sys.argv[1] == "--help":
  87. print("Usage: %s < dotfile | dot -Tpng -o filename.png" % sys.argv[0])
  88. sys.exit()
  89. # read text from stdin
  90. process_file(sys.stdin)