textspan.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * @file
  3. * @ingroup common_render
  4. * @brief @ref textspan_size
  5. */
  6. /*************************************************************************
  7. * Copyright (c) 2011 AT&T Intellectual Property
  8. * All rights reserved. This program and the accompanying materials
  9. * are made available under the terms of the Eclipse Public License v1.0
  10. * which accompanies this distribution, and is available at
  11. * https://www.eclipse.org/legal/epl-v10.html
  12. *
  13. * Contributors: Details at https://graphviz.org
  14. *************************************************************************/
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <cdt/cdt.h>
  19. #include <common/render.h>
  20. #include <common/textspan_lut.h>
  21. #include <util/alloc.h>
  22. #include <util/strcasecmp.h>
  23. /* estimate_textspan_size:
  24. * Estimate size of textspan, for given face and size, in points.
  25. */
  26. static void
  27. estimate_textspan_size(textspan_t * span, char **fontpath)
  28. {
  29. double fontsize;
  30. int flags = span->font->flags;
  31. bool bold = (flags & HTML_BF) != 0;
  32. bool italic = (flags & HTML_IF) != 0;
  33. fontsize = span->font->size;
  34. span->size.x = 0.0;
  35. span->size.y = fontsize * LINESPACING;
  36. span->yoffset_layout = 0.0;
  37. span->yoffset_centerline = 0.1 * fontsize;
  38. span->layout = NULL;
  39. span->free_layout = NULL;
  40. span->size.x = fontsize * estimate_text_width_1pt(span->font->name, span->str, bold, italic);
  41. if (fontpath)
  42. *fontpath = "[internal hard-coded]";
  43. }
  44. /*
  45. * This table maps standard Postscript font names to URW Type 1 fonts.
  46. */
  47. static PostscriptAlias postscript_alias[] = {
  48. #include "ps_font_equiv.h"
  49. };
  50. static int fontcmpf(const void *a, const void *b)
  51. {
  52. return strcasecmp(a, ((const PostscriptAlias*)b)->name);
  53. }
  54. static PostscriptAlias* translate_postscript_fontname(char* fontname)
  55. {
  56. static char *key;
  57. static PostscriptAlias *result;
  58. if (key == NULL || strcasecmp(key, fontname)) {
  59. free(key);
  60. key = gv_strdup(fontname);
  61. result = bsearch(key, postscript_alias,
  62. sizeof(postscript_alias) / sizeof(PostscriptAlias),
  63. sizeof(PostscriptAlias), fontcmpf);
  64. }
  65. return result;
  66. }
  67. pointf textspan_size(GVC_t *gvc, textspan_t * span)
  68. /// Estimates size of a textspan, in points.
  69. {
  70. char **fpp = NULL, *fontpath = NULL;
  71. textfont_t *font;
  72. assert(span->font);
  73. font = span->font;
  74. assert(font->name);
  75. /* only need to find alias once per font, since they are unique in dict */
  76. if (! font->postscript_alias)
  77. font->postscript_alias = translate_postscript_fontname(font->name);
  78. if (Verbose && emit_once(font->name))
  79. fpp = &fontpath;
  80. if (! gvtextlayout(gvc, span, fpp))
  81. estimate_textspan_size(span, fpp);
  82. if (fpp) {
  83. if (fontpath)
  84. fprintf(stderr, "fontname: \"%s\" resolved to: %s\n",
  85. font->name, fontpath);
  86. else
  87. fprintf(stderr, "fontname: unable to resolve \"%s\"\n", font->name);
  88. }
  89. return span->size;
  90. }
  91. static void *textfont_makef(void *obj, Dtdisc_t *disc) {
  92. (void)disc;
  93. textfont_t *f1 = obj;
  94. textfont_t *f2 = gv_alloc(sizeof(textfont_t));
  95. /* key */
  96. if (f1->name) f2->name = gv_strdup(f1->name);
  97. if (f1->color) f2->color = gv_strdup(f1->color);
  98. f2->flags = f1->flags;
  99. f2->size = f1->size;
  100. /* non key */
  101. f2->postscript_alias = f1->postscript_alias;
  102. return f2;
  103. }
  104. static void textfont_freef(void *obj) {
  105. textfont_t *f = obj;
  106. free(f->name);
  107. free(f->color);
  108. free(f);
  109. }
  110. static int textfont_comparf(void *key1, void *key2) {
  111. int rc;
  112. textfont_t *f1 = key1, *f2 = key2;
  113. if (f1->name || f2->name) {
  114. if (! f1->name) return -1;
  115. if (! f2->name) return 1;
  116. rc = strcmp(f1->name, f2->name);
  117. if (rc) return rc;
  118. }
  119. if (f1->color || f2->color) {
  120. if (! f1->color) return -1;
  121. if (! f2->color) return 1;
  122. rc = strcmp(f1->color, f2->color);
  123. if (rc) return rc;
  124. }
  125. if (f1->flags < f2->flags) return -1;
  126. if (f1->flags > f2->flags) return 1;
  127. if (f1->size < f2->size) return -1;
  128. if (f1->size > f2->size) return 1;
  129. return 0;
  130. }
  131. void textfont_dict_open(GVC_t *gvc) {
  132. DTDISC(&gvc->textfont_disc, 0, sizeof(textfont_t), -1, textfont_makef, textfont_freef, textfont_comparf);
  133. gvc->textfont_dt = dtopen(&(gvc->textfont_disc), Dtoset);
  134. }
  135. void textfont_dict_close(GVC_t *gvc)
  136. {
  137. dtclose(gvc->textfont_dt);
  138. }