/* AbiWord * Copyright (C) 1998 AbiSource, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include "gr_VectorImage.h" #include "ut_bytebuf.h" #include "gr_Graphics.h" #include "ut_svg.h" #include "ut_assert.h" #include "ut_debugmsg.h" static void _startElement(void * userdata, const char * name, const char ** atts); static void _endElement(void * userdata, const char * name); static void _charData(void * userdata, UT_ByteBuf * pBB); static void render_init(GR_VectorImage* pImage); #define TT_SVG 0 #define TT_GROUP 1 #define TT_RECT 2 #define TT_LINE 3 #define TT_CIRCLE 4 #define TT_ELLIPSE 5 #define TT_POLYGON 6 #define TT_POLYLINE 7 #define TT_PATH 8 struct _TokenTable { const char * m_name; int m_type; }; #if 0 static struct _TokenTable s_Tokens[] = { { "svg", TT_SVG }, { "g", TT_GROUP }, { "rect", TT_RECT }, { "line", TT_LINE }, { "circle", TT_CIRCLE }, { "ellipse", TT_ELLIPSE }, { "polygon", TT_POLYGON }, { "polyline", TT_POLYLINE }, { "path", TT_PATH }, }; #endif // basic drawing commands struct drawBase { int type; UT_RGBColor fill, stroke; float fill_opacity, stroke_opacity; UT_uint32 stroke_width; UT_Rect bounds; }; struct drawPoly : public drawBase { UT_Point * points; }; struct drawPathItem { int pathCommand; UT_Point point; }; struct drawPath : public drawBase { drawPathItem * points; }; GR_VectorImage::GR_VectorImage(const char* szName) : m_status(false), m_context(0), m_pSVG(0), m_pBB_Image(0) { if (szName) { setName (szName); } else { setName ( "VectorImage" ); } } GR_VectorImage::~GR_VectorImage() { FREEP(m_pSVG); FREEP(m_pBB_Image); UT_VECTOR_PURGEALL(UT_SVGMatrix*,m_SVG_Matrix); } bool GR_VectorImage::convertToBuffer(UT_ByteBuf** ppBB) const { UT_ByteBuf* pBB = new UT_ByteBuf; bool bCopied = pBB->append(m_pBB_Image->getPointer(0), m_pBB_Image->getLength()); if (!bCopied) FREEP(pBB); *ppBB = pBB; return bCopied; } bool GR_VectorImage::hasAlpha(void) const { UT_ASSERT(0); return false; } bool GR_VectorImage::isTransparentAt(UT_sint32 x, UT_sint32 y) { UT_ASSERT(0); return false; } bool GR_VectorImage::convertFromBuffer(const UT_ByteBuf* pBB, UT_sint32 iDisplayWidth, UT_sint32 iDisplayHeight) { setDisplaySize ( iDisplayWidth, iDisplayHeight ); FREEP(m_pBB_Image); m_pBB_Image = new UT_ByteBuf; bool bCopied = m_pBB_Image->append(pBB->getPointer(0), pBB->getLength()); if (!bCopied) FREEP(m_pBB_Image); return bCopied; } bool GR_VectorImage::render(GR_Graphics* pGR, UT_sint32 xDest, UT_sint32 yDest) { // Set origin m_iDisplayOx = xDest; m_iDisplayOy = yDest; DELETEP(m_pSVG); m_pSVG = new UT_svg(pGR); m_pSVG->cb_userdata = static_cast(this); m_pSVG->cb_start = _startElement; m_pSVG->cb_end = _endElement; m_pSVG->cb_text = _charData; m_iTreeLevel = 0; bool bParsed = m_pSVG->parse(m_pBB_Image); FREEP(m_pSVG); return bParsed; /* UT_RGBColor col(0, 0xff, 0); pGR->fillRect(col, xDest, yDest, iDisplayWidth, iDisplayHeight); UT_setColor(col, 0xff, 0, 0); pGR->setColor(col); pGR->drawLine(xDest + iDisplayWidth/2, yDest, xDest+iDisplayWidth, yDest+iDisplayHeight/2); pGR->drawLine(xDest + iDisplayWidth/2, yDest+iDisplayHeight, xDest+iDisplayWidth, yDest+iDisplayHeight/2); pGR->drawLine(xDest + iDisplayWidth/2, yDest, xDest, yDest+iDisplayHeight/2); pGR->drawLine(xDest + iDisplayWidth/2, yDest+iDisplayHeight, xDest, yDest+iDisplayHeight/2); return true; */ } static void _startElement(void* userdata, const char* name, const char** atts) { GR_VectorImage* pImage = static_cast(userdata); UT_svg* pSVG = pImage->getSVG(); if (pImage->m_iTreeLevel == 0) { render_init (pImage); } else { pImage->m_CurrentMatrix = new UT_SVGMatrix(*(pImage->m_CurrentMatrix)); if (pImage->m_SVG_Matrix.push_back(pImage->m_CurrentMatrix)) { UT_DEBUGMSG(("SVG: Matrix stack/vector: Insufficient memory?\n")); pSVG->m_bSVG = false; pSVG->m_bContinue = false; } } if (pSVG->m_bContinue == false) { return; // error somewhere } pImage->m_iTreeLevel++; // First apply specified transform, if any; not all element should have this though, I think pImage->m_CurrentMatrix->applyTransform(pImage->m_CurrentMatrix, pSVG->getAttribute("transform", atts)); // } static void _endElement(void* userdata, const char* name) { GR_VectorImage* pImage = static_cast(userdata); //UT_svg* pSVG = pImage->getSVG(); if (pImage->m_iTreeLevel > 0) { FREEP(pImage->m_CurrentMatrix); pImage->m_SVG_Matrix.pop_back(); pImage->m_CurrentMatrix = 0; } pImage->m_iTreeLevel--; if (pImage->m_iTreeLevel > 0) pImage->m_CurrentMatrix = pImage->m_SVG_Matrix.getLastItem(); // } static void _charData(void* userdata, UT_ByteBuf* pBB) { //GR_VectorImage* pImage = static_cast(userdata); // ByteBuf holds complete text, probably in UTF-8 FREEP(pBB); } static void render_init(GR_VectorImage* pImage) { UT_svg* pSVG = pImage->getSVG(); // White backgound (I think) //GR_Graphics* pGR = pSVG->m_pG; // UT_RGBColor col(0xff,0xff,0xff); // pGR->fillRect(col, pImage->getDisplayOx(), pImage->getDisplayOy(), pImage->getDisplayWidth(), pImage->getDisplayHeight()); // Set initial transformation matrix float x_origin = static_cast(pImage->getDisplayOx()); float y_origin = static_cast(pImage->getDisplayOy()); float x_scale = static_cast(static_cast(pImage->getDisplayWidth()) / static_cast(pSVG->m_iDisplayWidth)); float y_scale = static_cast(static_cast(pImage->getDisplayHeight()) / static_cast(pSVG->m_iDisplayHeight)); while (pImage->m_SVG_Matrix.getItemCount() > 0) { UT_SVGMatrix* matrix = pImage->m_SVG_Matrix.getLastItem(); if (matrix) { delete matrix; } pImage->m_SVG_Matrix.pop_back(); } UT_SVGMatrix matrix; matrix = matrix.translate (x_origin,y_origin); matrix = matrix.scaleNonUniform (x_scale,y_scale); pImage->m_CurrentMatrix = new UT_SVGMatrix(matrix); if (pImage->m_SVG_Matrix.push_back(pImage->m_CurrentMatrix)) { UT_DEBUGMSG(("SVG: Matrix stack/vector: Insufficient memory?\n")); pSVG->m_bSVG = false; pSVG->m_bContinue = false; return; } // }