Logo Search packages:      
Sourcecode: inkscape version File versions

wpg-input.cpp

/* 
 *  This file came from libwpg as a source, their utility wpg2svg
 *  specifically.  It has been modified to work as an Inkscape extension.
 *  The Inkscape extension code is covered by this copyright, but the
 *  rest is covered by the one bellow.
 *
 * Authors:
 *   Ted Gould <ted@gould.cx>
 *
 * Copyright (C) 2006 Authors
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 *
 */

/* libwpg
 * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
 * Copyright (C) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 * For further information visit http://libwpg.sourceforge.net
 */

/* "This product is not manufactured, approved, or supported by
 * Corel Corporation or Corel Corporation Limited."
 */

#include <stdio.h>

#include "wpg-input.h"
#include "extension/system.h"
#include "extension/input.h"
#include "document.h"

#include "libwpg/libwpg.h"
#include "libwpg/WPGStreamImplementation.h"

using namespace libwpg;

namespace Inkscape {
namespace Extension {
namespace Internal {

class InkscapePainter : public libwpg::WPGPaintInterface {
public:
      InkscapePainter();

      void startDocument(double imageWidth, double imageHeight);
      void endDocument();
      void startLayer(unsigned int id);
      void endLayer(unsigned int id);

      void setPen(const WPGPen& pen);
      void setBrush(const WPGBrush& brush);
      void setFillRule(FillRule rule);

