home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / sharewar / dos / program / gs300sr1 / gs300sr1.exe / ZCHAR1.C < prev    next >
C/C++ Source or Header  |  1994-07-27  |  10KB  |  336 lines

  1. /* Copyright (C) 1993 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* zchar1.c */
  20. /* Type 1 character display operator */
  21. #include "ghost.h"
  22. #include "errors.h"
  23. #include "oper.h"
  24. #include "gsstruct.h"
  25. #include "gxfixed.h"
  26. #include "gxmatrix.h"
  27. #include "gschar.h"
  28. #include "gxdevice.h"        /* for gxfont.h */
  29. #include "gxfont.h"
  30. #include "gxfont1.h"
  31. #include "gxtype1.h"
  32. #include "estack.h"
  33. #include "ialloc.h"
  34. #include "ichar.h"
  35. #include "idict.h"
  36. #include "ifont.h"
  37. #include "igstate.h"
  38. #include "store.h"
  39.  
  40. /* Forward references */
  41. private void op_type1_free(P1(os_ptr));
  42. private int type1_call_OtherSubr(P3(gs_type1_state *, int (*)(P1(os_ptr)), const ref *));
  43. private int type1_continue_dispatch(P3(gs_type1_state *, const byte *, ref *));
  44.  
  45. /* <string> .type1getsbw <lsbx> <lsby> <wx> <wy> */
  46. private int type1getsbw_continue(P1(os_ptr));
  47. private int type1getsbw_push(P2(os_ptr, gs_type1_state *));
  48. int
  49. ztype1getsbw(register os_ptr op)
  50. {    gs_show_enum *penum = op_show_find();
  51.     gs_font_type1 *pfont = (gs_font_type1 *)gs_currentfont(igs);
  52.     gs_type1_data *pdata;
  53.     gs_type1_state is;        /* stack allocate to avoid sandbars */
  54.     gs_type1_state *pis = &is;
  55.     int code;
  56.     ref other_subr;
  57.     if ( penum == 0 || pfont->FontType != ft_encrypted )
  58.       return_error(e_undefined);
  59.     check_type(*op, t_string);
  60.     pdata = &pfont->data;
  61.     if ( r_size(op) <= pdata->lenIV )
  62.       return_error(e_invalidfont);
  63.     check_estack(4);    /* in case we need to do a callback */
  64.     check_ostack(3);    /* for returning the result */
  65.     code = gs_type1_init(pis, penum, NULL,
  66.                  gs_show_in_charpath(penum), pdata->PaintType,
  67.                  pdata);
  68.     if ( code < 0 )
  69.       return code;
  70.     code = type1_continue_dispatch(pis, op->value.const_bytes,
  71.                        &other_subr);
  72.     switch ( code )
  73.     {
  74.     default:        /* code < 0 or done, error */
  75.         return((code < 0 ? code : gs_note_error(e_invalidfont)));
  76.     case type1_result_callothersubr:    /* unknown OtherSubr */
  77.         return type1_call_OtherSubr(pis, type1getsbw_continue,
  78.                         &other_subr);
  79.     case type1_result_sbw:            /* [h]sbw, done */
  80.         break;
  81.     }
  82.     return type1getsbw_push(op, pis);
  83. }
  84.  
  85. /* Push the results on the o-stack.  The caller must have done */
  86. /* a check_ostack. */
  87. private int
  88. type1getsbw_push(register os_ptr op, gs_type1_state *pis)
  89. {    push(3);
  90.     make_real(op - 3, fixed2float(pis->lsb.x));
  91.     make_real(op - 2, fixed2float(pis->lsb.y));
  92.     make_real(op - 1, fixed2float(pis->width.x));
  93.     make_real(op, fixed2float(pis->width.y));
  94.     return 0;
  95. }
  96.  
  97. /* Continue from an OtherSubr callback. */
  98. private int
  99. type1getsbw_continue(os_ptr op)
  100. {    ref other_subr;
  101.     gs_type1_state *pis = r_ptr(esp, gs_type1_state);
  102.     int code;
  103.     check_ostack(3);    /* for returning the result */
  104.     code = type1_continue_dispatch(pis, (const byte *)0, &other_subr);
  105.     op = osp;        /* in case z1_push/pop_proc was called */
  106.     switch ( code )
  107.     {
  108.     default:        /* code < 0 or done, error */
  109.         op_type1_free(op);
  110.         return((code < 0 ? code : gs_note_error(e_invalidfont)));
  111.     case type1_result_callothersubr:    /* unknown OtherSubr */
  112.         push_op_estack(type1getsbw_continue);
  113.         ++esp;
  114.         *esp = other_subr;
  115.         return o_push_estack;
  116.     case type1_result_sbw:            /* [h]sbw, done */
  117.         op_type1_free(op);
  118.         type1getsbw_push(op, pis);
  119.         return o_pop_estack;
  120.     }
  121. }
  122.  
  123. /* <string> .type1addpath - */
  124. /* <string> <lsbx> <lsby> .type1addpath - */
  125. private int type1addpath_continue(P1(os_ptr));
  126. private int op_type1_cleanup(P1(os_ptr));
  127. int
  128. ztype1addpath(register os_ptr op)
  129. {    int code = 0;
  130.     ref other_subr;
  131.     const byte *str;
  132.     gs_show_enum *penum = op_show_find();
  133.     gs_font_type1 *pfont = (gs_font_type1 *)gs_currentfont(igs);
  134.     gs_type1_data *pdata;
  135.     gs_type1_state is;        /* stack allocate to avoid sandbars */
  136.     gs_type1_state *pis = &is;
  137.     float sbxy[2];
  138.     gs_point sbpt;
  139.     gs_point *psbpt = 0;
  140.     os_ptr opc = op;
  141.     if ( penum == 0 || pfont->FontType != ft_encrypted )
  142.       return_error(e_undefined);
  143.     if ( !r_has_type(opc, t_string) )
  144.       {    check_op(3);
  145.         code = num_params(op, 2, sbxy);
  146.         if ( code < 0 )
  147.           return code;
  148.         sbpt.x = sbxy[0];
  149.         sbpt.y = sbxy[1];
  150.         psbpt = &sbpt;
  151.         opc -= 2;
  152.         check_type(*opc, t_string);
  153.       }
  154.     pdata = &pfont->data;
  155.     if ( r_size(opc) <= pdata->lenIV )
  156.        {    /* String is empty, or too short.  Just ignore it. */
  157.         goto ret;
  158.        }
  159.     check_estack(4);    /* in case we need to do a callback */
  160.     code = gs_type1_init(pis, penum, psbpt,
  161.                  gs_show_in_charpath(penum), pdata->PaintType,
  162.                  pdata);
  163.     if ( code < 0 )
  164.       return code;
  165.     str = opc->value.const_bytes;
  166. cont:    code = type1_continue_dispatch(pis, str, &other_subr);
  167.     switch ( code )
  168.     {
  169.     case 0:            /* all done */
  170.         break;
  171.     default:        /* code < 0, error */
  172.         return code;
  173.     case type1_result_callothersubr:    /* unknown OtherSubr */
  174.         return type1_call_OtherSubr(pis, type1addpath_continue,
  175.                         &other_subr);
  176.     case type1_result_sbw:            /* [h]sbw, just continue */
  177.         str = 0;
  178.         goto cont;
  179.     }
  180. ret:    pop((psbpt == 0 ? 1 : 3));
  181.     return code;
  182. }
  183.  
  184. /* Continue from an OtherSubr callback. */
  185. private int
  186. type1addpath_continue(os_ptr op)
  187. {    ref other_subr;
  188.     gs_type1_state *pis = r_ptr(esp, gs_type1_state);
  189.     int code;
  190. cont:    code = type1_continue_dispatch(pis, (const byte *)0, &other_subr);
  191.     op = osp;        /* in case z1_push/pop_proc was called */
  192.     switch ( code )
  193.     {
  194.     case 0:            /* all done */
  195.     {    /* Assume the OtherSubrs didn't mess with the o-stack.... */
  196.         int npop = (r_has_type(op, t_string) ? 1 : 3);
  197.         pop(npop);  op -= npop;
  198.         op_type1_free(op);
  199.         return o_pop_estack;
  200.     }
  201.     default:        /* code < 0, error */
  202.         op_type1_free(op);
  203.         if ( code < 0 )
  204.             return code;
  205.         else
  206.             return_error(e_invalidfont);
  207.     case type1_result_callothersubr:    /* unknown OtherSubr */
  208.         push_op_estack(type1addpath_continue);
  209.         ++esp;
  210.         *esp = other_subr;
  211.         return o_push_estack;
  212.     case type1_result_sbw:            /* [h]sbw, just continue */
  213.         goto cont;
  214.     }
  215. }
  216.  
  217. /* ----- Internal procedures ------ */
  218.  
  219. /* Do a callback to an OtherSubr implemented in PostScript. */
  220. /* The caller must have done a check_estack. */
  221. private int
  222. type1_call_OtherSubr(gs_type1_state *pis, int (*cont)(P1(os_ptr)),
  223.   const ref *pos)
  224. {    /* Move the Type 1 interpreter state to the heap. */
  225.     gs_type1_state *hpis = ialloc_struct(gs_type1_state,
  226.                          &st_gs_type1_state,
  227.                          ".type1addpath");
  228.     if ( hpis == 0 )
  229.       return_error(e_VMerror);
  230.     *hpis = *pis;
  231.     update_stem_hints(hpis);
  232.     push_mark_estack(es_show, op_type1_cleanup);
  233.     ++esp;
  234.     make_istruct(esp, 0, hpis);
  235.     push_op_estack(cont);
  236.     ++esp;
  237.     *esp = *pos;
  238.     return o_push_estack;
  239. }
  240.  
  241. /* Handle the results of gs_type1_interpret. */
  242. private int
  243. type1_continue_dispatch(gs_type1_state *pis, const byte *charstring, ref *pos)
  244. {    int value;
  245.     int code;
  246. cont:    code = gs_type1_interpret(pis, charstring, &value);
  247.     switch ( code )
  248.     {
  249.     case type1_result_seac:
  250.     {    font_data *pfdata = pfont_data(gs_currentfont(igs));
  251.         ref *pcstr;
  252.         ref enc_entry;
  253.         code = array_get(&StandardEncoding, (long)value, &enc_entry);
  254.         if ( code < 0 )
  255.             return code;
  256.         if ( dict_find(&pfdata->CharStrings,
  257.                    &enc_entry, &pcstr) <= 0 )
  258.             return_error(e_undefined);
  259.         if ( !r_has_type(pcstr, t_string) )
  260.             return_error(e_invalidfont);
  261.         charstring = pcstr->value.const_bytes;
  262.     }
  263.         goto cont;
  264.     case type1_result_callothersubr:
  265.     {    /* The Type 1 interpreter handles all known othersubrs, */
  266.         /* so this must be an unknown one. */
  267.         font_data *pfdata = pfont_data(gs_currentfont(igs));
  268.         code = array_get(&pfdata->OtherSubrs, (long)value, pos);
  269.         return (code < 0 ? code : type1_result_callothersubr);
  270.     }
  271.     }
  272.     return code;
  273. }
  274. /* Clean up after a Type 1 callback. */
  275. private int
  276. op_type1_cleanup(os_ptr op)
  277. {    ifree_object(r_ptr(esp + 2, void), "op_type1_cleanup");
  278.     return 0;
  279. }
  280. private void
  281. op_type1_free(os_ptr op)
  282. {    esp -= 2;        /* hpis, cleanup op */
  283.     op_type1_cleanup(op);
  284. }
  285.  
  286. /* ------ Auxiliary procedures for type 1 fonts ------ */
  287.  
  288. int
  289. z1_subr_proc(gs_type1_data *pdata, int index, const byte **pstr)
  290. {    /* Get the enclosing font by working backwards. */
  291.     gs_font_type1 *pfont = (gs_font_type1 *)
  292.         ((char *)pdata - offset_of(gs_font_type1, data));
  293.     font_data *pfdata = pfont_data(pfont);
  294.     ref *psubr;
  295.     if ( index < 0 || index >= r_size(&pfdata->Subrs) )
  296.         return_error(e_rangecheck);
  297.     psubr = pfdata->Subrs.value.refs + index;
  298.     check_type(*psubr, t_string);
  299.     *pstr = psubr->value.bytes;
  300.     return 0;
  301. }
  302.  
  303. int
  304. z1_push_proc(gs_type1_data *pdata, const fixed *pf, int count)
  305. {    const fixed *p = pf + count - 1;
  306.     int i;
  307.     check_ostack(count);
  308.     for ( i = 0; i < count; i++, p-- )
  309.       {    osp++;
  310.         make_real(osp, fixed2float(*p));
  311.       }
  312.     return 0;
  313. }
  314.  
  315. int
  316. z1_pop_proc(gs_type1_data *pdata, fixed *pf)
  317. {    float val;
  318.     int code = num_params(osp, 1, &val);
  319.     if ( code < 0 )
  320.         return code;
  321.     *pf = float2fixed(val);
  322.     osp--;
  323.     return 0;
  324. }
  325.  
  326. /* ------ Initialization procedure ------ */
  327.  
  328. op_def zchar1_op_defs[] = {
  329.     {"1.type1getsbw", ztype1getsbw},
  330.     {"1.type1addpath", ztype1addpath},
  331.         /* Internal operators */
  332.     {"0%type1getsbw_continue", type1getsbw_continue},
  333.     {"0%type1addpath_continue", type1addpath_continue},
  334.     op_def_end(0)
  335. };
  336.