home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / PostScriptFiles / TextFaceProcs.ps < prev    next >
Encoding:
Text File  |  2000-09-28  |  28.6 KB  |  954 lines  |  [TEXT/MPS ]

  1. %
  2. %    File:        TextFaceProcs.ps
  3. %
  4. %    Contains:    This file contains Procedures needed to construct layered fonts for text faces.
  5. %
  6. %    Version:    Technology:    Quickdraw GX 1.1.x.
  7. %
  8. %    Copyright:    © 1991-7 by Apple Computer, Inc., all rights reserved.
  9. %
  10. %
  11.  
  12. %        Add the bounding box on the stack as a rectangle to the current path.
  13. %
  14. %        x1 y1 x2 y2 BBoxPath -
  15. %
  16. /BBoxPath {
  17.  
  18.     3 index 3 index                        % Stack is: x1 y1 x2 y2 x1 y1
  19.     moveto                                        % Stack is: x1 y1 x2 y2
  20.     3 index 1 index                        % Stack is: x1 y1 x2 y2 x1 y2
  21.     lineto                                        % Stack is: x1 y1 x2 y2
  22.     2 copy                                        % Stack is: x1 y1 x2 y2 x2 y2
  23.     lineto                                        % Stack is: x1 y1 x2 y2
  24.     pop 1 index                                % Stack is: x1 y1 x2 y1
  25.     lineto lineto
  26.     closepath
  27.     
  28. } Bdef
  29.  
  30.  
  31. %
  32. %        Procedure StringBBox:
  33. %
  34. %        Procedure computes an accurate bounding box in current userspace for the string in the
  35. %        current font.
  36. %
  37. %        string StringBBox x1 y1 x2 y2
  38. %
  39. %        string:              string containing text of which to obtain bounding box.
  40. %        x1 y1 x2 y2:     returned on stack:  tight bounding box of glyph in user space.
  41. %
  42. /SaveMatrix matrix def
  43. /SaveFont null def
  44. /StringBBox {
  45.  
  46.     currentpoint 3 -1 roll                % Stack is Cx Cy char
  47.         
  48.     % Make the CTM so that character paths are in untransformed user space (Glyph space).
  49.     
  50.     SaveMatrix currentmatrix pop            % Save the current matrix.
  51.     initmatrix                                                % Set up the normal userspace matrix.
  52.     currentpoint translate                        % Make the currentpoint the origin.
  53.     currentfont dup /SaveFont Xstore    % Save the current font
  54.     100 scalefont                                            % and Make sure the font is scaled so we don't
  55.     setfont                                                        %  get hinting errors when we do the charpath (NTX shows this problem)
  56.  
  57.     false userdict /charpath known {    % Get the path
  58.         userdict /charpath get exec            %   If defined in userdict (by TT scaler for example) use it
  59.     } {                                                                % else
  60.         charpath                                                %     Execute whatever charpath is around
  61.     } ifelse
  62.     
  63.     pathbbox                                                    % Get the bounding box.
  64.     4 {100 div 4 1 roll} repeat                % Divide the result by how much we scaled the font.
  65.     newpath
  66.     
  67.     % Restore the graphics state (Matrix and font, path is left uninialized)
  68.     SaveMatrix setmatrix
  69.     SaveFont setfont
  70.     
  71.     % Stack is: Cx Cy x1 y1 x2 y2     (Bouding box in Glyph space).
  72.     
  73.     6 -2 roll                                     % Stack is: x1 y1 x2 y2 Cx Cy
  74.     2 copy                                            % Stack is: x1 y1 x2 y2 Cx Cy Cx Cy
  75.     translate                                        % Stack is: x1 y1 x2 y2 Cx Cy
  76.     
  77.     % CTM now has been translated so origin is at the currentpoint.
  78.     %  Mapping the points through this and then back through untranslated CTM yields userspace.
  79.     
  80.     6 2 roll                                        % Stack is: Cx Cy x1 y1 x2 y2
  81.     
  82.     % Translate the bounding box to device space
  83.     
  84.     transform                                        % Stack is: Cx Cy x1 y1 x2' y2'
  85.     4 2 roll transform                    % Stack is: Cx Cy x2' y2' x1' y1'
  86.     4 2 roll                                        % Stack is: Cx Cy x1' y1' x2' y2'
  87.     
  88.     % untranslate the CTM and put bounding box back in user space.
  89.     
  90.     6 -2 roll                                        % Stack is: x1' y1' x2' y2' Cx Cy
  91.     neg exch neg exch                        % Stack is: x1' y1' x2' y2' -Cx -Cy
  92.     translate                                        % Stack is: x1' y1' x2' y2'
  93.     itransform 4 2 roll                    % Stack is: x2'' y2'' x1' y1'
  94.     itransform 4 2 roll                    % Stack is: x1'' y1'' x2'' y2''
  95.     
  96. } Bdef
  97.  
  98.  
  99.  
  100. %<FF>
  101. %
  102. %        Procedure AddBBoxes:
  103. %
  104. %        Procedure produces the union of the passed in rectangle to the path's bounding box.
  105. %                if the first one is null, the second one is just left on the stack.
  106. %        x1 y1 x2 y2 px1 py1 px2 py2 AddBBoxes  x1' y1' x2' y2'
  107. %            or
  108. %        null px1 py1 px2 py2 AddBBoxes px1 py1 px2 py2
  109. %
  110. %            x1 y1 x2 y2:            starting bounding box
  111. %            px1 py1 px2 py2:    bounding box todd.
  112. %            x1' y1' x2' y2':    union of starting box and box to add.
  113. %
  114. /AddBBoxes {
  115.  
  116.     4 index null ne {                                                        % the first box is not null, add the two boxes.
  117.     
  118.         % stack is x1 y1 x2 y2 px1 py1 px2 py2
  119.         
  120.         4 index Max
  121.         4 1 roll
  122.         
  123.         % stack is x1 y1 x2 y2 y2' px1 py1 px2
  124.         
  125.         5 index Max
  126.         4 1 roll
  127.         % stack is x1 y1 x2 y2 x2' y2' px1 py1
  128.         
  129.         6 index Min
  130.         4 1 roll
  131.  
  132.         % stack is x1 y1 x2 y2 y1' x2' y2' px1
  133.         
  134.         7 index Min
  135.         4 1 roll
  136.         
  137.         % stack is x1 y1 x2 y2 x1' y2' x2' y2'
  138.         
  139.         8 4 roll
  140.         pop pop pop pop
  141.         
  142.     } {
  143.     
  144.         5 -1 roll pop                % Get rid of the null and leave the box as the sum of the two bounding boxes.
  145.         
  146.     } ifelse
  147.  
  148. } Bdef
  149.  
  150.  
  151. %<FF>
  152. %
  153. %        Procedure: LW8LayerBuildChar
  154. %
  155. %            This is a super-trimmed down version of LayerBuildChar that works for basic text
  156. %            faces.  All that is respected from the layers is:
  157. %                    outlineTransform,
  158. %                    framed layers (only if base font supports PaintType = 2)
  159. %                    whiteLayer, but drawn in white rather than transparently (like LW 7.x and 8.x drivers)
  160. %            BuildChar does not use PS font cache, thus allowing us to draw with white for white layers.
  161. %
  162. /LW8LayerBuildChar {
  163.  
  164.     exch begin                                % Put layered font dictionary on stack.
  165.     
  166.     Moby begin                                % Make sure Moby Dict is on stack.
  167.  
  168.     % Set up the metrics for the layered glyph.
  169.     
  170.     baseFont setfont
  171.     
  172.     theChar exch 0 exch put                % Make the integer back into a string.
  173.     theChar stringwidth                        % Get the metrics for this character
  174.     advanceMapping transform             % Run through advanceMapping.
  175.     setcharwidth                                    % Set up advances.
  176.  
  177.     faceLayers {
  178.     
  179.         gsave
  180.         begin                        % Put layer dictionary on dictionary stack.
  181.         
  182.             fillKey /No ne {                % Don't bother for no fill layers.
  183.         
  184.                 LayerFont setfont                            % Set font for layer.
  185.                 whiteLayer {1.0 setgray} if        % This is wrong, but fast.  Real LayerBuildChar does right thing.
  186.     
  187.                 outlineTransform begin                % Get the transform dictionary on the dict. stack.
  188.     
  189.                     isSimpleTranslation {                % If it is simple translation, can just do moveto without modifying CTM.
  190.                     
  191.                         xTrans yTrans moveto                %     Move to xTrans yTrans
  192.                         
  193.                     } {                                                        % Else                
  194.                     
  195.                         Mapping concat                            %        Concatenate the mapping with the CTM
  196.                         TrSetClip                                        %        Set the clip
  197.                         0 0 moveto                                     %        Move to 0,0 (goes through mapping)
  198.                     
  199.                     } ifelse
  200.     
  201.                 end                                                    % Pop transform dictionary off stack.
  202.     
  203.                 theChar show                                % Draw the layer's glyph (We can assume we don't need to use QD2Show for LW8 case.
  204.                 
  205.             } if
  206.         
  207.         end
  208.         grestore
  209.     
  210.     } forall
  211.     
  212.     
  213.     end 
  214.  
  215.     end
  216.  
  217. } Bdef
  218.  
  219.  
  220.  
  221. %<FF>
  222. %
  223. %    Procedure AdvanceMappingBuildChar:
  224. %        This is the buildchar procedure for a text face that has no layers but has an advance
  225. %            mapping.
  226. %
  227. /AdvanceMappingBuildChar {
  228.  
  229.     exch begin                                                % Put the layered font dictionary on the stack.
  230.  
  231.     theChar 0 3 -1 roll put                        % Save the character to render in the string.
  232.     
  233.     % Compute the new advance for the glyph
  234.     
  235.     baseFont setfont
  236.     theChar stringwidth
  237.     advanceMapping transform                    % Transform the advance of the character by the advanceMapping.
  238.     setcharwidth                                            % Set the transformed value to be new advance widths.
  239.     
  240.     % Now draw the glyph.
  241.     
  242.     0 0 moveto
  243.     theChar show
  244.     
  245.     end
  246.  
  247. } Bdef
  248.  
  249.  
  250.  
  251. %
  252. %        TextFaceSetupFontCache is a wrapper for "setcachedevice"
  253. %        It either does a setcharwidth or a setcachedevice.
  254. %        It also sets the clip to the bounding box passed in.
  255. %            Assumes text face font dictionary is on stack.
  256. %
  257. /TextFaceSetupFontCache {
  258.         
  259.     6 copy                                                % Copy the setcachedevice parameters so we can set the clip.
  260.     
  261.     languagelevel 2 ge HasPattern and {        % since in L2 patterns are colors, we can't use font cache.
  262.         pop pop pop pop setcharwidth                %   so don't, just set up metrics
  263.     } {                                                                        % else
  264.         setcachedevice                                            %     Set up the font cache parameters for layered glyph.
  265.     }    ifelse
  266.  
  267.     % Now with the copied setcachedevice parameters, set the clip.  Do it after call to 
  268.     %    setcachedevice becuase setcachedevice can modify the CTM depending on whether or not
  269.     % it actually succeeds in caching.  We wouldn't have to do any of this if we could depend
  270.     %    on setcachedevice setting the clip to the glyph bounding box like it is supposed to do.
  271.     
  272.     2 copy 6 -2 roll                            % Stack is now: wX wY x1 y1 x1 y1 x2 y2
  273.     BoxWidths                                            % stack is now:    wX wY x1 y2 W H
  274.     
  275.     %%%%% Draw X in bbox
  276.     %%%%% 0.02 setlinewidth 4 copy RStr
  277.     
  278.     RCl                                                        % Set the clip!
  279.     pop pop
  280.  
  281.  
  282. } Bdef
  283.  
  284.  
  285.  
  286. %
  287. %        ComputeLayerBBox
  288. %
  289. %        Function computes the bounding box for a layer.
  290. %
  291. %        Assumes dictionary for layer is on dict stack, layered font dict behind it,
  292. %            and theChar contains the character passed into BuildChar.
  293. %
  294. /ComputeLayerBBox {
  295.  
  296.     LayerFont setfont                            % Make the current font the layer's font.
  297.     
  298.     newpath 0 0 moveto                        % Place currentpoint at 0,0
  299.     theChar StringBBox                        % Get the bounding box of the glyph in userspace.
  300.                                                                 %   The rectangle: X1,Y1 X2,Y2 X3,Y3 X4,Y4
  301.                                                                 
  302.     
  303.  
  304.     % Take into account the layer's transform, bolness, pen, and dash to expand bounding box
  305.     
  306.                                                                 % Compute the rectangle: X1,Y1 X2,Y2 X3,Y3 X4,Y4
  307.     /Y3 Xdef        /X3 Xdef                    % Y3 X3 Y1 X1 are on stack 
  308.     /Y1 Xdef        /X1 Xdef                    % 
  309.     /X2 X3 def    /Y2 Y1 def                % X2, Y2 is really X3,Y1
  310.     /X4 X1 def    /Y4 Y3 def                % X4, Y4 is really X1,Y3
  311.  
  312.  
  313.     % Run the 4 points of the bounding box through the layer's transform.
  314.     
  315.     X1 Y1 outlineTransform /Mapping get transform /Y1 Xdef /X1 Xdef
  316.     X2 Y2 outlineTransform /Mapping get transform /Y2 Xdef /X2 Xdef
  317.     X3 Y3 outlineTransform /Mapping get transform /Y3 Xdef /X3 Xdef
  318.     X4 Y4 outlineTransform /Mapping get transform /Y4 Xdef /X4 Xdef
  319.     
  320.     % We now have the rectangle enclosing the glyph transformed through the layer's mapping, thus in glyph space.
  321.     % Now compute the glyph space box that encloses these points.
  322.  
  323.     X1 X2 Min X3 Min X4 Min                % x1
  324.     Y1 Y2 Min Y3 Min Y4 Min                % y1
  325.     X1 X2 Max X3 Max X4 Max                % x2
  326.     Y1 Y2 Max Y3 Max Y4 Max                % y2
  327.  
  328.  
  329.     %% Expand bounding box by pen, boldness, and dash bounding box.
  330.     
  331.     /LayerBBoxGrowX xBold 2 div def            % half of bold because bold specifies total in both in and out.
  332.     /LayerBBoxGrowY yBold 2 div def
  333.  
  334.     %
  335.     %        If it is a framed layer, expand the bounding box even more.
  336.     %
  337.     fillKey /Fr eq LayerFont /PaintType 2 copy known {get} {pop pop 0} ifelse 2 eq or {
  338.     
  339.         % Compute a device gridded pen size.
  340.         
  341.         outlineStyle /pen get dup dtransform            % Map pen to device space
  342.         2.0 Max exch 2.0 Max exch                                    % Make sure it is at least one pixel on each side of path to be stroked
  343.         idtransform                                                                % Map it back to user space.
  344.         Max                                                                                % Take the biggest of the x&y pen thickness.
  345.         /LayerPen exch def                                                % Save the value.    
  346.     
  347.         outlineStyle /dash get null ne {                    % If it dashed, expand by dash size.
  348.         
  349.             outlineStyle /dash get /Shape get ShapeBBox            % Get the bounding box of the dash.
  350.             BoxWidths exch pop                                                            % Get the height of the dash shape.
  351.             LayerPen 2 div mul dup                                                    % Multiply the Y height by pen thickness.
  352.             LayerBBoxGrowY add /LayerBBoxGrowY Xdef                    %    add it to the expansion value.
  353.             LayerBBoxGrowX add /LayerBBoxGrowX Xdef                    %    add it to the expansion value.
  354.             
  355.         } {            % Else, just expand by half the pen width.
  356.         
  357.             LayerBBoxGrowY LayerPen 2 div add /LayerBBoxGrowY Xdef
  358.             LayerBBoxGrowX LayerPen 2 div add /LayerBBoxGrowX Xdef
  359.         
  360.         } ifelse
  361.     
  362.     } if
  363.                 
  364.     LayerBBoxGrowY add                            % Stack is now: x1 y1 x2 y2+yBold
  365.     exch LayerBBoxGrowX add                    % Stack is now: x1 y1 y2+yBold x2+xBold
  366.     4 2 roll                                                % Stack is now: y2+yBold x2+xBold x1 y1
  367.     LayerBBoxGrowY sub                            % Stack is now: y2+yBold x2+xBold x1 y1-Bold
  368.     exch LayerBBoxGrowX sub                    % Stack is now: y2+yBold x2+xBold y1+yBold x1-xBold
  369.     exch 4 2 roll exch                            % stack is now: x1-xBold y1-yBold x2+xBold y2+yBold
  370.  
  371. } Bdef    
  372.  
  373.  
  374.  
  375.  
  376.  
  377. %<FF>
  378. %
  379. %        Procedure: ComputeFaceBBox
  380. %
  381. %        Computes the bounding box of a text face.  Can compute the tight bounding box for a particular
  382. %        glyph or the smallest necessary for any glyph.
  383. %        
  384. %        If autoAdvance is true, or any layers have inverseFill, then tight box is computed for character
  385. %            stored in theChar in layered font dictionary.  Otherwise, computes a gross bounding box.
  386. %
  387. %        assumes Layered font dictionary is on dict stack.
  388. %
  389. %        - ComputeFacBBox x1 y1 x2 y2
  390. %
  391. /ComputeFaceBBox {
  392.  
  393.     null                                                % Start the bounding box with null.
  394.     faceLayers {
  395.     
  396.         begin                                            % Put this layer dictionary on dict stack
  397.         
  398.             whiteLayer not fillKey /No ne and {        % White layers and noFil layers do not affect bounding box.
  399.                             
  400.                 ComputeLayerBBox        % Compute bounding box for this layer.
  401.                 AddBBoxes                        % Add it into the layered glyph bounding box
  402.             
  403.             } if
  404.             
  405.         end
  406.     
  407.     } forall    
  408.     
  409.     dup null eq {            % If there is a null on the stack, none of the layers contributed to bounding box.
  410.     
  411.         pop                         %        Pop off nul    
  412.         0 0 0 0                    %        Leave an empty bounding box on the stack.
  413.     
  414.     } if
  415.  
  416. } Bdef
  417.  
  418.  
  419.  
  420.  
  421.  
  422. %<FF>
  423. /LayerBuildChar {
  424.     
  425.     /TextFaceSave save store        % do a save for the buildchar
  426.                                                             %  This ensures that the buildchar has no side effects.    
  427.     
  428.     Moby begin                                    % Put Moby dict on stack.  Text face fonts can be
  429.                                                             %   called from synonyms in which case Moby is taken off stack.
  430.     
  431.     1 0 0 1 0 0                                 % Make the current font mapping the identity since all fonts drawn
  432.     AugGstate /FontMapping get    % in the layer are unscaled and boldness uses this mapping.
  433.     astore pop
  434.     
  435.  
  436.     exch begin                                    % Put the layered font dictionary on the dict stack.
  437.     
  438.     theChar exch 0 exch put            % Make the integer back into a string.
  439.     
  440.     %
  441.     % Generate the metrics for the layered glyph
  442.     %
  443.     baseFont setfont                        % Make the base font the current font.
  444.     theChar stringwidth                    % Get the advance metrics of the base glyph.
  445.             
  446.     
  447.     % If autoadvance was turned on, modify the advance width of the glyph by adding the difference
  448.     %        between the bounding box of the layered glyph and the base glyph to the advance widths of
  449.     %        the base glyph.  Only modify non-zero advance, however.
  450.     
  451.     autoAdvance {
  452.     
  453.         ComputeFaceBBox        % Compute the tight bounding box for the glyph
  454.     
  455.         % The 6 items on the top of the stack are now the bounding box number for the layered glyph
  456.         %        and the advance metrics of the original glyph.
  457.     
  458.         4 copy                        % Make a copy of the layered glyph's bounding box
  459.         10 4 roll                    % Move the copy behind the previously mentioned 6 items.
  460.         
  461.         % Get bounding box of original glyph
  462.         
  463.         baseFont setfont
  464.         newpath
  465.         0 0 moveto
  466.         theChar StringBBox
  467.         
  468.         % stack is now: x1 y1 x2 y2    wX wY x1 y1 x2 y2 x3 y3 x4 y4, (x3, y3, x4, y4 is box of original glyph)
  469.         
  470.         BoxWidths
  471.         
  472.         % stack is now: x1 y1 x2 y2 wX wY x1 y1 x2 y2 (x4-x3) (y4-y3)
  473.         
  474.         6 2 roll
  475.         
  476.         % stack is now: x1 y1 x2 y2 wX wY (x4-x3) (y4-y3) x1 y1 x2 y2
  477.         
  478.         BoxWidths
  479.         
  480.         % stack is now: x1 y1 x2 y2 wX wY (x4-x3) (y4-y3) (x2-x1) (y2-y1)
  481.                 
  482.         BoxWidths
  483.         
  484.         % Stack is now: x1 y1 x2 y2 wX wY delta-X delta-Y, deltas = differences in bbox dimensions.
  485.         
  486.         4 2 roll
  487.         % Stack is now: x1 y1 x2 y2 delta-X delta-Y wX wY
  488.         
  489.         dup 0 ne {2 index add} if                        % If starting wY wasn't 0 add delta-y to it.
  490.         exch
  491.         % Stack is now: x1 y1 x2 y2 delta-X delta-Y wYfinal wx
  492.         
  493.         dup 0 ne {3 index add} if                        % If starting wX wasn't 0 add delta-X to it.
  494.         exch
  495.         % Stack is now: x1 y1 x2 y2 delta-X delta-Y wXfinal wYfinal
  496.         
  497.         4 2 roll pop pop                        % Stack is now x1 y1 x2 y2 wXfinal wYfinal    
  498.         
  499.         advanceMapping transform        % Run the advance metrics through the advance mapping.
  500.                     
  501.         6 2 roll                                        % Stack is now wXfinal wYfinal x1 y1 x2 y2    
  502.         
  503.     } {                                                % Else, if no autoadvance, transform the normal advances.
  504.     
  505.         advanceMapping transform        % Transform them by the advance mapping.
  506.         
  507.         ComputeBBox {                                %        Inverse fill requires tight bounding box.
  508.             ComputeFaceBBox                        %     Compute it.
  509.         } {                                                    % Else
  510.             /FontBBox load cvx exec        %     Just use the Layered font's big bounding box, its faster.
  511.         } ifelse
  512.         
  513.     } ifelse
  514.  
  515.     % Stack now contains bounding box and metrics
  516.     
  517.     TextFaceSetupFontCache
  518.     
  519.     %
  520.     %        Now draw the layered glyph into the font cache:
  521.     %        •    The layers are drawn in reverse order so white-layers can be done as clips.
  522.     %    
  523.     nLayers 1 sub -1 0 {                            % Traverse layers in reverse order.
  524.     
  525.         faceLayers exch get begin                    % Put this layer's dictionary on dict stack.
  526.         
  527.             fillKey /No ne {            % Ignore layer if it is noFill.
  528.             
  529.                 newpath                                                        % Get ready for drawing
  530.                 LayerFont setfont                                    % Make this layer's font the current font
  531.                 whiteLayer {                                            % If it is a white layer then set clip
  532.         
  533.                     CurrCTM currentmatrix            % Save a copy of the current transform (on stack) for restoring.
  534.                     
  535.                     outlineTransform SetTr        % Apply the outline transform.
  536.                     0 0 moveto                                % Move to 0 0 before drawing the glyph.
  537.                     theChar false GXCharPath    % Get the path of the character
  538.                     /In {QD2Clip}    stopped {        % Inverse clip to the character. (if we can't clip oh well)
  539.                         newpath                                    %   If not, then just clean up the current path.
  540.                     } if
  541.                     
  542.                     setmatrix                                    % Restore the transform, clips carry through for subsequent layers.
  543.                 
  544.                 } {
  545.                     
  546.                     outlineStyle SetStyle                        % Set the style for this layer in augmented g-state.
  547.                     xBold yBold SetBold                            % Set the boldness for the layer in augmented g-state.
  548.  
  549.                     gsave
  550.  
  551.                     outlineTransform SetTr
  552.                     SynchPatMatrix                                                        % Synchronize the pattern with the CTM.
  553.                     newpath 0 0 moveto                                                % moveto where 0 0.
  554.                     mark                                                                            % Set up to clean up after the show
  555.                     theChar fillKey {QD2Show} stopped    {                % Do the show if it fails.
  556.                         counttomark 6 eq{                                                % Check if we have to do any clean up
  557.                             5{pop}repeat                                                     % Pop the parameters to image mask
  558.                             dup type /savetype eq{restore}if            % Do the restore for save that TT scaler left.
  559.                         }if                                                                            %
  560.                     } if                                                                            % 
  561.                     cleartomark    
  562.  
  563.                     grestore
  564.                 
  565.                 } ifelse
  566.                 
  567.             } if
  568.         
  569.         end                                                                % Pop layer dictionary off dict stack.
  570.         
  571.     } for
  572.  
  573.     end                                                            % pop font dictionary off dict stack.
  574.  
  575.  
  576.     end                                                        % Pop Moby dict off dict stack.
  577.     
  578.     TextFaceSave restore            % Restore it!
  579.  
  580. } Bdef
  581.  
  582.  
  583. %<FF>
  584. %
  585. %        Procedure MakeLayerDict:
  586. %
  587. %        Procedure Makes a face layer dictionary.
  588. %
  589. %        fillKey whiteLayer outlineStyle outlineTransform xBold yBold MakeLayerDict dict
  590. %
  591. %            fillKey:                            The fill key for the layer.
  592. %            whiteLayer:                        Boolean, true if this bit is set in the layerFlags.
  593. %            outlineStyle:                    The style for this layer.
  594. %            outlineTransform:            The transform for this layer.
  595. %            xBold yBold:                    boldness from layer.
  596. %
  597. %            dict:                                    Left on stack, a layer dictionary.
  598. %
  599. /MakeLayerDict {
  600.  
  601.     19 dict begin                    %    Create a dictionary
  602.  
  603.     /yBold Xdef
  604.     /xBold Xdef
  605.     /outlineTransform Xdef
  606.     /outlineStyle Xdef
  607.     /whiteLayer Xdef
  608.     /fillKey Xdef
  609.     /layerIndex 0 def
  610.     
  611.     /LayerFont null def                % The seventh entry will be base font for this layer.
  612.     
  613.     /LayerBBoxGrowX 0 def                                            % Compute amount to grow layer's bounding box in X
  614.     /LayerBBoxGrowY 0 def                                            % Compute amount to grow layer's bounding box in Y
  615.     /X1 0 def /Y1 0 def /X2 0 def /Y2 0 def        %    Store layer's bouding box in here.
  616.     /X3 0 def /Y3 0 def /X4 0 def /Y4 0 def
  617.     
  618.     /LayerPen 0 def                                                        % Compute device gridded pen size for framed layers here.    
  619.     
  620.     currentdict                                % Leave the layer dictionary on the operand stack.
  621.             
  622.     end
  623.  
  624. } Bdef
  625.  
  626.  
  627.  
  628. %<FF>
  629. %
  630. %    Procedure MakeLayeredFontDict:
  631. %        Procedure makes a type-3 font to represent the text face (without underlines) applied to 
  632. %            The base font specified.  The base font cannot be a composite font.
  633. %
  634. % baseFont faceBBox autoAdvance advanceMapping faceLayers useLW8BuildChar MakeLayeredFontDict layeredFontDict
  635. %
  636. %        useLW8BuildChar:        Use the fast buildchar routine?
  637. %        faceLayers:                    An array of layer dictionaries
  638. %        advanceMapping:            The Skia Advance mapping from the face data structure.
  639. %        autoAdvance:                Boolean, Autoadvance bit from style runs's style.
  640. %        faceBBox:                        Bounding box of text face at 1 point as 4 element array., null means unknown, must be computed.
  641. %        baseFont:                        The base font dictionary.
  642. %
  643. %        Left on stack:
  644. %            layeredFontDict:                    The dictionary describing the layered font.
  645. %
  646. /MakeLayeredFontDict {
  647.  
  648.     16 dict begin                                    % Make a dictionary for the type-3 font.
  649.     
  650.     %        Save the parameters
  651.     
  652.     /useLW8BuildChar Xdef
  653.     /faceLayers Xdef
  654.     /advanceMapping Xdef
  655.     /autoAdvance Xdef
  656.  
  657.     % Stack is: baseFont faceBBox
  658.     %Invert Y axis of base font and Face's bounding box.
  659.     %     Since the layered-font must be selected without flipping the Y axis so skewing
  660.     %     in the layer's transform works correctly.  (works backwards otherwise)
  661.     %        Use this opportunity of calling makefont to apply the layer's style's point size as well.
  662.     %        Also, properly scale the bounding box by the same matrix.
  663.  
  664.     [ 1 0 0 -1 0 0 ] exch
  665.     dup null ne {
  666.         aload pop 4 index transform 4 2 roll 4 index transform 4 2 roll 4 array astore /FontBBox Xdef
  667.         /ComputeBBox false def
  668.     } {
  669.         pop
  670.         /FontBBox [0 0 0 0] def
  671.         /ComputeBBox true def                    % We must compute a bounding box for each glyph.
  672.     } ifelse
  673.         
  674.     makefont /baseFont Xdef
  675.     
  676.     %        Some needed local variables for the layered font.
  677.     
  678.     /theChar 1 string def                                            % Place for character to render.
  679.     /nLayers faceLayers length def                        %    Number of layers.
  680.     /CurrCTM matrix def                                                % We need to save the CTM someplace during layering.
  681.     
  682.     /HasPattern false def                                            % We need to know if any layers have a pattern.
  683.     
  684.     %        Some needed font dictionary entries.
  685.     
  686.     /FontType 3 def
  687.     /FontMatrix matrix def
  688.     /Encoding                                                                    % Copy the encoding vector from the base font.
  689.         baseFont /Encoding get
  690.     def
  691.     
  692.     nLayers 0 eq {                        % If # layers is zero then
  693.     
  694.         /BuildChar /AdvanceMappingBuildChar load def          % Use simple build-char for zero layer faces
  695.         
  696.     } {                                                % Else use the layer-build char and compute modified layer fonts.
  697.     
  698.         useLW8BuildChar {
  699.  
  700.             /BuildChar /LW8LayerBuildChar load def
  701.  
  702.         } {
  703.  
  704.             /BuildChar /LayerBuildChar load def
  705.  
  706.         } ifelse
  707.         
  708.         %
  709.         %    For each layer, create The modified base font that will be used.
  710.         %
  711.         %
  712.         baseFont                            % Get base font dict on the stack.
  713.         
  714.         faceLayers {                                    % For each layer:
  715.         
  716.             exch dup 3 -1 roll                        % Duplicate the base font dict, stick it behind the layer dict.
  717.             begin                                                    % Put layer dictionary on dict stack.
  718.                 outlineStyle begin                    % Put the layer's style dictionary on dict stack.
  719.  
  720.                     % Stack is now baseFontDict
  721.                                 
  722.                     % If the layer's style is framed, and there is no dash, and the font supports changing PaintType
  723.                     %    make a framed font and change the fill key to windingNumber
  724.                     fillKey /Fr eq dash null eq and baseFont /PaintType known and {
  725.                     
  726.                         pen                                                                        % Stack is now baseFontDict stylePen
  727.                         1 index exch MakeFramedFont
  728.                         /FredTheFramedFont exch definefont        % Stack is now baseFontDict framedFontDict
  729.                         exch pop                                                            % Get rid duplicate base font
  730.                         /fillKey /W store                                            % Change the fill in layerDict to be winding-number because show will now do framed.
  731.                                 
  732.                     } if
  733.                     
  734.                     %  Now the font dictionary is on the stack.
  735.                     % Scale font for layer and bounding box if necessary.
  736.                     
  737.                     textSize 1 ne {
  738.                                                 
  739.                         textSize scalefont                                % Scale layerFontDict by textSize.
  740.                         /LayerFont Xstore                                    % Store in in layer dictionary.
  741.                         
  742.                     } {
  743.  
  744.                         /LayerFont Xstore                                        % No need to change font on stack.
  745.  
  746.                     } ifelse
  747.                                         
  748.                     pattern null ne {/HasPattern true store} if        % set flag in the font dictionary if there is pattern.
  749.                     fillKey /In eq {/ComputeBBox true store} if        % Inverse Fill means we need to compute a tight bounding box.
  750.                     
  751.                 end
  752.                                     
  753.             end
  754.             
  755.         } forall
  756.         
  757.         pop                                                            % Get rid of the extra base font dictionary.
  758.         
  759.     } ifelse
  760.  
  761.     currentdict                                                % Leave the dictionary on the operand stack.
  762.     
  763.     end
  764.  
  765. } Bdef
  766.  
  767.  
  768.  
  769. %<FF>
  770. /cUseLW8BuildChar false def
  771. /cFaceLayers null def
  772. /cAdvanceMapping null def
  773. /cAutoAdvance null def
  774. /cfaceBBox null def
  775. %
  776. %    Procedure MakeLayeredCompositeFont
  777. %        Procedure makes a composite font's whose child fonts are type-3 layered font dictionaries.
  778. %        The face layer parameters are retrieved from the globals stored in Moby Dict by MakeLayeredFont
  779. %
  780. %        baseFont MakeLayeredCompositeFont layeredFontDict:
  781. %
  782. %            baseFont:                the base font dictionary of the composite font.
  783. %
  784. /MakeLayeredCompositeFont {
  785.  
  786.     dup /FontType get 0 eq {                        % If the font passed is a composite font then get all of the child fonts
  787.     
  788.         
  789.         0 MakeFontClone dup begin                    % Make a clone of the font, put it on dict stack
  790.             
  791.             FDepVector {                                        % For each font in the FDepVector
  792.             
  793.                 MakeLayeredCompositeFont                    % Pass font dictionary from the vector back in recursively
  794.                 /FDepLayeredFont exch definefont    %    Make it a valid font.
  795.             
  796.             } forall
  797.  
  798.             FDepVector length array astore                % Make a new FDepVector with the new layered fonts.
  799.             /FDepVector exch def
  800.             
  801.         end
  802.         
  803.     
  804.     } {            % Recursive termination condition: font was not composite, make a layered font out of it.
  805.     
  806.         cfaceBBox
  807.         cAutoAdvance
  808.         cAdvanceMapping
  809.  
  810.         % Make a new array of face layers so the child font has its own copy.
  811.         %     since each child font has its own base font dictionary (as opposed to the main
  812.         %     font dictionary) which is stored in the layer dictionary.
  813.         [        
  814.             cFaceLayers {
  815.             
  816.                 begin
  817.                     fillKey whiteLayer outlineStyle outlineTransform xBold yBold
  818.                 end
  819.                 
  820.                 MakeLayerDict            % make a new Copy of the layer dictionary.
  821.                 
  822.             } forall
  823.         ]
  824.         
  825.         cUseLW8BuildChar
  826.             
  827.         MakeLayeredFontDict
  828.     
  829.     } ifelse
  830.  
  831. } Bdef
  832.  
  833.  
  834.  
  835. %    Procedure MakeLayeredFont:
  836. %        Procedure makes a type-3 font to represent the text face (without underlines) applied to 
  837. %            The base font specified.  The base font can be a composite font and the layered font
  838. %            is generated recursively (in this case, the font created is a type-0 with child
  839. %            fonts that are type-3 text face fonts.
  840. %
  841. %  psFontName layerFontName baseFont faceBBox autoAdvance advanceMapping faceLayers cUseLW8BuildChar MakeLayeredFont layeredFontDict
  842. %
  843. %        cUseLW8BuildChar:        Boolean of indicating to use fast/wrong buildChar for LW driver performance.
  844. %        faceLayers:                    An array of layer dictionaries
  845. %        advanceMapping:            The Skia Advance mapping from the face data structure.
  846. %        autoAdvance:                Boolean, Autoadvance bit from style runs's style.
  847. %        faceBBox:                        Bounding box of text face font at 1 point.
  848. %        baseFont:                        The base font dictionary.
  849. %        layerFontName:            The name to give the text face font so it can be used again.
  850. %        psFontName:                    Name of potential font on printer that may be usable for this face.
  851. %
  852. %        Left on stack:
  853. %            layeredFontDict:                    The dictionary describing the layered font.
  854. %
  855. /MakeLayeredFont {
  856.  
  857.     6 index FontDirectory exch known {    % If layerFontName exists, then we've already made this font.
  858.     
  859.         pop pop pop pop pop pop                        %    Pop    the face parameters off the stack.
  860.         
  861.         % (Using Cached font:) print dup == flush
  862.         
  863.         findfont                                                    %    Just get the font we already made.
  864.         exch pop                                                    % pop off the psFontName.
  865.     
  866.     } {                                                                % Else, make the font from the text face parameters
  867.     
  868.         7 index FontDirectory exch known {    % Can we make it from the psFontName font
  869.  
  870.             pop pop pop pop pop                                % stack is: psFontName layerFontName baseFont
  871.             
  872.             % (Making Face from ROM:) print 2 index == flush
  873.             
  874.             % Get the encoding to use from the base font.
  875.             
  876.             /Encoding get                            % stack is: psFontName layerFontName encoding
  877.             2 index findfont                    % stack is: psFontName layerFontName encoding psFontDict
  878.             [1 0 0 -1 0 0] makefont        % flip it in the Y direction - so Imaging Engine's SFt works correctly.
  879.             0 MakeFontClone                        % Clone the font dictionary.
  880.             dup 3 -1 roll                            % Stack is: psFontName layerFontName psFontDict psFontDict encoding
  881.             /Encoding exch put                % Stack is: psFontName layerFontName reencodedFlippedFontDict.
  882.  
  883.         } {
  884.         
  885.             % (Making Algorithmic font) == flush
  886.  
  887.             5 index /FontType get 0 ne {            % If baseFont is not a composite font then just do it.
  888.             
  889.                 MakeLayeredFontDict
  890.             
  891.             } {                                                                % Else recursively traverse the embedded font dictionaries
  892.             
  893.                 % Store the face parameters in Moby Dict
  894.                 
  895.                 /cUseLW8BuildChar Xdef
  896.                 /cFaceLayers Xdef
  897.                 /cAdvanceMapping Xdef
  898.                 /cAutoAdvance Xdef
  899.                 /cfaceBBox Xdef
  900.                 
  901.                 % the base font dict is left on the stack.
  902.                 
  903.                 MakeLayeredCompositeFont                    % Make a layered composite font
  904.             
  905.             } ifelse
  906.             
  907.         } ifelse
  908.  
  909.         % Stack is: psFontName layerFontName layeredFontDict
  910.         
  911.         exch dup /DontCache eq {    % If the name is DontCache, then just use name LayeredFont and it won't be cached.
  912.         
  913.             pop /LayeredFont
  914.             
  915.         } if
  916.             
  917.         exch                                            % Stack is psFontName layeredFontName layerFontDict
  918.         
  919.         definefont                                % Define it using layerFontName, leave the dict on the stack.
  920.         
  921.         exch pop                                    % Pop off the psFontName
  922.         
  923.     } ifelse
  924.  
  925. } Bdef
  926.  
  927.  
  928.  
  929. %<FF>
  930. %    Procedure MakeSimpleLayeredFont:
  931. %        Procedure makes a text face font for the simple one layer case.
  932. %            This can be many orders of magnitude faster in the uncached case as a general
  933. %            text face font.
  934. %
  935. %        baseFont faceMapping MakeSimpleLayeredFont layeredFontDict
  936. %
  937. %        layerMapping:                The mapping in the text face's layer.
  938. %        baseFont:                        The base font dictionary.
  939. %
  940. %        Left on stack:
  941. %            layeredFontDict:                    The dictionary describing the layered font.
  942. %
  943. /MakeSimpleLayeredFont {
  944.     
  945.     % Concatenate the face mapping with invert in Y direction
  946.     %        because PostScript coordinate system is flipped.  Do it here otherwise skewing happens backwards.
  947.     
  948.     [1 0 0 -1 0 0] exch ScratchMatrix concatmatrix            % Scale the layer's mapping by 1,-1
  949.     makefont                                                                                        % Do a makefont.
  950.     
  951.     % We're done, very simple Eh??
  952.     
  953. } Bdef
  954.