Beispiel #1
0
    //==============================================================================
    Drawable* parseSVGElement (const XmlElement& xml)
    {
        if (! xml.hasTagNameIgnoringNamespace ("svg"))
            return nullptr;

        DrawableComposite* const drawable = new DrawableComposite();

        drawable->setName (xml.getStringAttribute ("id"));

        SVGState newState (*this);

        if (xml.hasAttribute ("transform"))
            newState.addTransform (xml);

        newState.elementX = getCoordLength (xml.getStringAttribute ("x",      String (newState.elementX)), viewBoxW);
        newState.elementY = getCoordLength (xml.getStringAttribute ("y",      String (newState.elementY)), viewBoxH);
        newState.width    = getCoordLength (xml.getStringAttribute ("width",  String (newState.width)),    viewBoxW);
        newState.height   = getCoordLength (xml.getStringAttribute ("height", String (newState.height)),   viewBoxH);

        if (newState.width  <= 0) newState.width  = 100;
        if (newState.height <= 0) newState.height = 100;

        if (xml.hasAttribute ("viewBox"))
        {
            const String viewBoxAtt (xml.getStringAttribute ("viewBox"));
            String::CharPointerType viewParams (viewBoxAtt.getCharPointer());
            Point<float> vxy, vwh;

            if (parseCoords (viewParams, vxy, true)
                 && parseCoords (viewParams, vwh, true)
                 && vwh.x > 0
                 && vwh.y > 0)
            {
                newState.viewBoxW = vwh.x;
                newState.viewBoxH = vwh.y;

                int placementFlags = 0;

                const String aspect (xml.getStringAttribute ("preserveAspectRatio"));

                if (aspect.containsIgnoreCase ("none"))
                {
                    placementFlags = RectanglePlacement::stretchToFit;
                }
                else
                {
                    if (aspect.containsIgnoreCase ("slice"))        placementFlags |= RectanglePlacement::fillDestination;

                    if (aspect.containsIgnoreCase ("xMin"))         placementFlags |= RectanglePlacement::xLeft;
                    else if (aspect.containsIgnoreCase ("xMax"))    placementFlags |= RectanglePlacement::xRight;
                    else                                            placementFlags |= RectanglePlacement::xMid;

                    if (aspect.containsIgnoreCase ("yMin"))         placementFlags |= RectanglePlacement::yTop;
                    else if (aspect.containsIgnoreCase ("yMax"))    placementFlags |= RectanglePlacement::yBottom;
                    else                                            placementFlags |= RectanglePlacement::yMid;
                }

                newState.transform = RectanglePlacement (placementFlags)
                                        .getTransformToFit (Rectangle<float> (vxy.x, vxy.y, vwh.x, vwh.y),
                                                            Rectangle<float> (newState.width, newState.height))
                                        .followedBy (newState.transform);
            }
        }
        else
        {
            if (viewBoxW == 0)  newState.viewBoxW = newState.width;
            if (viewBoxH == 0)  newState.viewBoxH = newState.height;
        }

        newState.parseSubElements (xml, *drawable);

        drawable->setContentArea (RelativeRectangle (Rectangle<float> (newState.viewBoxW, newState.viewBoxH)));
        drawable->resetBoundingBoxToContentArea();

        return drawable;
    }
