UserPath.m 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * UserPath.m by Bruce Blumberg, NeXT Computer, Inc.
  3. *
  4. * You may freely copy,distribute and re-use the code in this example. NeXT
  5. * disclaims any warranty of any kind, expressed or implied, as to its fitness
  6. * for any particular purpose
  7. *
  8. */
  9. #import "UserPath.h"
  10. #import <mach/mach_init.h>
  11. #import <appkit/graphics.h>
  12. #import <appkit/errors.h>
  13. #import <math.h>
  14. #import <libc.h>
  15. static NXZone *upZone = NULL;
  16. NXZone *userPathZone()
  17. /* Creates a unique zone for use by all user paths */
  18. {
  19. if (!upZone) {
  20. upZone = NXCreateZone(vm_page_size, vm_page_size, 1);
  21. }
  22. return upZone;
  23. }
  24. UserPath *newUserPath()
  25. /* Creates a new User Path in the zone returned by userPathZone */
  26. {
  27. UserPath *up;
  28. up = (UserPath *)NXZoneMalloc(userPathZone(), sizeof(UserPath));
  29. up->max = 8192; // JDC
  30. up->points = (float *)NXZoneMalloc(userPathZone(),
  31. sizeof(float) * up->max);
  32. up->ops = (char *)NXZoneMalloc(userPathZone(),
  33. (2 + (up->max / 2)) * sizeof(char));
  34. up->ping = NO;
  35. return up;
  36. }
  37. void freeUserPath(UserPath *up)
  38. /* Frees User Path and its associated buffers */
  39. {
  40. free(up->points);
  41. free(up->ops);
  42. free(up);
  43. return;
  44. }
  45. void growUserPath(UserPath *up)
  46. /*
  47. * grows the associated buffers as necessary. buffer size doubles on each
  48. * call. You never need to call grow directly as it is called as needed by the
  49. * methods and functions which add elements into the buffer
  50. */
  51. {
  52. /* double the size of the internal buffers */
  53. printf ("growUserPath\n");
  54. up->max *= 2;
  55. up->points = (float *)NXZoneRealloc(userPathZone(), up->points,
  56. sizeof(float) * up->max);
  57. up->ops = (char *)NXZoneRealloc(userPathZone(), up->ops,
  58. (2 + (up->max / 2)) * sizeof(char));
  59. return;
  60. }
  61. void beginUserPath(UserPath *up, BOOL cache)
  62. /*
  63. * Call this to start generating a user path. The cache argument specifies if
  64. * you want the user path cached at the server (i.e. dps_ucache). In either
  65. * case, the UserPath object will automatically calculate the bounding box for
  66. * the path and add the dps_setbbox operator.
  67. */
  68. {
  69. up->numberOfPoints = up->numberOfOps = 0;
  70. up->cp.x = up->cp.y = 0;
  71. up->bbox[0] = up->bbox[1] = 1.0e6;
  72. up->bbox[2] = up->bbox[3] = -1.0e6;
  73. if (cache) {
  74. up->ops[up->numberOfOps++] = dps_ucache;
  75. }
  76. up->ops[up->numberOfOps++] = dps_setbbox;
  77. up->opForUserPath = 0;
  78. return;
  79. }
  80. void endUserPath(UserPath *up, int op)
  81. /*
  82. * Call this to stop filling the path. Note this does not send the userpath to
  83. * the server -- use sendUserPath. The op argument should be one of the
  84. * following:
  85. * dps_uappend, dps_ufill ,dps_ueofill, dps_ustroke, dps_ustrokepath,
  86. * dps_inufill, dps_inueofill, dps_inustroke, dps_def, dps_put.
  87. * These are defined in <dpsclient/dpsNext.h.
  88. */
  89. {
  90. up->opForUserPath = op;
  91. return;
  92. }
  93. void UPdebug(UserPath *up, BOOL shouldPing)
  94. /*
  95. * Sets ping to YES so that after each time a user path is sent down to the
  96. * window server, an NXPing() is sent after. The purpose is to catch PostScript
  97. * errors that may be generated by the user path. sendUserPath brackets the
  98. * download and the NXPing() in an NX_DURING... NX_HANDLER construct. Normally
  99. * ping is NO.
  100. */
  101. {
  102. up->ping = shouldPing;
  103. return;
  104. }
  105. int sendUserPath(UserPath *up)
  106. /*
  107. * Call this to send the path down to the server. If ping==YES (set via
  108. * debug:), the function will send an NXPing() after the Path. In any event,
  109. * code is bracketed by a NX_DURING ... NX_HANDLER construct which will try to
  110. * catch postscript errors. If ping==NO (the default) it is unlikely to catch
  111. * errors, with ping==YES it will. Whether you can recover or not is another
  112. * matter. sendUserPath returns 0 on success and -1 on failure. If no previous
  113. * endUserPath: has been sent, will return -2 and will not send the path to the
  114. * server.
  115. */
  116. {
  117. NXHandler exception;
  118. exception.code = 0;
  119. if (up->opForUserPath != 0) {
  120. NX_DURING
  121. DPSDoUserPath(up->points, up->numberOfPoints, dps_float, up->ops,
  122. up->numberOfOps, up->bbox, up->opForUserPath);
  123. if (up->ping) {
  124. NXPing();
  125. }
  126. NX_HANDLER
  127. exception = NXLocalHandler;
  128. NX_ENDHANDLER
  129. if (exception.code) {
  130. NXReportError(&exception);
  131. if (exception.code == dps_err_ps) {
  132. return -1;
  133. }
  134. } else {
  135. return 0;
  136. }
  137. }
  138. return -1;
  139. }
  140. void UPmoveto(UserPath *up, float x, float y)
  141. /* adds <x y moveto> to user path and updates bounding box */
  142. {
  143. up->ops[up->numberOfOps++] = dps_moveto;
  144. up->points[up->numberOfPoints++] = x;
  145. up->points[up->numberOfPoints++] = y;
  146. if (x < up->bbox[0]) {
  147. up->bbox[0] = x;
  148. }
  149. if (y < up->bbox[1]) {
  150. up->bbox[1] = y;
  151. }
  152. if (x > up->bbox[2]) {
  153. up->bbox[2] = x;
  154. }
  155. if (y > up->bbox[3]) {
  156. up->bbox[3] = y;
  157. }
  158. return;
  159. }
  160. void UPlineto(UserPath *up, float x, float y)
  161. /* adds <x y lineto> to user path and updates bounding box */
  162. {
  163. up->ops[up->numberOfOps++] = dps_lineto;
  164. up->points[up->numberOfPoints++] = x;
  165. up->points[up->numberOfPoints++] = y;
  166. if (x < up->bbox[0]) {
  167. up->bbox[0] = x;
  168. }
  169. if (y < up->bbox[1]) {
  170. up->bbox[1] = y;
  171. }
  172. if (x > up->bbox[2]) {
  173. up->bbox[2] = x;
  174. }
  175. if (y > up->bbox[3]) {
  176. up->bbox[3] = y;
  177. }
  178. return;
  179. }