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 / Imaging Engine / PrimaryDrones.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  19.5 KB  |  671 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        PrimaryDrones.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains Routines for the Imaging Engine Primary Drones
  6.  
  7.      Version:    Technology:    Quickdraw GX 1.1.x
  8.       
  9.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  10. */
  11.  
  12. #include "GXToPSBuildConfig.h"
  13. #include "RDUtil.h"
  14. #include "PublicPostScriptIE.h"
  15. #include "private.h"
  16. #include "PSIEResources.h"
  17. #include "GXGraphics.h"
  18. #include "GXGraphicsPriv.h"
  19. #include "ShapeUtilities.h"
  20.  
  21. #ifdef resumeLabel
  22.     #undef resumeLabel
  23. #endif
  24. #define resumeLabel(exception)
  25.  
  26.  
  27.  
  28.  
  29. /*******************************
  30.     The Shape Drone:
  31.     
  32.     This routine is responsible for getting the parts of the shape
  33.     (style, transform, ink, etc…) and calling the respective shape-parts drones
  34.     to translate them to PostScript.  It is the shape drone that governs the
  35.     graphics state.  The order in which the shape parts drones are called
  36.     is vital to the proper maintenance of the graphics state.
  37.     
  38.         hIEGlobals:            An imaging Engine globals handle.
  39.         theShape:                The shape to translate to PostScript.
  40.         parents:                An array of transforms which describe the ancestory of the shape, 1st is root.
  41.         depth:                    The depth of the shape in the picture hierarchy.
  42.     
  43. *********************************/
  44. OSErr ShapeDrone (TIEGlobalsHdl hIEGlobals, gxShape theShape, gxTransform *parents, long depth)
  45.     {
  46.         OSErr                                status;
  47.         gxStyle                            theStyle;
  48.         gxTransform                    theTransform;
  49.         gxInk                                theInk, oldInk;
  50.         TIEGlobalsPtr                pGlobals;
  51.         TGstate                            *pGstate;
  52.         long                                nSyn;
  53.  
  54.                 
  55.         /** Now process each shape part **/
  56.         
  57.         theStyle =             GXGetShapeStyle(theShape);
  58.         theTransform =     GXGetShapeTransform(theShape);
  59.         theInk =                 GXGetShapeInk(theShape);
  60.         
  61.         /**** Handle the transform hiearchy ****/
  62.         #if USECOMPATFLAGS
  63.             if (!((*hIEGlobals)->compatFlags.flags1 & kPSIgnoreTransformList))
  64.                 nrequire(status = DoTransformHiearchy(hIEGlobals, parents, depth, theShape), failed_Hiearchy);
  65.         #else
  66.             nrequire(status = DoTransformHiearchy(hIEGlobals, parents, depth, theShape), failed_Hiearchy);
  67.         #endif
  68.         
  69.         pGlobals = *hIEGlobals;
  70.                     
  71.         /********** 
  72.             The style will persist across grestores, but do it after the transform because
  73.             doing the transform hiearchy could do a restore (Calling FHBalanceSaveLevel)
  74.             if the font handler had done a  save that we have to grestore before to.  Since
  75.             the restore will even flush our persistent state, output the style after the transform
  76.             hiearchy.  Fear not, if DoTransform calls FHBalanceSaveLevel, it marks the style as out
  77.             of date so the style drone is forced to update the printer's state.
  78.         **********/
  79.         
  80.         pGlobals = *hIEGlobals;
  81.         if ( !PSEqualStyle(pGlobals->theStyle, theStyle) || (pGlobals->ieStateFlags & eStyleOutOfDate) ) {
  82.         
  83.             nrequire(status = StyleDrone(hIEGlobals, theStyle), failed_Style);
  84.             pGlobals = *hIEGlobals;
  85.             
  86.             GXDisposeStyle(pGlobals->theStyle);
  87.             pGlobals->theStyle = GXCloneStyle(theStyle);
  88.             
  89.         }//end if
  90.  
  91.         /**********
  92.             The ink is maintained as part of the nested graphics state because there is no good way
  93.             in both language levels to put it on the stack and set it back across a grestore.
  94.         ***********/
  95.         pGlobals = *hIEGlobals;
  96.         pGstate = &(pGlobals->gStateNest[pGlobals->gStateDepth]);
  97.         oldInk = pGstate->theInk;
  98.         if (!PSEqualInk(oldInk, theInk) || (pGlobals->ieStateFlags & eInkOutOfDate)) {
  99.             
  100.             /** Output the ink **/
  101.             
  102.             status = InkDrone(hIEGlobals, theInk);
  103.             nrequire(status, failed_Ink);
  104.             
  105.             /** replace graphics' state ink with new one **/
  106.             
  107.             GXDisposeInk(oldInk);
  108.             pGlobals = *hIEGlobals;
  109.             pGstate = &(pGlobals->gStateNest[pGlobals->gStateDepth]);
  110.             pGstate->theInk = GXCloneInk(theInk);
  111.                     
  112.         }//end if
  113.         
  114.         
  115.         
  116.         
  117.         /** If there are shape synonyms output them, else translate the shape to postscript **/
  118.  
  119.         nSyn = GXGetShapeTags(theShape, gxPostScriptTag, 1, gxSelectToEnd, nil);
  120.                 
  121.         if ( nSyn == 0 )
  122.             nrequire(status = FillShapeDrone(hIEGlobals, theShape, parents, depth), failed_FillShape);
  123.         else
  124.             nrequire(status = PostScriptSynonymDrone(hIEGlobals, theShape, nSyn), failed_Synonym);
  125.         
  126.         /** Do this every time to be safe - Unclear if there is a better way **/
  127.         
  128. failed_FillShape:
  129. failed_Synonym:
  130. failed_Ink:
  131. failed_Hiearchy:
  132. failed_Style:
  133.     
  134.     
  135.         return(status);
  136.         
  137.         
  138.     }//ShapeDrone
  139.  
  140. //<FF>
  141. /**********************************
  142.  
  143.     Routine:    SwapShapeAndBitmapClip
  144.     
  145.     For geometric shapes with bitmap clips,
  146.     we can resolve this by swapping the shape
  147.     and the clip and drawing the bitmap in the
  148.     color of the shape.
  149.     
  150. ***********************************/
  151. void SwapShapeAndBitmapClip(gxShape theShape)
  152.     {
  153.         gxColor                        shapeColor;
  154.         gxSetColor                newSetColor;
  155.         gxShape                        newShape, newClip;
  156.         gxBitmap                    clipBits;
  157.         gxMapping                    tempMap;
  158.         gxTag                            orTag;
  159.     
  160.         check(GXGetShapeType(theShape) != gxBitmapType);
  161.     
  162.         newShape = GXGetShapeClip(theShape);                // Get the clip as the new shape.
  163.             
  164.         check(GXGetShapeType(newShape) == gxBitmapType);
  165.         
  166.         GXGetBitmap(newShape, &clipBits, nil);
  167.         
  168.         check(clipBits.pixelSize == 1);
  169.         
  170.         /** Make the bitmaps' 1 bits in the color of the shape **/
  171.  
  172.         GXGetShapeColor(theShape, &shapeColor);
  173.  
  174.         clipBits.profile = shapeColor.profile;
  175.         clipBits.space = shapeColor.space;
  176.     
  177.         newSetColor.component[0] = shapeColor.element.component[0];
  178.         newSetColor.component[1] = shapeColor.element.component[1];
  179.         newSetColor.component[2] = shapeColor.element.component[2];
  180.         newSetColor.component[3] = shapeColor.element.component[3];
  181.         
  182.         GXSetColorSetParts(clipBits.set, 2, 1, 1, &newSetColor);        // sure hope this isn't shared.
  183.  
  184.         /** Make the clip the original shape with style applied **/
  185.  
  186.         newClip = GXCopyToShape(nil, theShape);
  187.         GXPrimitiveShape(newClip);
  188.         
  189.         GXSetShapeMapping(newShape, GXGetShapeMapping(theShape, &tempMap));
  190.         GXSetShapeClip(newShape, newClip);
  191.         GXDisposeShape(newClip);
  192.  
  193.         /** Make sure the bitmap is in or-mode **/
  194.         
  195.         orTag = GXNewTag(orModeTag, 0, nil);
  196.         GXSetInkTags(GXGetShapeInk(newShape), orModeTag, 1, 0, 0, &orTag);
  197.         GXDisposeTag(orTag);
  198.         
  199.         GXCopyToShape(theShape, newShape);                // put the new shape in the old shape.
  200.         
  201.         GXDisposeShape(newShape);
  202.  
  203.         ncheck(GXGetGraphicsError(nil));
  204.     
  205.     }//SwapShapeAndBitmapClip
  206.  
  207.  
  208. //<FF>
  209. /******************
  210.  
  211.     Routine:    ResolveComplexTransform:
  212.     
  213.     Routine checks the transform hiearchy to see if it is too complex for PostScript.
  214.     If the hiearchy contains any transforms that have perspective or bitmap clips,
  215.     or the hiearchy is deeper than maximum allowable gsave levels,
  216.     the shape will be mapped by gx graphics up to that level in the hiearchy.
  217.     The transform at that level will then become the identity and that
  218.     level will become the bottom-most level of the hiearchy and depth
  219.     modified appropriately.
  220.     
  221.         hIEGLobals:                imaging engine global state.
  222.         parents:                    Array of parent transforms of the current shape.
  223.         depth:                        Length of this array, can be modified.
  224.         pShape:                        Current shape to be drawn, by reference; may be changed.
  225.     
  226. *******************/
  227. OSErr ResolveComplexTransform(TIEGlobalsHdl hIEGlobals, gxTransform *parents, long *depth,
  228.                                                                 gxShape *pShape)
  229.     {
  230.         OSErr                 status = noErr;
  231.         gxMapping            aMapping;
  232.         gxTransform        aTransform, *pTransform;
  233.         gxShape                shapeCopy, theShape;
  234.         long                    gsaveLimit;
  235.         long                    postscriptableDepth;                    // Maximum transform depth that is PostScriptable.
  236.         long                    i;
  237.         gxShape                clipShape;
  238.         gxShapeType        clipType;
  239.         
  240.         theShape = *pShape;
  241.         gsaveLimit = (*hIEGlobals)->params.gsaveLimit;
  242.         
  243.         /** See if the shape itself has a text clip or a bitmap clip and fix it!! **/
  244.         
  245.         clipType = GXGetShapeClipType(theShape);
  246.         if ( (clipType == gxTextType) || (clipType == gxGlyphType) || (clipType == gxLayoutType) ) {
  247.         
  248.             clipShape = GXGetShapeClip(theShape);
  249.             status = TextToUnhintedPath(clipShape);
  250.             GXSetShapeClip(theShape, clipShape);
  251.             GXDisposeShape(clipShape);
  252.             nrequire(status, failed_TextToUnhintedPath);
  253.         
  254.         } else if (clipType == gxBitmapType) {
  255.  
  256.             status = DupShapeIfNecessary(theShape, &shapeCopy);
  257.             nrequire(status, failed_Dup);
  258.             theShape = shapeCopy;
  259.             SwapShapeAndBitmapClip(theShape);
  260.         
  261.         }//end if
  262.         
  263.         /** Find the maximum depth of the hiearchy that is PostScriptable **/
  264.         
  265.         pTransform = parents;
  266.         for (postscriptableDepth = 0; postscriptableDepth < *depth; ++postscriptableDepth) {
  267.         
  268.             aTransform = *pTransform++;
  269.             
  270.             GXGetTransformMapping(aTransform, &aMapping);
  271.             if ( (postscriptableDepth >= gsaveLimit) || TestMappingPerspective(&aMapping) ) {
  272.                 break;
  273.             }//end if
  274.         
  275.             /*****
  276.                     While we're here, convert text clips into paths, Could do something better
  277.                     later using charpath clip, etc…  We'll just do this for alpha, however,
  278.             ******/
  279.             clipType = GetTransformClipType(aTransform);
  280.             if ( (clipType == gxTextType) || (clipType == gxGlyphType) || (clipType == gxLayoutType) ) {
  281.             
  282.                 clipShape = GXGetTransformClip(aTransform);
  283.                 status = TextToUnhintedPath(clipShape);
  284.                 GXSetTransformClip(aTransform, clipShape);
  285.                 GXDisposeShape(clipShape);
  286.                 nrequire(status, failed_TextToUnhintedPath);
  287.             
  288.             } else if (clipType == gxBitmapType) {
  289.             
  290.                 break;                // bitmap clip in hiearchy means stop here.
  291.                 
  292.             }//end if
  293.             
  294.         }//end for
  295.         
  296.         GXGetShapeMapping(theShape, &aMapping);            // Include shapes own mapping in test.
  297.         
  298.         /** If the transform hiearchy is too complex (too deep or contains perspective or bitmap clip), fix it!! **/
  299.         
  300.         if ((postscriptableDepth < *depth) || TestMappingPerspective( &aMapping ) ) {
  301.  
  302.             gxTransform        newShapeTransform;
  303.             
  304.             status = DupShapeIfNecessary(theShape, &shapeCopy);            // In case shape is shared, make a copy
  305.             nrequire(status, failed_Dup);
  306.             theShape = shapeCopy;
  307.             
  308.             newShapeTransform = GXNewTransform();
  309.             GXResetTransform(newShapeTransform);
  310.  
  311.             /** Concatenate all of the non-postscriptable transforms **/
  312.             
  313.             pTransform = &(parents[postscriptableDepth]);
  314.             for (i = postscriptableDepth; i < *depth; ++i, ++pTransform) {
  315.                 
  316.                 aTransform = *pTransform;
  317.                 ConcatTransform(newShapeTransform, aTransform);
  318.             
  319.             }//end for
  320.             
  321.             ConcatTransform( newShapeTransform, GXGetShapeTransform(theShape) );
  322.             GXSetShapeTransform(theShape, newShapeTransform);
  323.             GXDisposeTransform(newShapeTransform);
  324.             
  325.             /* Map the shape through the concatenated transform */
  326.             
  327.             MapWholeShape(theShape, nil);
  328.             
  329.             /** Check to see if we ended up with a bitmap on the shape's clip and fix it if we did. **/
  330.  
  331.             if (GXGetShapeClipType(theShape) == gxBitmapType) {
  332.             
  333.                 status = DupShapeIfNecessary(theShape, &shapeCopy);
  334.                 nrequire(status, failed_Dup);
  335.                 theShape = shapeCopy;
  336.                 SwapShapeAndBitmapClip(theShape);
  337.                 
  338.             }//end if
  339.  
  340.         }//end if
  341.         
  342.             
  343.         *depth = postscriptableDepth;                    // new transform depth.
  344.         *pShape = theShape;                                        // new shape if it was created.
  345.         
  346. failed_IntersectShapeAndBitmap:
  347. failed_Graphics:
  348. failed_MapShape:
  349. failed_Dup:
  350. failed_TextToUnhintedPath:
  351.  
  352.         return(status);
  353.     
  354.     }//ResolveComplexTransform
  355.  
  356.  
  357. //<FF>
  358. /***************************************
  359.     The Validate Fill-Shape drone:
  360.     
  361.     This procedure is responsible for making sure that the 
  362.     shape can be translated into PostScript.  If it
  363.     has any style attributes that cannot, it must use gx graphics to
  364.     resolve them.  See ERS for more details.
  365.     
  366.         hIEGlobals:            An imaging Engine globals handle.
  367.         pShape:                    The shape to translate to PostScript, by reference; may be changed.
  368.     
  369. *********************************/
  370. OSErr ValidateFillShape(TIEGlobalsHdl hIEGlobals, gxShape *pShape)
  371.     {
  372.         OSErr                                    status = noErr;
  373.         gxShape                                theShape, shapeCopy;
  374.         gxStyle                                theStyle;
  375.         gxStyleAttribute            theAttributes;    
  376.         gxShapeFill                        theFill;
  377.         gxShapeType                        theType;
  378.         Fixed                                    penWidth;
  379.         Fixed                                    theInset = 0;
  380.         gxJoinRecord                    theJoin;
  381.         gxDashRecord                    theDash;
  382.         gxPatternRecord                thePattern;
  383.         long                                    psVal;
  384.         TIEPrimitiveFlags            primFlags = 0;
  385.  
  386.         theShape = *pShape;
  387.  
  388.         theType = GXGetShapeType(theShape);
  389.         theDash.dash = nil;
  390.         theJoin.join = nil;
  391.         thePattern.pattern = nil;
  392.         
  393.         /*********
  394.             First primitivize any point-shape since we can't
  395.             do these in PostScript except hairlines
  396.         *******/
  397.         
  398.         if ((theType == gxPointType) && (GXGetShapePen(theShape) != 0)) {
  399.         
  400.             primFlags = eApplyFrameStyle;
  401.             status = DupShapeIfNecessary(theShape, &shapeCopy);
  402.             nrequire(status, failed_Duplicate);
  403.             theShape = shapeCopy;
  404.             
  405.             #if DEBUGLEVEL >= DEBUGFEEDBACK
  406.                 dprintf(trace, "Primitivizing Point Shape");
  407.             #endif
  408.  
  409.             status = PSPrimitiveShape(theShape, primFlags);
  410.             nrequire(status, failed_PointShape);
  411.         
  412.         }//end if
  413.         
  414.         
  415.         theFill = GXGetShapeFill(theShape);
  416.         theStyle = GXGetShapeStyle(theShape);
  417.         theAttributes = GXGetStyleAttributes(theStyle);
  418.         GXGetShapePattern(theShape, &thePattern);    
  419.         
  420.         
  421.         /** Check for inverse winding fill and resolve it **/
  422.  
  423.         if (theFill == gxInverseWindingFill) {
  424.         
  425.             GXSimplifyShape(theShape);
  426.             nrequire(status = GXGetGraphicsError(nil), failed_Simplify);
  427.             
  428.             theFill = GXGetShapeFill(theShape);                // these may have changed, update them.
  429.             theType = GXGetShapeType(theShape);
  430.             
  431.         }//end if
  432.     
  433.         if ((theType == gxEmptyType) && (theFill != gxInverseFill) )
  434.             return(noErr);
  435.  
  436.         /** For text type shapes, check for postscriptable text faces and underlines **/
  437.         
  438.         if ( (theType == gxTextType) || (theType == gxGlyphType) || (theType == gxLayoutType) ) {
  439.             
  440.             Boolean            hasUnderlines;
  441.             Boolean            notPostscriptable;
  442.             
  443.             status = AnalyzeTextFace(hIEGlobals, theShape, &hasUnderlines, ¬Postscriptable);
  444.             nrequire(status, failed_Underlines);
  445.             
  446.             if (notPostscriptable) {
  447.             
  448.                 #if DEBUGLEVEL >= DEBUGFEEDBACK
  449.                     dprintf(trace, "Shape has non-postscriptable text face - converting to paths");
  450.                 #endif
  451.                 status = DupShapeIfNecessary(theShape, &shapeCopy);
  452.                 nrequire(status, failed_Duplicate);
  453.                 theShape = shapeCopy;
  454.                 status = PSTextToPaths(theShape);            /* make a picture full of paths, 1 per glyph. */
  455.                 nrequire(status, failed_TextToPaths);
  456.                 
  457.             } else if (hasUnderlines) {
  458.  
  459.                 #if DEBUGLEVEL >= DEBUGFEEDBACK
  460.                     dprintf(trace, "Shape has underlines");
  461.                 #endif
  462.                 
  463.                 status = DupShapeIfNecessary(theShape, &shapeCopy);        // don't screw with a shared shape.
  464.                 nrequire(status, failed_Duplicate);
  465.                 theShape = shapeCopy;
  466.                 
  467.                 nrequire(status = SeperateUnderlineShape(hIEGlobals, theShape), failed_Underlines);
  468.                 
  469.             }//end if        
  470.         
  471.         /** For non text, framed shapes… **/
  472.         
  473.         } else if ((theFill == gxFrameFill) || (theFill == gxClosedFrameFill) ) {
  474.         
  475.             /** First see if dashing isn't postscriptable **/
  476.         
  477.             GXGetShapeDash(theShape, &theDash);
  478.             
  479.             if ((theDash.dash != nil) && (GXGetStyleTags(theStyle, gxDashSynonymTag, 1, gxSelectToEnd, nil) == 0) ) {
  480.             
  481.                 if (!TestDashPostScriptable(theShape, &theDash, theAttributes)) {
  482.                 
  483.                     primFlags |= eApplyFrameStyle;
  484. #if DEBUGLEVEL >= DEBUGFEEDBACK
  485.                     dprintf(trace, "Dash is not PostScriptable, Calling PrimitiveShape");
  486. #endif
  487.                     goto finished_Validate;
  488.                     
  489.                 } else if (theDash.attributes & gxAutoAdvanceDash) {                    // modify dash advance for fit-dash.
  490.                 
  491. #ifdef SkiaCalculatesRightLength
  492.  
  493.                     wide            tempWide;
  494.                     long            nDashes;
  495.                     
  496.                     /** There will ultimately be a gx graphics call GetShapeDashAdvance or something that does this **/
  497.                     
  498.                     dprintf(notrace, "Old advance: %F", theDash.advance);
  499.                     nDashes = WideDivide( GetShapeLength(theShape, 1, &tempWide), theDash.advance, 0);
  500.                     theDash.advance = WideDivide(&tempWide, nDashes, 0);
  501.                     
  502.                     GXSetShapeDash(theShape, &theDash);
  503.                     GXSetShapeStyleAttributes(theShape, theAttributes & ~autoAdvance);
  504.  
  505.                     dprintf(notrace, "length: %d . %F,# Dashes %d, New advance: %F", 
  506.                                         tempWide.hi, tempWide.lo, nDashes, theDash.advance);
  507.                                         
  508. #endif
  509.  
  510.                 }//end if
  511.             
  512.             }//end if
  513.             
  514.             penWidth = GXGetStylePen(theStyle);
  515.             
  516.             /** Now see if the join isn't PostScriptable **/
  517.             
  518.             GXGetStyleJoin(theStyle, &theJoin);
  519.             psVal = GetPSLineJoin(&theJoin);
  520.             
  521.             if (psVal == -1) {
  522.             
  523.                 primFlags |= eApplyFrameStyle;
  524. #if DEBUGLEVEL >= DEBUGFEEDBACK
  525.                 dprintf(trace, "Join shape is not PostScriptable, Calling PrimitiveShape");
  526. #endif
  527.                 goto finished_Validate;
  528.                 
  529.             } else if ( ((psVal == eMiterJoin) && (theJoin.miter != 0) && (penWidth != 0)) 
  530.                                         && (theDash.dash == nil) ) {
  531.             
  532.                 if (TestMiterMatters(theShape, &theJoin, penWidth)) {
  533.                 
  534.                     primFlags |= eApplyFrameStyle;
  535. #if DEBUGLEVEL >= DEBUGFEEDBACK
  536.                     dprintf(trace, "Join miter is not PostScriptable, Calling PrimitiveShape");
  537. #endif
  538.                     goto finished_Validate;
  539.                     
  540.                 }//end if
  541.             
  542.             }//end if
  543.             
  544.             
  545.             /** Now see if the caps aren't PostScriptable **/
  546.             status = GetPSLineCap(theStyle, &psVal);
  547.             nrequire(status, failed_GetCapValue);
  548.             if ((psVal == -1) && (theDash.dash == nil) ) {
  549.             
  550.                 primFlags |= eApplyFrameStyle;
  551. #if DEBUGLEVEL >= DEBUGFEEDBACK
  552.                 dprintf(trace, "Caps are not PostScriptable, Calling PrimitiveShape");
  553. #endif
  554.                 goto finished_Validate;
  555.                 
  556.             }//end if
  557.             
  558.             
  559.             
  560.             /************************************
  561.                 If we are to fill a framed shape with a pattern (but not if it is dashed)
  562.                 then we must call PrimitiveShape to apply the thick pen.  We could do this
  563.                 with strokepath in PostScript, but it is likely to generate a limitcheck
  564.                 or some shape that would be really horrible to clip to - as we do for patterns
  565.                 in level-1
  566.                 
  567.                 We also do this for level-2 if the pattern is port-mapped.  Otherwise the pen width
  568.                 will run through the port-mapping only rather than the shapes CTM.
  569.             **************************************/
  570.             
  571.             if (  ( (thePattern.pattern != nil) && (theDash.dash == nil) ) &&
  572.                         ( ((*hIEGlobals)->params.languageLevel == 1) || (thePattern.attributes & gxPortMapPattern))
  573.                  ) {
  574.                         
  575.                 primFlags |= eApplyPen;
  576.                 #if DEBUGLEVEL >= DEBUGFEEDBACK
  577.                 dprintf(trace, " Calling PrimitiveShape for frame due to pattern");
  578.                 #endif
  579.                 goto finished_Validate;
  580.                         
  581.             }//end if
  582.             
  583.             
  584.             /** Deal with non-center frame fill **/
  585.             
  586.             if ( (theAttributes & (gxInsideFrameStyle | gxOutsideFrameStyle) ) != 0 ) {
  587.             
  588.                 /** See if non-center frame can be done by insetting the shape **/
  589.                 
  590.                 if ( TestNonCenterShapeCanBeInset( theShape, theStyle) ) {
  591.  
  592.                     if (theAttributes & gxInsideFrameStyle)
  593.                         theInset = penWidth >> 1;
  594.                     else if (theAttributes & gxOutsideFrameStyle)
  595.                         theInset = -penWidth >> 1;
  596.                 
  597.                     status = DupShapeIfNecessary(theShape, &shapeCopy);
  598.                     nrequire(status, failed_Duplicate);
  599.                     
  600.                     theShape = shapeCopy;
  601.                     
  602.                     if (theInset != 0)
  603.                         GXInsetShape(theShape, theInset);
  604.                         
  605.                     /** Shape can be center framed now **/
  606.                     
  607.                     GXSetShapeStyleAttributes(theShape, theAttributes & ~(gxInsideFrameStyle | gxOutsideFrameStyle));
  608.                 
  609.                 } else {
  610.             
  611.                     /** Non dashed inside/outside framed shapes (except rectangles) require call to primitive shape **/
  612.                     if (theType != gxRectangleType) {
  613.                             
  614.                         primFlags |= eApplyPen;
  615.                         #if DEBUGLEVEL >= DEBUGFEEDBACK
  616.                         dprintf(trace, " Calling PrimitiveShape for frame due inside/outside frame");
  617.                         #endif
  618.                         goto finished_Validate;
  619.         
  620.                     }//end if
  621.                 
  622.                 }//end if
  623.             
  624.             
  625.             }//end if (inside/outside frame)
  626.  
  627.         
  628.         }//end if (framed shape)
  629.     
  630.     
  631. finished_Validate:
  632.  
  633.         if (primFlags != 0) {
  634.         
  635.             status = DupShapeIfNecessary(theShape, &shapeCopy);
  636.             nrequire(status, failed_Duplicate);
  637.             
  638.             theShape = shapeCopy;
  639.             
  640.             status = PSPrimitiveShape(theShape, primFlags);
  641.             ncheck(status);
  642.     
  643.         }//end if
  644.         
  645.         *pShape = theShape;                    // return to caller the new shape
  646.         
  647. failed_Duplicate:
  648. failed_GetCapValue:
  649.  
  650.         if (thePattern.pattern != nil)            
  651.             GXDisposeShape(thePattern.pattern);
  652.         
  653.         if (theDash.dash != nil)
  654.             GXDisposeShape(theDash.dash);
  655.         
  656.         if (theJoin.join != nil)
  657.             GXDisposeShape(theJoin.join);
  658.  
  659.         if (status == noErr)
  660.             status = GXGetGraphicsError(nil);
  661.  
  662. failed_Underlines:
  663. failed_TextToPaths:
  664. failed_Simplify:
  665. failed_PointShape:
  666.  
  667.         return(status);
  668.     
  669.     
  670.     }//ValidateFillShape
  671.