Beispiel #2
0
//==============================================================================
static bool parseFile (const File& rootFolder,
                       const File& newTargetFile,
                       OutputStream& dest,
                       const File& file,
                       StringArray& alreadyIncludedFiles,
                       const StringArray& includesToIgnore,
                       const StringArray& wildcards,
                       bool isOuterFile,
                       bool stripCommentBlocks)
{
    if (! file.exists())
    {
        std::cout << "!! ERROR - file doesn't exist!";
        return false;
    }

    StringArray lines;
    lines.addLines (file.loadFileAsString());

    if (lines.size() == 0)
    {
        std::cout << "!! ERROR - input file was empty: " << file.getFullPathName();
        return false;
    }

    bool lastLineWasBlank = true;

    for (int i = 0; i < lines.size(); ++i)
    {
        String line (lines[i]);
        String trimmed (line.trimStart());

        if ((! isOuterFile) && trimmed.startsWith ("//================================================================"))
            line = String::empty;

        if (trimmed.startsWithChar ('#')
             && trimmed.removeCharacters (" \t").startsWithIgnoreCase ("#include\""))
        {
            const int endOfInclude = line.indexOfChar (line.indexOfChar ('\"') + 1, '\"') + 1;
            const String lineUpToEndOfInclude (line.substring (0, endOfInclude));
            const String lineAfterInclude (line.substring (endOfInclude));

            const String filename (line.fromFirstOccurrenceOf ("\"", false, false)
                                       .upToLastOccurrenceOf ("\"", false, false));
            const File targetFile (file.getSiblingFile (filename));

            if (targetFile.exists() && targetFile.isAChildOf (rootFolder))
            {
                if (matchesWildcard (filename.replaceCharacter ('\\', '/'), wildcards)
                     && ! includesToIgnore.contains (targetFile.getFileName()))
                {
                    if (line.containsIgnoreCase ("FORCE_AMALGAMATOR_INCLUDE")
                        || ! alreadyIncludedFiles.contains (targetFile.getFullPathName()))
                    {
                        if (! canFileBeReincluded (targetFile))
                            alreadyIncludedFiles.add (targetFile.getFullPathName());

                        dest << newLine << "/*** Start of inlined file: " << targetFile.getFileName() << " ***/" << newLine;

                        if (! parseFile (rootFolder, newTargetFile,
                                         dest, targetFile, alreadyIncludedFiles, includesToIgnore,
                                         wildcards, false, stripCommentBlocks))
                        {
                            return false;
                        }

                        dest << "/*** End of inlined file: " << targetFile.getFileName() << " ***/" << newLine << newLine;

                        line = lineAfterInclude;
                    }
                    else
                    {
                        line = String::empty;
                    }
                }
                else
                {
                    line = lineUpToEndOfInclude.upToFirstOccurrenceOf ("\"", true, false)
                            + targetFile.getRelativePathFrom (newTargetFile.getParentDirectory())
                                        .replaceCharacter ('\\', '/')
                            + "\""
                            + lineAfterInclude;
                }
            }
        }

        if ((stripCommentBlocks || i == 0) && trimmed.startsWith ("/*") && (i > 10 || ! isOuterFile))
        {
            int originalI = i;
            String originalLine = line;

            for (;;)
            {
                int end = line.indexOf ("*/");

                if (end >= 0)
                {
                    line = line.substring (end + 2);

                    // If our comment appeared just before an assertion, leave it in, as it
                    // might be useful..
                    if (lines [i + 1].contains ("assert")
                         || lines [i + 2].contains ("assert"))
                    {
                        i = originalI;
                        line = originalLine;
                    }

                    break;
                }

                line = lines [++i];

                if (i >= lines.size())
                    break;
            }

            line = line.trimEnd();
            if (line.isEmpty())
                continue;
        }

        line = line.trimEnd();

        {
            // Turn initial spaces into tabs..
            int numIntialSpaces = 0;
            int len = line.length();
            while (numIntialSpaces < len && line [numIntialSpaces] == ' ')
                ++numIntialSpaces;

            if (numIntialSpaces > 0)
            {
                int tabSize = 4;
                int numTabs = numIntialSpaces / tabSize;
                line = String::repeatedString ("\t", numTabs) + line.substring (numTabs * tabSize);
            }

            if (! line.containsChar ('"'))
            {
                // turn large areas of spaces into tabs - this will mess up alignment a bit, but
                // it's only the amalgamated file, so doesn't matter...
                line = line.replace ("        ", "\t", false);
                line = line.replace ("    ", "\t", false);
            }
        }

        if (line.isNotEmpty() || ! lastLineWasBlank)
            dest << line << newLine;

        lastLineWasBlank = line.isEmpty();
    }

    return true;
}