      void drawRectangle(const WPGRect& rect, double rx, double ry);
      void drawEllipse(const WPGPoint& center, double rx, double ry);
      void drawPolygon(const WPGPointArray& vertices);
      void drawPath(const WPGPath& path);

private:
      WPGPen m_pen;
      WPGBrush m_brush;
      FillRule m_fillRule;
      int m_gradientIndex;
      void writeStyle();
        void printf (char * fmt, ...) {
            va_list args;
            va_start(args, fmt);
            gchar * buf = g_strdup_vprintf(fmt, args);
            va_end(args);
            if (buf) {
                document += buf;
                g_free(buf);
            }
        }

public:
        Glib::ustring document;
};

InkscapePainter::InkscapePainter(): m_fillRule(AlternatingFill), m_gradientIndex(1)
{
}

void InkscapePainter::startDocument(double width, double height) 
{
        document = "";
      printf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
      printf("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"");
      printf(" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");

//    printf("<!-- Created with wpg2svg/libwpg %s -->\n", LIBWPG_VERSION_STRING);

      printf("<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" ");
      printf("xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");    
      printf("width=\"%g\" height=\"%f\" >\n", 72*width, 72*height);
      
      m_gradientIndex = 1;
}

void InkscapePainter::endDocument()
{
      printf("</svg>\n");
}

void InkscapePainter::setPen(const WPGPen& pen)
{
      m_pen = pen;
}

void InkscapePainter::setBrush(const WPGBrush& brush)
{
      m_brush = brush;
      
      if(m_brush.style == WPGBrush::Gradient)
      {
            double angle = m_brush.gradient.angle();

            printf("<defs>\n");
            printf("  <linearGradient id=\"grad%d\" >\n", m_gradientIndex++);
            for(unsigned c = 0; c < m_brush.gradient.count(); c++)
            {
                  // round to nearest percentage
                  int ofs = (int)(100.0*m_brush.gradient.stopOffset(c)+0.5);

                  WPGColor color = m_brush.gradient.stopColor(c);
                  printf("    <stop offset=\"%d%%\" stop-color=\"#%02x%02x%02x\" />\n",
                        ofs, color.red, color.green, color.blue);
            }
            printf("  </linearGradient>\n");
            
            // not a simple horizontal gradient
            if(angle != -90.0)
            {
                  printf("  <linearGradient xlink:href=\"#grad%d\"", m_gradientIndex-1);
                  printf(" id=\"grad%d\" ", m_gradientIndex++);
                  printf("x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\" "); 
                  printf("gradientTransform=\"rotate(%f)\" ", angle);
                  printf("gradientUnits=\"objectBoundingBox\" >\n");
                  printf("  </linearGradient>\n");
            }
            
            printf("</defs>\n");
      }
}

void InkscapePainter::setFillRule(FillRule rule)
{
      m_fillRule = rule;
}

void InkscapePainter::startLayer(unsigned int id)
{
      printf("<g id=\"Layer%d\" >\n", id);
}

void InkscapePainter::endLayer(unsigned int)
{
      printf("</g>\n");
}

void InkscapePainter::drawRectangle(const WPGRect& rect, double rx, double ry)
{
      printf("<rect ");
      printf("x=\"%f\" y=\"%f\" ", 72*rect.x1, 72*rect.y1);
      printf("width=\"%f\" height=\"%f\" ", 72*rect.width(), 72*rect.height());
      if((rx !=0) || (ry !=0))
            printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);
      writeStyle();
      printf("/>\n");
}

void InkscapePainter::drawEllipse(const WPGPoint& center, double rx, double ry)
{
      printf("<ellipse ");
      printf("cx=\"%f\" cy=\"%f\" ", 72*center.x, 72*center.y);
      printf("rx=\"%f\" ry=\"%f\" ", 72*rx, 72*ry);
      writeStyle();
      printf("/>\n");
}

void InkscapePainter::drawPolygon(const WPGPointArray& vertices)
{
      if(vertices.count() < 2)
            return;

      if(vertices.count() == 2)
      {
            const WPGPoint& p1 = vertices[0];
            const WPGPoint& p2 = vertices[1];
            printf("<line ");
            printf("x1=\"%f\"  y1=\"%f\" ", 72*p1.x, 72*p1.y);
            printf("x2=\"%f\"  y2=\"%f\"\n", 72*p2.x, 72*p2.y);
            writeStyle();
            printf("/>\n");
      }
      else
      {
            printf("<polyline ");
            printf("points=\"");
            for(unsigned i = 0; i < vertices.count(); i++)
            {
                  printf("%f %f", 72*vertices[i].x, 72*vertices[i].y);
                  if(i < vertices.count()-1) printf(", ");
            }
            printf("\"\n");
            writeStyle();
            printf("/>\n");
      }
}

void InkscapePainter::drawPath(const WPGPath& path)
{
      printf("<path d=\"");
      for(unsigned i = 0; i < path.count(); i++)
      {
            WPGPathElement element = path.element(i);
            WPGPoint point = element.point;
            switch(element.type)
            {
                  case WPGPathElement::MoveToElement:
                        printf("\n M%f,%f ", 72*point.x, 72*point.y );
                        break;
                        
                  case WPGPathElement::LineToElement:
                        printf("\n L%f,%f ", 72*point.x, 72*point.y );
                        break;
                  
                  case WPGPathElement::CurveToElement:
                        printf("C");
                        printf("%f,%f ", 72*element.extra1.x, 72*element.extra1.y );
                        printf("%f,%f ", 72*element.extra2.x, 72*element.extra2.y );
                        printf("%f,%f", 72*point.x, 72*point.y );
                        break;
                  
                  default:
                        break;
            }
      }
      
      if(path.closed)
            printf("Z");

      printf("\" \n");
      writeStyle();
      printf("/>\n");
}

// create "style" attribute based on current pen and brush
void InkscapePainter::writeStyle()
{
      printf("style=\"");

      const WPGColor& color = m_pen.foreColor;
      printf("stroke-width: %f; ", 72*m_pen.width);
      if(m_pen.width > 0.0)
      {
            printf("stroke: rgb(%d,%d,%d); ", color.red, color.green, color.blue);
            if(color.alpha != 0)
                  // alpha = 0 means opacity = 1.0, alpha = 256 means opacity = 0
                  printf("stroke-opacity: %f; ", 1.0-(color.alpha/256.0));
      }

      if(!m_pen.solid)
      {
            printf("stroke-dasharray: ");
            for(unsigned i = 0; i < m_pen.dashArray.count(); i++)
            {
                  printf("%f", 72*m_pen.dashArray.at(i)*m_pen.width);
                  if(i < m_pen.dashArray.count()-1) 
                        printf(", ");
            }
            printf("; ");
      }
      
      if(m_brush.style == WPGBrush::NoBrush)
            printf("fill: none; ");

      if(m_fillRule == InkscapePainter::WindingFill)
            printf("fill-rule: nonzero; ");
      else if(m_fillRule == InkscapePainter::AlternatingFill)
            printf("fill-rule: evenodd; ");

      if(m_brush.style == WPGBrush::Gradient)
            printf("fill: url(#grad%d); ", m_gradientIndex-1);

      if(m_brush.style == WPGBrush::Solid)
            printf("fill: rgb(%d,%d,%d); ", m_brush.foreColor.red, 
                  m_brush.foreColor.green, m_brush.foreColor.blue);

      printf("\""); // style
}

SPDocument *
WpgInput::open(Inkscape::Extension::Input * mod, const gchar * uri) {
    WPGInputStream* input = new WPGFileStream(uri);
    if (input->isOle()) {
        WPGInputStream* olestream = input->getWPGOleStream();
        if (olestream) {
            delete input;
            input = olestream;
        }
    }

    if (!WPGraphics::isSupported(input)) {
        //! \todo Dialog here
        // fprintf(stderr, "ERROR: Unsupported file format (unsupported version) or file is encrypted!\n");
        // printf("I'm giving up not supported\n");
        return NULL;
    }

    InkscapePainter painter;
    WPGraphics::parse(input, &painter);

    //printf("I've got a doc: \n%s", painter.document.c_str());

    return sp_document_new_from_mem(painter.document.c_str(), strlen(painter.document.c_str()), TRUE);
}

#include "clear-n_.h"

void
WpgInput::init(void) {
    Inkscape::Extension::Extension * ext;

    ext = Inkscape::Extension::build_from_mem(
        "<inkscape-extension>\n"
            "<name>" N_("WPG Input") "</name>\n"
            "<id>org.inkscape.input.wpg</id>\n"
            "<input>\n"
                "<extension>.wpg</extension>\n"
                "<mimetype>image/x-wpg</mimetype>\n"
                "<filetypename>" N_("WordPerfect Graphics (*.wpg)") "</filetypename>\n"
                "<filetypetooltip>" N_("Vector graphics format used by Corel WordPerfect") "</filetypetooltip>\n"
            "</input>\n"
        "</inkscape-extension>", new WpgInput());
} // init

} } }  /* namespace Inkscape, Extension, Implementation */

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :

Generated by  Doxygen 1.6.0   Back to index