diff --git a/src/tests/kits/interface/PictureTest.cpp b/src/tests/kits/interface/PictureTest.cpp deleted file mode 100644 index 38f5c4eeea..0000000000 --- a/src/tests/kits/interface/PictureTest.cpp +++ /dev/null @@ -1,136 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -class OriginalView : public BBox { -public: - OriginalView(BRect frame); - virtual void Draw(BRect update); -}; - - -class PictureView : public BBox { -public: - PictureView(BRect frame); - ~PictureView(); - - virtual void Draw(BRect update); - virtual void AllAttached(); - -private: - BPicture *fPicture; -}; - - -static void -DrawStuff(BView *view) -{ - // StrokeShape - BShape shape; - BPoint bezier[3] = {BPoint(100,0), BPoint(100, 100), BPoint(25, 50)}; - shape.MoveTo(BPoint(150,0)); - shape.LineTo(BPoint(200,100)); - shape.BezierTo(bezier); - shape.Close(); - view->StrokeShape(&shape); - - // Stroke/FillRect, Push/PopState, SetHighColor, SetLineMode, SetPenSize - view->PushState(); - const rgb_color blue = { 0, 0, 240, 0 }; - view->SetHighColor(blue); - view->SetLineMode(B_BUTT_CAP, B_BEVEL_JOIN); - view->SetPenSize(7); - view->StrokeRect(BRect(10, 220, 50, 260)); - view->FillRect(BRect(65, 245, 120, 300)); - view->PopState(); - - // Stroke/FillEllipse - view->StrokeEllipse(BPoint(50, 150), 50, 50); - view->FillEllipse(BPoint(100, 120), 50, 50); - - // Stroke/FillArc - view->StrokeArc(BRect(0, 200, 50, 250), 180, 180); - view->FillArc(BPoint(150, 250), 50, 50, 0, 125); - - // DrawString, SetHighColor, SetFontSize - const rgb_color red = { 240, 0, 0, 0 }; - view->SetHighColor(red); - view->SetFontSize(20); - view->DrawString("BPicture test", BPoint(30, 20)); -} - - -// OriginalView -OriginalView::OriginalView(BRect frame) - : BBox(frame, "original_view", B_FOLLOW_ALL_SIDES, B_WILL_DRAW) -{ -} - - -void -OriginalView::Draw(BRect updateRect) -{ - DrawStuff(this); -} - - -// PictureView -PictureView::PictureView(BRect frame) - : BBox(frame, "pict_view", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), - fPicture(NULL) -{ -} - -PictureView::~PictureView() -{ - delete fPicture; -} - -void -PictureView::AllAttached() -{ - BeginPicture(new BPicture); - - DrawStuff(this); - - fPicture = EndPicture(); -} - -void -PictureView::Draw(BRect update) -{ - if (fPicture) - DrawPicture(fPicture, B_ORIGIN); -} - - -// main -int -main() -{ - BApplication pictureApp("application/x-vnd.picture"); - BWindow *pictureWindow = new BWindow(BRect(100, 100, 500, 400), - "BPicture test", B_TITLED_WINDOW, - B_NOT_RESIZABLE|B_NOT_ZOOMABLE|B_QUIT_ON_WINDOW_CLOSE); - - BRect rect(pictureWindow->Bounds()); - rect.right -= (rect.Width() + 1) / 2; - OriginalView *testView = new OriginalView(rect); - - rect.OffsetBy(rect.Width() + 1, 0); - PictureView *pictureView = new PictureView(rect); - - pictureWindow->AddChild(testView); - pictureWindow->AddChild(pictureView); - - pictureWindow->Show(); - - pictureApp.Run(); - - return 0; -} - diff --git a/src/tests/kits/interface/picture/Jamfile b/src/tests/kits/interface/picture/Jamfile index d428d1232d..0916fa0778 100644 --- a/src/tests/kits/interface/picture/Jamfile +++ b/src/tests/kits/interface/picture/Jamfile @@ -1,6 +1,25 @@ SubDir HAIKU_TOP src tests kits interface picture ; +# libicon.a source directories +local iconSourceDirs = + icon + icon/flat_icon + icon/shape + icon/style + icon/transformable + icon/transformer +; + +local iconSourceDir ; +for iconSourceDir in $(iconSourceDirs) { + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src libs $(iconSourceDir) ] ; +} + +# system headers +UseLibraryHeaders agg expat ; + SimpleTest PictureTest : PictureTest.cpp - : be + SVGViewView.cpp + : be translation libexpat.a ; diff --git a/src/tests/kits/interface/picture/PictureTest.cpp b/src/tests/kits/interface/picture/PictureTest.cpp index 38f5c4eeea..d4122793d0 100644 --- a/src/tests/kits/interface/picture/PictureTest.cpp +++ b/src/tests/kits/interface/picture/PictureTest.cpp @@ -5,6 +5,17 @@ #include #include +#include "SVGViewView.h" + +class Svg2PictureWindow : public BWindow { +public: + Svg2PictureWindow(BRect frame, const char *filename) + : BWindow(frame, "Svg2Picture", B_TITLED_WINDOW, 0) { + + BView *view = new Svg2PictureView(Bounds(), filename); + AddChild(view); + } +}; class OriginalView : public BBox { public: @@ -117,6 +128,9 @@ main() "BPicture test", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE|B_QUIT_ON_WINDOW_CLOSE); + BWindow *svgWindow = new Svg2PictureWindow(BRect(300, 300, 600, 600), "/boot/beos/etc/artwork/lion.svg"); + + BRect rect(pictureWindow->Bounds()); rect.right -= (rect.Width() + 1) / 2; OriginalView *testView = new OriginalView(rect); @@ -128,7 +142,8 @@ main() pictureWindow->AddChild(pictureView); pictureWindow->Show(); - + svgWindow->Show(); + pictureApp.Run(); return 0; diff --git a/src/tests/kits/interface/picture/SVGViewView.cpp b/src/tests/kits/interface/picture/SVGViewView.cpp index 128fb10455..f925f6e7f7 100755 --- a/src/tests/kits/interface/picture/SVGViewView.cpp +++ b/src/tests/kits/interface/picture/SVGViewView.cpp @@ -1,26 +1,23 @@ -// Standard Includes ----------------------------------------------------------- - -// System Includes ------------------------------------------------------------- -#include +#include +#include #include +#include #include #include -#include + +#include "Matrix.h" +#include "SVGViewView.h" -// Project Includes ------------------------------------------------------------ -#include "SVGViewView.h" - -// Local Includes -------------------------------------------------------------- - -// Local Defines --------------------------------------------------------------- - -// Globals --------------------------------------------------------------------- +struct named_color { + const char *name; + rgb_color color; +}; named_color colors[] = { { "aliceblue", { 240, 248, 255, 255 } }, { "antiquewhite", { 250, 235, 215, 255 } }, { "aqua", { 0, 255, 255, 255 } }, - { "aquamarine", { 127, 255, 212, 255 } }, + { "aquamarine", { 127, 255, 212, 255 } }, { "azure", { 240, 255, 255, 255 } }, { "beige", { 245, 245, 220, 255 } }, { "bisque", { 255, 228, 196, 255 } }, @@ -167,81 +164,97 @@ named_color colors[] = { { NULL , { 0, 0, 0, 255 } }, }; -//------------------------------------------------------------------------------ -SVGViewView::SVGViewView(BRect frame, const char *name, const char *file) - : BView(frame, "SVGView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), - fPicture(NULL) -{ - fDoc.LoadFile(file); -} -//------------------------------------------------------------------------------ -SVGViewView::~SVGViewView() -{ - delete fPicture; -} -//------------------------------------------------------------------------------ -void SVGViewView::Draw(BRect updateRect) -{ - if (!fPicture) +enum { + STROKE_FLAG = 0x01, + FILL_FLAG = 0x02, + STROKE_WIDTH_FLAG = 0x04, + LINE_MODE_FLAG = 0x08, + FONT_SIZE_FLAG = 0x10, + MATRIX_FLAG = 0x20, + +}; + +struct _state_ { + + _state_() { set_default_values(); } + _state_(_state_ &state) { *this = state; } + void set_default_values() { - SetLineMode(B_BUTT_CAP, B_BUTT_JOIN); - SetDrawingMode(B_OP_ALPHA); - BeginPicture(new BPicture); - DrawNode(&fDoc); - fPicture = EndPicture(); - - BFile file("D:\\web\\picture2.pict", B_WRITE_ONLY | B_CREATE_FILE | - B_ERASE_FILE); - fPicture->Flatten(&file); - - /*BFile file("D:\\web\\picture.pict", B_READ_ONLY); - - fPicture = new BPicture; - fPicture->Unflatten(&file);*/ + fFlags = 0; + fStrokeColor.red = 0; fStrokeColor.green = 0; + fStrokeColor.blue = 0; fStrokeColor.alpha = 255; + fStroke = false; + fFillColor.red = 0; fFillColor.green = 0; + fFillColor.blue = 0; fFillColor.alpha = 255; + fFill = true; + fStrokeWidth = 1.0f; + fLineCap = B_BUTT_CAP; + fLineJoin = B_MITER_JOIN; + fLineMiterLimit = B_DEFAULT_MITER_LIMIT; + fFontSize = 9.0f; } - DrawPicture(fPicture); -} -//------------------------------------------------------------------------------ -float GetFloat(TiXmlElement *element, const char *name) -{ - const char *attr = element->Attribute(name); + uint32 fFlags; + rgb_color fStrokeColor; + bool fStroke; + rgb_color fFillColor; + bool fFill; + float fStrokeWidth; + cap_mode fLineCap; + join_mode fLineJoin; + float fLineMiterLimit; + float fFontSize; + BMatrix fMatrix; +}; - if (attr) - return atof(attr); +_state_ fState; +BList fStack; +//BList fGradients; + +bool HasAttribute(const XML_Char **attributes, const char *name) { + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; + + return (*attributes); +} + +float GetFloatAttribute(const XML_Char **attributes, const char *name) { + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; + + if (*attributes) + return atof(*(attributes + 1)); else return 0; } -const char *GetText(TiXmlElement *element) -{ - TiXmlNode *child = 0; +const char *GetStringAttribute(const XML_Char **attributes, const char *name) { + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; - while (child = element->IterateChildren(child )) - if (child->Type() == TiXmlNode::TEXT) - return child->Value(); - - return NULL; + if (*attributes) + return *(attributes + 1); + else + return NULL; } -rgb_color SVGViewView::GetColor(const char *name, uint8 alpha) -{ - if (!name) +rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha) { + const char *attr = GetStringAttribute(attributes, name); + + if (!attr) return colors[0].color; int32 red, green, blue; - if (name[0] == '#') - { - if (strlen(name) == 4) - { - sscanf(name, "#%1X%1X%1X", &red, &green, &blue); + if (attr[0] == '#') { + if (strlen(attr) == 4) { + sscanf(attr, "#%1X%1X%1X", &red, &green, &blue); red = (red << 4) + red; green = (green << 4) + green; blue = (blue << 4) + blue; } else - sscanf(name, "#%2X%2X%2X", &red, &green, &blue); + sscanf(attr, "#%2X%2X%2X", &red, &green, &blue); rgb_color color; @@ -253,8 +266,7 @@ rgb_color SVGViewView::GetColor(const char *name, uint8 alpha) return color; } - if (sscanf(name, "rgb(%d, %d, %d)", &red, &green, &blue) == 3) - { + if (sscanf(attr, "rgb(%d, %d, %d)", &red, &green, &blue) == 3) { rgb_color color; color.red = red; @@ -267,8 +279,7 @@ rgb_color SVGViewView::GetColor(const char *name, uint8 alpha) float redf, greenf, bluef; - if (sscanf(name, "rgb(%f%%, %f%%, %f%%)", &redf, &greenf, &bluef) == 3) - { + if (sscanf(attr, "rgb(%f%%, %f%%, %f%%)", &redf, &greenf, &bluef) == 3) { rgb_color color; color.red = (int32)(redf * 2.55f); @@ -279,29 +290,24 @@ rgb_color SVGViewView::GetColor(const char *name, uint8 alpha) return color; } - if (strcmpi(name, "url")) - { - char *grad = strchr(name, '#'); + /*if (strcasecmp(attr, "url")) { + const char *grad = strchr(attr, '#'); - if (grad) - { - for (int32 i = 0; i < fGradients.CountItems(); i++) - { + if (grad) { + for (int32 i = 0; i < fGradients.CountItems(); i++) { named_color *item = (named_color*)fGradients.ItemAt(i); - - if (strstr(grad, item->name)) - { + + if (strstr(grad, item->name)) { rgb_color color = item->color; color.alpha = alpha; return color; } } } - } + }*/ for (int32 i = 0; colors[i].name != NULL; i++) - if (strcmpi(colors[i].name, name) == 0) - { + if (strcasecmp(colors[i].name, attr) == 0) { rgb_color color = colors[i].color; color.alpha = alpha; return color; @@ -312,9 +318,14 @@ rgb_color SVGViewView::GetColor(const char *name, uint8 alpha) return color; } -void GetPolygon(TiXmlElement *element, const char *name, BShape *shape) -{ - const char *attr = element->Attribute(name); +void GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape) { + const char *attr = NULL; + + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; + + if (*attributes) + attr = *(attributes + 1); if (!attr) return; @@ -323,8 +334,7 @@ void GetPolygon(TiXmlElement *element, const char *name, BShape *shape) BPoint point; bool first = true; - while (*ptr) - { + while (*ptr) { // Skip white space and ',' while (*ptr && (*ptr == ' ') || (*ptr == ',')) ptr++; @@ -342,11 +352,11 @@ void GetPolygon(TiXmlElement *element, const char *name, BShape *shape) if (first) { - shape->MoveTo(point); + shape.MoveTo(point); first = false; } else - shape->LineTo(point); + shape.LineTo(point); // Skip y while (*ptr && (*ptr != ' ') && (*ptr != ',')) @@ -354,19 +364,88 @@ void GetPolygon(TiXmlElement *element, const char *name, BShape *shape) } } -double CalcVectorAngle(double ux, double uy, double vx, double vy) -{ +void GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix) { + const char *attr = NULL; + + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; + + if (*attributes) + attr = *(attributes + 1); + + if (!attr) + return; + + char *ptr = (char*)attr; + + while (*ptr) { + while (*ptr == ' ') + ptr++; + + char *transform_name = ptr; + + while (*ptr != '(') + ptr++; + + if (strncmp(transform_name, "translate", 9) == 0) { + float x, y; + + if (sscanf(ptr, "(%f %f)", &x, &y) != 2) + sscanf(ptr, "(%f,%f)", &x, &y); + + matrix->Translate(x, y); + } + else if (strncmp(transform_name, "rotate", 6) == 0) { + float angle; + + sscanf(ptr, "(%f)", &angle); + + matrix->Rotate(angle); + } + else if (strncmp(transform_name, "scale", 5) == 0) { + float sx, sy; + + if (sscanf(ptr, "(%f,%f)", &sx, &sy) == 2) + matrix->Scale(sx, sy); + else + { + sscanf(ptr, "(%f)", &sx); + matrix->Scale(sx, sx); + } + } + else if (strncmp(transform_name, "skewX", 5) == 0) { + float angle; + + sscanf(ptr, "(%f)", &angle); + + matrix->SkewX(angle); + } + else if (strncmp(transform_name, "skewY", 5) == 0) { + float angle; + + sscanf(ptr, "(%f)", &angle); + + matrix->SkewY(angle); + } + + while (*ptr != ')') + ptr++; + + ptr++; + } +} + +double CalcVectorAngle(double ux, double uy, double vx, double vy) { double ta = atan2(uy, ux); double tb = atan2(vy, vx); - + if (tb >= ta) return tb - ta; return 6.28318530718 - (ta - tb); } -char *SkipFloat(char *string) -{ +char *SkipFloat(char *string) { if (*string == '-') string++; @@ -375,22 +454,25 @@ char *SkipFloat(char *string) return string + len; } -char *FindFloat(char *string) -{ +char *FindFloat(char *string) { return strpbrk(string, "1234567890-."); } -float GetFloat(char **string) -{ +float GetFloat(char **string) { *string = FindFloat(*string); float f = atof(*string); *string = SkipFloat(*string); return f; } -void GetShape(TiXmlElement *element, const char *name, BShape *shape) -{ - const char *attr = element->Attribute(name); +void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &shape) { + const char *attr = NULL; + + while (*attributes && strcasecmp(*attributes, name) != 0) + attributes += 2; + + if (*attributes) + attr = *(attributes + 1); if (!attr) return; @@ -403,8 +485,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) BPoint pos, startPos; bool canMove = true; - while (*ptr) - { + while (*ptr) { ptr = strpbrk(ptr, "ZzMmLlCcQqAaHhVvSsTt"); if (ptr == NULL) @@ -412,14 +493,13 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) command = *ptr; - switch (command) - { + switch (command) { case 'Z': case 'z': { pos.Set(startPos.x, startPos.y); canMove = true; - shape->Close(); + shape.Close(); ptr++; break; } @@ -431,7 +511,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.Set(x, y); if (canMove) startPos = pos; - shape->MoveTo(pos); + shape.MoveTo(pos); break; } case 'm': @@ -443,17 +523,17 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.y += y; if (canMove) startPos = pos; - shape->MoveTo(pos); + shape.MoveTo(pos); break; } case 'L': { x = GetFloat(&ptr); y = GetFloat(&ptr); - + pos.Set(x, y); canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'l': @@ -464,14 +544,13 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.x += x; pos.y += y; canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'C': case 'c': { - if (command == 'C') - { + if (command == 'C') { x1 = GetFloat(&ptr); y1 = GetFloat(&ptr); x2 = GetFloat(&ptr); @@ -479,8 +558,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) x = GetFloat(&ptr); y = GetFloat(&ptr); } - else - { + else { x1 = GetFloat(&ptr); y1 = GetFloat(&ptr); x2 = GetFloat(&ptr); @@ -495,7 +573,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) x += pos.x; y += pos.y; } - + BPoint controlPoints[3]; controlPoints[0].Set(x1, y1); @@ -505,19 +583,17 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.Set(x, y); prevCtlPt = controlPoints[1]; canMove = false; - shape->BezierTo(controlPoints); + shape.BezierTo(controlPoints); break; } case 'Q': case 'q': { - if (command == 'Q') - { + if (command == 'Q') { if (sscanf(ptr, "Q %f %f %f %f", &x1, &y1, &x, &y) != 4) sscanf(ptr, "Q %f,%f %f,%f", &x1, &y1, &x, &y); } - else - { + else { if (sscanf(ptr, "q %f %f %f %f", &x1, &y1, &x, &y) != 4) sscanf(ptr, "q %f,%f %f,%f", &x1, &y1, &x, &y); @@ -526,7 +602,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) x += pos.x; y += pos.y; } - + BPoint controlPoints[3]; controlPoints[0].Set(pos.x + 2.0f / 3.0f * (x1 - pos.x), @@ -538,7 +614,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.Set(x, y); prevCtlPt.Set(x1, y1); canMove = false; - shape->BezierTo(controlPoints); + shape.BezierTo(controlPoints); break; } case 'A': @@ -547,8 +623,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) x1 = pos.x; y1 = pos.y; - if (command == 'A') - { + if (command == 'A') { if (sscanf(ptr, "A %f %f %f %d %d %f %f", &rx, &ry, &angle, &largeArcFlag, &sweepFlag, &x, &y) != 7) sscanf(ptr, "A %f,%f %f %d,%d %f,%f", &rx, &ry, &angle, @@ -557,8 +632,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) x2 = x; y2 = y; } - else - { + else { if (sscanf(ptr, "a %f %f %f %d %d %f %f", &rx, &ry, &angle, &largeArcFlag, &sweepFlag, &x, &y) != 7) sscanf(ptr, "a %f,%f %f %d,%d %f,%f", &rx, &ry, &angle, @@ -573,10 +647,9 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) if (x1 == x2 && y1 == y2) break; - - if (rx == 0.0f || ry == 0.0f) - { - shape->LineTo(BPoint((float)x2, (float)y2)); + + if (rx == 0.0f || ry == 0.0f) { + shape.LineTo(BPoint((float)x2, (float)y2)); break; } @@ -597,16 +670,14 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) double root, numerator = rx * rx * ry * ry - rx * rx * y1dash * y1dash - ry * ry * x1dash * x1dash; - if (numerator < 0.0) - { + if (numerator < 0.0) { double s = (float)sqrt(1.0 - numerator / (rx * rx * ry * ry)); rx *= s; ry *= s; root = 0.0; } - else - { + else { root = (largeArcFlag == sweepFlag ? -1.0 : 1.0) * sqrt(numerator / (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash)); @@ -635,8 +706,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) BPoint controlPoints[3]; - for (int n = 0; n < segments; ++n) - { + for (int n = 0; n < segments; ++n) { double cosTheta1 = cos(theta1); double sinTheta1 = sin(theta1); double theta2 = theta1 + delta; @@ -656,13 +726,13 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) controlPoints[1].Set((float)(xe + dxe), (float)(ye + dye)); controlPoints[2].Set((float)xe, (float)ye ); - shape->BezierTo(controlPoints); + shape.BezierTo(controlPoints); theta1 = theta2; x1 = (float)xe; y1 = (float)ye; } - + pos.Set(x2, y2); break; } @@ -672,53 +742,51 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.x = x; canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'h': { x = GetFloat(&ptr); - + pos.x += x; canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'V': { y = GetFloat(&ptr); - + pos.y = y; canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'v': { y = GetFloat(&ptr); - + pos.y += y; canMove = false; - shape->LineTo(pos); + shape.LineTo(pos); break; } case 'S': case 's': { - if (command == 'S') - { + if (command == 'S') { x2 = GetFloat(&ptr); y2 = GetFloat(&ptr); x = GetFloat(&ptr); y = GetFloat(&ptr); } - else - { + else { x2 = GetFloat(&ptr); y2 = GetFloat(&ptr); x = GetFloat(&ptr); y = GetFloat(&ptr); - + x2 += pos.x; y2 += pos.y; x += pos.x; @@ -726,13 +794,11 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) } if (prevCommand == 'C' || prevCommand == 'c' || - prevCommand == 'S' || prevCommand == 's') - { + prevCommand == 'S' || prevCommand == 's') { x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); } - else - { + else { x1 = pos.x; y1 = pos.y; } @@ -746,34 +812,30 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.Set(x, y); prevCtlPt.Set(x2, y2); canMove = false; - shape->BezierTo(controlPoints); + shape.BezierTo(controlPoints); break; } case 'T': case 't': { - if (command == 'T') - { + if (command == 'T') { if (sscanf(ptr, "T %f %f", &x, &y) != 2) sscanf(ptr, "T %f,%f", &x, &y); } - else - { + else { if (sscanf(ptr, "t %f %f", &x, &y) != 2) sscanf(ptr, "t %f,%f", &x, &y); x += pos.x; y += pos.y; } - + if (prevCommand == 'Q' || prevCommand == 'q' || - prevCommand == 'T' || prevCommand == 't') - { + prevCommand == 'T' || prevCommand == 't') { x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); } - else - { + else { x1 = pos.x; y1 = pos.y; } @@ -789,7 +851,7 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) pos.Set(x, y); prevCtlPt.Set(x1, y1); canMove = false; - shape->BezierTo(controlPoints); + shape.BezierTo(controlPoints); break; } } @@ -798,511 +860,111 @@ void GetShape(TiXmlElement *element, const char *name, BShape *shape) } } -void GetMatrix(const char *name, BMatrix *matrix) -{ - if (!name) - return; - - char *ptr = (char*)name; - - while (*ptr) - { - while (*ptr == ' ') - ptr++; - - char *transform_name = ptr; - - while (*ptr != '(') - ptr++; - - if (strncmp(transform_name, "translate", 9) == 0) - { - float x, y; - - if (sscanf(ptr, "(%f %f)", &x, &y) != 2) - sscanf(ptr, "(%f,%f)", &x, &y); - - matrix->Translate(x, y); - } - else if (strncmp(transform_name, "rotate", 6) == 0) - { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->Rotate(angle); - } - else if (strncmp(transform_name, "scale", 5) == 0) - { - float sx, sy; - - if (sscanf(ptr, "(%f,%f)", &sx, &sy) == 2) - matrix->Scale(sx, sy); - else - { - sscanf(ptr, "(%f)", &sx); - matrix->Scale(sx, sx); - } - } - else if (strncmp(transform_name, "skewX", 5) == 0) - { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->SkewX(angle); - } - else if (strncmp(transform_name, "skewY", 5) == 0) - { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->SkewY(angle); - } - - while (*ptr != ')') - ptr++; - - ptr++; - } -} - -named_color *SVGViewView::GetGradient(TiXmlElement *element) -{ - TiXmlElement *stop = element->FirstChildElement("stop"); - - if (!stop) - return NULL; - - const char *attr = stop->Attribute("stop-color"); - - if (!attr) - { - attr = stop->Attribute("style"); - - if (!attr) - return NULL; - - attr = strstr(attr, "stop-color"); - - if (!attr) - return NULL; - - attr = strchr(attr, ':'); - - if (!attr) - return NULL; - - attr++; - } - - named_color *gradient = new named_color; - - gradient->name = strdup(element->Attribute("id")); - gradient->color = GetColor(attr, 255); - - stop = stop->NextSiblingElement("stop"); - - while (stop) - { - attr = stop->Attribute("stop-color"); - - if (!attr) - { - attr = stop->Attribute("style"); - - if (!attr) - continue; - - attr = strstr(attr, "stop-color"); - - if (!attr) - continue; - - attr = strchr(attr, ':'); - - if (!attr) - continue; - - attr++; - } - - rgb_color color = GetColor(attr, 255); - - gradient->color.red = (int8)(((int32)gradient->color.red + - (int32)color.red) / 2); - gradient->color.green = (int8)(((int32)gradient->color.green + - (int32)color.green) / 2); - gradient->color.blue = (int8)(((int32)gradient->color.blue + - (int32)color.blue) / 2); - - stop = stop->NextSiblingElement("stop"); - } - - return gradient; -} - -void SVGViewView::CheckAttributes(TiXmlElement *element) -{ - const char *attr; - +void CheckAttributes(const XML_Char **attributes, BView *view) { uint8 alpha = fState.fStrokeColor.alpha; - attr = element->Attribute("opacity"); - - if (attr) - { - fState.fStrokeColor.alpha = (uint8)(atof(attr) * alpha); + if (HasAttribute(attributes, "opacity")) { + float opacity = GetFloatAttribute(attributes, "opacity"); + fState.fStrokeColor.alpha = (uint8)(opacity * alpha); fState.fFlags |= STROKE_FLAG; - fState.fFillColor.alpha = (uint8)(atof(attr) * alpha); + fState.fFillColor.alpha = (uint8)(opacity * alpha); fState.fFlags |= FILL_FLAG; } - - attr = element->Attribute("stroke"); - if (attr) - { - if (strcmpi(attr, "none") == 0) + if (HasAttribute(attributes, "stroke")) { + const char *stroke = GetStringAttribute(attributes, "stroke"); + if (strcasecmp(stroke, "none") == 0) fState.fStroke = false; - else - { - fState.fStrokeColor = GetColor(attr, fState.fFillColor.alpha); + else { + fState.fStrokeColor = GetColorAttribute(attributes, "stroke", fState.fFillColor.alpha); fState.fStroke = true; - SetHighColor(fState.fStrokeColor); + view->SetHighColor(fState.fStrokeColor); } fState.fFlags |= STROKE_FLAG; } - attr = element->Attribute("stroke-opacity"); - - if (attr) - { - fState.fStrokeColor.alpha = (uint8)(atof(attr) * alpha); + if (HasAttribute(attributes, "stroke-opacity")) { + fState.fStrokeColor.alpha = (uint8)(GetFloatAttribute(attributes, "stroke-opacity") * alpha); fState.fFlags |= STROKE_FLAG; } - attr = element->Attribute("fill"); - - if (attr) - { - if (strcmpi(attr, "none") == 0) + if (HasAttribute(attributes, "fill")) { + const char *fill = GetStringAttribute(attributes, "fill"); + if (strcasecmp(fill, "none") == 0) fState.fFill = false; - else - { - fState.fFillColor = GetColor(attr, fState.fFillColor.alpha); + else { + fState.fFillColor = GetColorAttribute(attributes, "fill", fState.fFillColor.alpha); fState.fFill = true; } fState.fFlags |= FILL_FLAG; } - attr = element->Attribute("fill-opacity"); - - if (attr) - { - fState.fFillColor.alpha = (uint8)(atof(attr) * alpha); + if (HasAttribute(attributes, "fill-opacity")) { + fState.fFillColor.alpha = (uint8)(GetFloatAttribute(attributes, "fill-opacity") * alpha); fState.fFlags |= FILL_FLAG; } - attr = element->Attribute("stroke-width"); - - if (attr) - { - fState.fStrokeWidth = atof(attr); - SetPenSize(fState.fStrokeWidth); + if (HasAttribute(attributes, "stroke-width")) { + fState.fStrokeWidth = GetFloatAttribute(attributes, "stroke-width"); + view->SetPenSize(fState.fStrokeWidth); fState.fFlags |= STROKE_WIDTH_FLAG; } - attr = element->Attribute("stroke-linecap"); + if (HasAttribute(attributes, "stroke-linecap")) { + const char *stroke_linecap = GetStringAttribute(attributes, "stroke-linecap"); - if (attr) - { - if (strcmpi(attr, "but") == 0) + if (strcasecmp(stroke_linecap, "but") == 0) fState.fLineCap = B_BUTT_CAP; - else if (strcmpi(attr, "round") == 0) + else if (strcasecmp(stroke_linecap, "round") == 0) fState.fLineCap = B_ROUND_CAP; - else if (strcmpi(attr, "square") == 0) + else if (strcasecmp(stroke_linecap, "square") == 0) fState.fLineCap = B_SQUARE_CAP; - SetLineMode(fState.fLineCap, LineJoinMode(), LineMiterLimit()); - + view->SetLineMode(fState.fLineCap, view->LineJoinMode(), view->LineMiterLimit()); fState.fFlags |= LINE_MODE_FLAG; } - attr = element->Attribute("stroke-linejoin"); + if (HasAttribute(attributes, "stroke-linejoin")) { + const char *stroke_linejoin = GetStringAttribute(attributes, "stroke-linejoin"); - if (attr) - { - if (strcmpi(attr, "miter") == 0) + if (strcasecmp(stroke_linejoin, "miter") == 0) fState.fLineJoin = B_MITER_JOIN; - else if (strcmpi(attr, "round") == 0) + else if (strcasecmp(stroke_linejoin, "round") == 0) fState.fLineJoin = B_ROUND_JOIN; - else if (strcmpi(attr, "bevel") == 0) + else if (strcasecmp(stroke_linejoin, "bevel") == 0) fState.fLineJoin = B_BEVEL_JOIN; - SetLineMode(LineCapMode(), fState.fLineJoin, LineMiterLimit()); - + view->SetLineMode(view->LineCapMode(), fState.fLineJoin, view->LineMiterLimit()); fState.fFlags |= LINE_MODE_FLAG; } - attr = element->Attribute("stroke-miterlimit"); - - if (attr) - { - fState.fLineMiterLimit = atof(attr); - - SetLineMode(LineCapMode(), LineJoinMode(), fState.fLineMiterLimit); - + if (HasAttribute(attributes, "stroke-miterlimit")) { + fState.fLineMiterLimit = GetFloatAttribute(attributes, "stroke-miterlimit"); + view->SetLineMode(view->LineCapMode(), view->LineJoinMode(), fState.fLineMiterLimit); fState.fFlags |= LINE_MODE_FLAG; } - attr = element->Attribute("font-size"); - - if (attr) - { - fState.fFontSize = atof(attr); - SetFontSize(fState.fFontSize); + if (HasAttribute(attributes, "font-size")) { + fState.fFontSize = GetFloatAttribute(attributes, "font-size"); + view->SetFontSize(fState.fFontSize); fState.fFlags |= FONT_SIZE_FLAG; } - attr = element->Attribute("transform"); - - if (attr) - { + if (HasAttribute(attributes, "transform")) { BMatrix matrix; - GetMatrix(attr, &matrix); + GetMatrixAttribute(attributes, "transform", &matrix); fState.fMatrix *= matrix; fState.fFlags |= MATRIX_FLAG; } } -void SVGViewView::DrawNode(TiXmlNode *node) -{ - if (node->Type() == TiXmlNode::ELEMENT) - { - TiXmlElement *element = node->ToElement(); - - Push(); - CheckAttributes(element); - - if (strcmpi(node->Value(), "circle") == 0) - { - BPoint c(GetFloat(element, "cx"), GetFloat(element, "cy")); - float r = GetFloat(element, "r"); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillEllipse(c, r, r); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeEllipse(c, r, r); - } - else if (strcmpi(node->Value(), "ellipse") == 0) - { - BPoint c(GetFloat(element, "cx"), GetFloat(element, "cy")); - float rx = GetFloat(element, "rx"); - float ry = GetFloat(element, "ry"); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillEllipse(c, rx, ry); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeEllipse(c, rx, ry); - } - else if (strcmpi(node->Value(), "image") == 0) - { - BPoint topLeft(GetFloat(element, "x"), GetFloat(element, "y")); - BPoint bottomRight(topLeft.x + GetFloat(element, "width"), - topLeft.y + GetFloat(element, "height")); - - fState.fMatrix.Transform(&topLeft); - fState.fMatrix.Transform(&bottomRight); - - const char *href = element->Attribute("xlink:href"); - - if (href) - { - BBitmap * bitmap = BTranslationUtils::GetBitmap(href); - - if (bitmap) - { - DrawBitmap(bitmap, BRect(topLeft, bottomRight)); - delete bitmap; - } - } - } - else if (strcmpi(node->Value(), "line") == 0) - { - BPoint from(GetFloat(element, "x1"), GetFloat(element, "y1")); - BPoint to(GetFloat(element, "x2"), GetFloat(element, "y2")); - - fState.fMatrix.Transform(&from); - fState.fMatrix.Transform(&to); - - StrokeLine(from, to); - } - else if (strcmpi(node->Value(), "linearGradient") == 0) - { - named_color *gradient = GetGradient(element); - - if (gradient) - fGradients.AddItem(gradient); - } - else if (strcmpi(node->Value(), "path") == 0) - { - BShape shape; - GetShape(element, "d", &shape); - fState.fMatrix.Transform(&shape); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillShape(&shape); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeShape(&shape); - } - else if (strcmpi(node->Value(), "polygon") == 0) - { - BShape shape; - GetPolygon(element, "points", &shape); - shape.Close(); - fState.fMatrix.Transform(&shape); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillShape(&shape); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeShape(&shape); - } - else if (strcmpi(node->Value(), "polyline") == 0) - { - BShape shape; - GetPolygon(element, "points", &shape); - fState.fMatrix.Transform(&shape); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillShape(&shape); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeShape(&shape); - } - else if (strcmpi(node->Value(), "rect") == 0) - { - BPoint points[4]; - - points[0].x = points[3].x = GetFloat(element, "x"); - points[0].y= points[1].y = GetFloat(element, "y"); - points[1].x = points[2].x = points[0].x + GetFloat(element, "width"); - points[2].y = points[3].y = points[0].y + GetFloat(element, "height"); - - /*const char *_rx = element->Attribute("rx"); - const char *_ry = element->Attribute("ry"); - - if (_rx || _ry) - { - float rx, ry; - - if (_rx) - { - rx = atof(_rx); - - if (_ry) - ry = atof(_ry); - else - ry = rx; - } - else - rx = ry = atof(_ry); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillRoundRect(rect, rx, ry); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeRoundRect(rect, rx, ry); - } - else - { - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillRect(rect); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeRect(rect); - }*/ - - BShape shape; - - shape.MoveTo(points[0]); - shape.LineTo(points[1]); - shape.LineTo(points[2]); - shape.LineTo(points[3]); - shape.Close(); - - fState.fMatrix.Transform(&shape); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillShape(&shape); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeShape(&shape); - } - else if (strcmpi(node->Value(), "text") == 0) - { - BPoint point(GetFloat(element, "x"), GetFloat(element, "y")); - - fState.fMatrix.Transform(&point); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - DrawString(GetText(element), point); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - DrawString(GetText(element), point); - - } - } - - TiXmlNode *child = 0; - - while (child = node->IterateChildren(child )) - DrawNode(child); - - if (node->Type() == TiXmlNode::ELEMENT) - Pop(); -} -//------------------------------------------------------------------------------ -void SVGViewView::Push() -{ +void Push() { _state_ *state = new _state_(fState); fStack.AddItem(state); } -//------------------------------------------------------------------------------ -void SVGViewView::Pop() -{ + +void Pop(BView *view) { if (fStack.CountItems() == 0) printf("Unbalance Push/Pop\n"); @@ -1311,27 +973,270 @@ void SVGViewView::Pop() if (fState.fFlags & STROKE_FLAG) { if (state->fStroke) - SetHighColor(state->fStrokeColor); + view->SetHighColor(state->fStrokeColor); } - + if (fState.fFlags & FILL_FLAG) { if (state->fFill) - SetHighColor(state->fFillColor); + view->SetHighColor(state->fFillColor); } - + if (fState.fFlags & STROKE_WIDTH_FLAG) - SetPenSize(state->fStrokeWidth); + view->SetPenSize(state->fStrokeWidth); if (fState.fFlags & LINE_MODE_FLAG) - SetLineMode(state->fLineCap, state->fLineJoin, state->fLineMiterLimit); - + view->SetLineMode(state->fLineCap, state->fLineJoin, state->fLineMiterLimit); + if (fState.fFlags & FONT_SIZE_FLAG) - SetFontSize(state->fFontSize); + view->SetFontSize(state->fFontSize); fState = *state; fStack.RemoveItem(state); delete state; } -//------------------------------------------------------------------------------ \ No newline at end of file + +void startElement(BView *view, const XML_Char *name, const XML_Char **attributes) { + Push(); + CheckAttributes(attributes, view); + + if (strcasecmp(name, "circle") == 0) { + BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); + float r = GetFloatAttribute(attributes, "r"); + + if (fState.fFill) { + view->SetHighColor(fState.fFillColor); + view->FillEllipse(c, r, r); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeEllipse(c, r, r); + } + else if (strcasecmp(name, "ellipse") == 0) { + BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); + float rx = GetFloatAttribute(attributes, "rx"); + float ry = GetFloatAttribute(attributes, "ry"); + + if (fState.fFill) { + view->SetHighColor(fState.fFillColor); + view->FillEllipse(c, rx, ry); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeEllipse(c, rx, ry); + } + else if (strcasecmp(name, "image") == 0) { + BPoint topLeft(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); + BPoint bottomRight(topLeft.x + GetFloatAttribute(attributes, "width"), + topLeft.y + GetFloatAttribute(attributes, "height")); + + fState.fMatrix.Transform(&topLeft); + fState.fMatrix.Transform(&bottomRight); + + const char *href = GetStringAttribute(attributes, "xlink:href"); + + if (href) { + BBitmap *bitmap = BTranslationUtils::GetBitmap(href); + + if (bitmap) { + view->DrawBitmap(bitmap, BRect(topLeft, bottomRight)); + delete bitmap; + } + } + } + else if (strcasecmp(name, "line") == 0){ + BPoint from(GetFloatAttribute(attributes, "x1"), GetFloatAttribute(attributes, "y1")); + BPoint to(GetFloatAttribute(attributes, "x2"), GetFloatAttribute(attributes, "y2")); + + fState.fMatrix.Transform(&from); + fState.fMatrix.Transform(&to); + + view->StrokeLine(from, to); + } + /*else if (strcasecmp(name, "linearGradient") == 0) { + named_color *gradient = GetFloatAttribute(element); + + if (gradient) + fGradients.AddItem(gradient); + }*/ + else if (strcasecmp(name, "path") == 0) { + BShape shape; + GetShapeAttribute(attributes, "d", shape); + fState.fMatrix.Transform(shape); + + if (fState.fFill) { + view->SetHighColor(fState.fFillColor); + view->FillShape(&shape); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeShape(&shape); + } + else if (strcasecmp(name, "polygon") == 0) { + BShape shape; + GetPolygonAttribute(attributes, "points", shape); + shape.Close(); + fState.fMatrix.Transform(shape); + + if (fState.fFill) { + view->SetHighColor(fState.fFillColor); + view->FillShape(&shape); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeShape(&shape); + } + else if (strcasecmp(name, "polyline") == 0) { + BShape shape; + GetPolygonAttribute(attributes, "points", shape); + fState.fMatrix.Transform(shape); + + if (fState.fFill) { + view->SetHighColor(fState.fFillColor); + view->FillShape(&shape); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeShape(&shape); + } + else if (strcasecmp(name, "rect") == 0) { + BPoint points[4]; + + points[0].x = points[3].x = GetFloatAttribute(attributes, "x"); + points[0].y= points[1].y = GetFloatAttribute(attributes, "y"); + points[1].x = points[2].x = points[0].x + GetFloatAttribute(attributes, "width"); + points[2].y = points[3].y = points[0].y + GetFloatAttribute(attributes, "height"); + + /*const char *_rx = element->Attribute("rx"); + const char *_ry = element->Attribute("ry"); + + if (_rx || _ry) + { + float rx, ry; + + if (_rx) + { + rx = atof(_rx); + + if (_ry) + ry = atof(_ry); + else + ry = rx; + } + else + rx = ry = atof(_ry); + + if (fState.fFill) + { + SetHighColor(fState.fFillColor); + FillRoundRect(rect, rx, ry); + SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + StrokeRoundRect(rect, rx, ry); + } + else + { + if (fState.fFill) + { + SetHighColor(fState.fFillColor); + FillRect(rect); + SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + StrokeRect(rect); + }*/ + + BShape shape; + + shape.MoveTo(points[0]); + shape.LineTo(points[1]); + shape.LineTo(points[2]); + shape.LineTo(points[3]); + shape.Close(); + + fState.fMatrix.Transform(shape); + + if (fState.fFill) + { + view->SetHighColor(fState.fFillColor); + view->FillShape(&shape); + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->StrokeShape(&shape); + } + /*else if (strcasecmp(name, "text") == 0) { + BPoint point(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); + + fState.fMatrix.Transform(&point); + + if (fState.fFill) + { + view->SetHighColor(fState.fFillColor); + view->DrawString(GetText(element), point); // We need to get the text using another callback + view->SetHighColor(fState.fStrokeColor); + } + if (fState.fStroke) + view->DrawString(GetText(element), point); + + }*/ +} + + +void +endElement(BView *view, const XML_Char *name) +{ + Pop(view); +} + + +Svg2PictureView::Svg2PictureView(BRect frame, const char *filename) + : BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), + fPicture(NULL) +{ + fFilename = filename; + fPicture = new BPicture; +} + + +Svg2PictureView::~Svg2PictureView() +{ + delete fPicture; +} + + +void +Svg2PictureView::AttachedToWindow() +{ + BeginPicture(fPicture); + char buf[256]; + bool done = false; + FILE *file = fopen(fFilename.String(), "rb"); + + if (file) { + XML_Parser parser = XML_ParserCreate("UTF-8"); + XML_SetUserData(parser, this); + XML_SetElementHandler(parser, (XML_StartElementHandler)startElement, (XML_EndElementHandler)endElement); + + while (!done) { + size_t len = fread(buf, 1, sizeof(buf), file); + done = len < sizeof(buf); + if (!XML_Parse(parser, buf, len, done)) + break; + } + + XML_ParserFree(parser); + fclose(file); + } + + EndPicture(); +} + + +void +Svg2PictureView::Draw(BRect updateRect) +{ + DrawPicture(fPicture); +} diff --git a/src/tests/kits/interface/picture/SVGViewView.h b/src/tests/kits/interface/picture/SVGViewView.h index a45db432b3..c279ff825d 100755 --- a/src/tests/kits/interface/picture/SVGViewView.h +++ b/src/tests/kits/interface/picture/SVGViewView.h @@ -1,97 +1,22 @@ #ifndef _SVG_VIEW_VIEW_H #define _SVG_VIEW_VIEW_H - -// Standard Includes ----------------------------------------------------------- - -// System Includes ------------------------------------------------------------- + +#include #include -// Project Includes ------------------------------------------------------------ -#include "tinyxml.h" -#include "Matrix.h" - -// Local Includes -------------------------------------------------------------- - -// Local Defines --------------------------------------------------------------- - -// Globals --------------------------------------------------------------------- - -enum { - STROKE_FLAG = 0x01, - FILL_FLAG = 0x02, - STROKE_WIDTH_FLAG = 0x04, - LINE_MODE_FLAG = 0x08, - FONT_SIZE_FLAG = 0x10, - MATRIX_FLAG = 0x20, - -}; - -struct _state_ { - - _state_() { set_default_values(); } - _state_(_state_ &state) { *this = state; } - void set_default_values() - { - fFlags = 0; - fStrokeColor.red = 0; fStrokeColor.green = 0; - fStrokeColor.blue = 0; fStrokeColor.alpha = 255; - fStroke = false; - fFillColor.red = 0; fFillColor.green = 0; - fFillColor.blue = 0; fFillColor.alpha = 255; - fFill = true; - fStrokeWidth = 1.0f; - fLineCap = B_BUTT_CAP; - fLineJoin = B_MITER_JOIN; - fLineMiterLimit = B_DEFAULT_MITER_LIMIT; - fFontSize = 9.0f; - } - - uint32 fFlags; - rgb_color fStrokeColor; - bool fStroke; - rgb_color fFillColor; - bool fFill; - float fStrokeWidth; - cap_mode fLineCap; - join_mode fLineJoin; - float fLineMiterLimit; - float fFontSize; - BMatrix fMatrix; -}; - -struct named_color { - const char *name; - rgb_color color; -}; - -// SVGViewWindow class ------------------------------------------------------ -class SVGViewView : public BView { +class BPicture; +class Svg2PictureView : public BView { public: - SVGViewView(BRect frame, const char *name, - const char *file); -virtual ~SVGViewView(); + Svg2PictureView(BRect frame, const char *filename); + ~Svg2PictureView(); -virtual void Draw(BRect updateRect); + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); private: - rgb_color GetColor(const char *name, uint8 alpha); - named_color *GetGradient(TiXmlElement *element); - - void CheckAttributes(TiXmlElement *element); - void DrawNode(TiXmlNode *node); - - void Push(); - void Pop(); - - _state_ fState; - BList fStack; - - BList fGradients; - BPicture *fPicture; - - TiXmlDocument fDoc; + BString fFilename; + BPicture *fPicture; }; -//------------------------------------------------------------------------------ #endif // _SVG_VIEW_VIEW_H diff --git a/src/tests/kits/interface/picture/main.cpp b/src/tests/kits/interface/picture/main.cpp deleted file mode 100755 index 06c1c89823..0000000000 --- a/src/tests/kits/interface/picture/main.cpp +++ /dev/null @@ -1,1261 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "Matrix.h" - -struct named_color { - const char *name; - rgb_color color; -}; - -named_color colors[] = { - { "aliceblue", { 240, 248, 255, 255 } }, - { "antiquewhite", { 250, 235, 215, 255 } }, - { "aqua", { 0, 255, 255, 255 } }, - { "aquamarine", { 127, 255, 212, 255 } }, - { "azure", { 240, 255, 255, 255 } }, - { "beige", { 245, 245, 220, 255 } }, - { "bisque", { 255, 228, 196, 255 } }, - { "black", { 0, 0, 0, 255 } }, - { "blanchedalmond", { 255, 235, 205, 255 } }, - { "blue", { 0, 0, 255, 255 } }, - { "blueviolet", { 138, 43, 226, 255 } }, - { "brown", { 165, 42, 42, 255 } }, - { "burlywood", { 222, 184, 135, 255 } }, - { "cadetblue", { 95, 158, 160, 255 } }, - { "chartreuse", { 127, 255, 0, 255 } }, - { "chocolate", { 210, 105, 30, 255 } }, - { "coral", { 255, 127, 80, 255 } }, - { "cornflowerblue", { 100, 149, 237, 255 } }, - { "cornsilk", { 255, 248, 220, 255 } }, - { "crimson", { 220, 20, 60, 255 } }, - { "cyan", { 0, 255, 255, 255 } }, - { "darkblue", { 0, 0, 139, 255 } }, - { "darkcyan", { 0, 139, 139, 255 } }, - { "darkgoldenrod", { 184, 134, 11, 255 } }, - { "darkgray", { 169, 169, 169, 255 } }, - { "darkgreen", { 0, 100, 0, 255 } }, - { "darkgrey", { 169, 169, 169, 255 } }, - { "darkkhaki", { 189, 183, 107, 255 } }, - { "darkmagenta", { 139, 0, 139, 255 } }, - { "darkolivegreen", { 85, 107, 47, 255 } }, - { "darkorange", { 255, 140, 0, 255 } }, - { "darkorchid", { 153, 50, 204, 255 } }, - { "darkred", { 139, 0, 0, 255 } }, - { "darksalmon", { 233, 150, 122, 255 } }, - { "darkseagreen", { 143, 188, 143, 255 } }, - { "darkslateblue", { 72, 61, 139, 255 } }, - { "darkslategray", { 47, 79, 79, 255 } }, - { "darkslategrey", { 47, 79, 79, 255 } }, - { "darkturquoise", { 0, 206, 209, 255 } }, - { "darkviolet", { 148, 0, 211, 255 } }, - { "deeppink", { 255, 20, 147, 255 } }, - { "deepskyblue", { 0, 191, 255, 255 } }, - { "dimgray", { 105, 105, 105, 255 } }, - { "dimgrey", { 105, 105, 105, 255 } }, - { "dodgerblue", { 30, 144, 255, 255 } }, - { "firebrick", { 178, 34, 34, 255 } }, - { "floralwhite", { 255, 250, 240, 255 } }, - { "forestgreen", { 34, 139, 34, 255 } }, - { "fuchsia", { 255, 0, 255, 255 } }, - { "gainsboro", { 220, 220, 220, 255 } }, - { "ghostwhite", { 248, 248, 255, 255 } }, - { "gold", { 255, 215, 0, 255 } }, - { "goldenrod", { 218, 165, 32, 255 } }, - { "gray", { 128, 128, 128, 255 } }, - { "grey", { 128, 128, 128, 255 } }, - { "green", { 0, 128, 0, 255 } }, - { "greenyellow", { 173, 255, 47, 255 } }, - { "honeydew", { 240, 255, 240, 255 } }, - { "hotpink", { 255, 105, 180, 255 } }, - { "indianred", { 205, 92, 92, 255 } }, - { "indigo", { 75, 0, 130, 255 } }, - { "ivory", { 255, 255, 240, 255 } }, - { "khaki", { 240, 230, 140, 255 } }, - { "lavender", { 230, 230, 250, 255 } }, - { "lavenderblush", { 255, 240, 245, 255 } }, - { "lawngreen", { 124, 252, 0, 255 } }, - { "lemonchiffon", { 255, 250, 205, 255 } }, - { "lightblue", { 173, 216, 230, 255 } }, - { "lightcoral", { 240, 128, 128, 255 } }, - { "lightcyan", { 224, 255, 255, 255 } }, - { "lightgoldenrodyellow",{ 250, 250, 210, 255 } }, - { "lightgray", { 211, 211, 211, 255 } }, - { "lightgreen", { 144, 238, 144, 255 } }, - { "lightgrey", { 211, 211, 211, 255 } }, - { "lightpink", { 255, 182, 193, 255 } }, - { "lightsalmon", { 255, 160, 122, 255 } }, - { "lightseagreen", { 32, 178, 170, 255 } }, - { "lightskyblue", { 135, 206, 250, 255 } }, - { "lightslategray", { 119, 136, 153, 255 } }, - { "lightslategrey", { 119, 136, 153, 255 } }, - { "lightsteelblue", { 176, 196, 222, 255 } }, - { "lightyellow", { 255, 255, 224, 255 } }, - { "lime", { 0, 255, 0, 255 } }, - { "limegreen", { 50, 205, 50, 255 } }, - { "linen", { 250, 240, 230, 255 } }, - { "magenta", { 255, 0, 255, 255 } }, - { "maroon", { 128, 0, 0, 255 } }, - { "mediumaquamarine", { 102, 205, 170, 255 } }, - { "mediumblue", { 0, 0, 205, 255 } }, - { "mediumorchid", { 186, 85, 211, 255 } }, - { "mediumpurple", { 147, 112, 219, 255 } }, - { "mediumseagreen", { 60, 179, 113, 255 } }, - { "mediumslateblue", { 123, 104, 238, 255 } }, - { "mediumspringgreen", { 0, 250, 154, 255 } }, - { "mediumturquoise", { 72, 209, 204, 255 } }, - { "mediumvioletred", { 199, 21, 133, 255 } }, - { "midnightblue", { 25, 25, 112, 255 } }, - { "mintcream", { 245, 255, 250, 255 } }, - { "mistyrose", { 255, 228, 225, 255 } }, - { "moccasin", { 255, 228, 181, 255 } }, - { "navajowhite", { 255, 222, 173, 255 } }, - { "navy", { 0, 0, 128, 255 } }, - { "oldlace", { 253, 245, 230, 255 } }, - { "olive", { 128, 128, 0, 255 } }, - { "olivedrab", { 107, 142, 35, 255 } }, - { "orange", { 255, 165, 0, 255 } }, - { "orangered", { 255, 69, 0, 255 } }, - { "orchid", { 218, 112, 214, 255 } }, - { "palegoldenrod", { 238, 232, 170, 255 } }, - { "palegreen", { 152, 251, 152, 255 } }, - { "paleturquoise", { 175, 238, 238, 255 } }, - { "palevioletred", { 219, 112, 147, 255 } }, - { "papayawhip", { 255, 239, 213, 255 } }, - { "peachpuff", { 255, 218, 185, 255 } }, - { "peru", { 205, 133, 63, 255 } }, - { "pink", { 255, 192, 203, 255 } }, - { "plum", { 221, 160, 221, 255 } }, - { "powderblue", { 176, 224, 230, 255 } }, - { "purple", { 128, 0, 128, 255 } }, - { "red", { 255, 0, 0, 255 } }, - { "rosybrown", { 188, 143, 143, 255 } }, - { "royalblue", { 65, 105, 225, 255 } }, - { "saddlebrown", { 139, 69, 19, 255 } }, - { "salmon", { 250, 128, 114, 255 } }, - { "sandybrown", { 244, 164, 96, 255 } }, - { "seagreen", { 46, 139, 87, 255 } }, - { "seashell", { 255, 245, 238, 255 } }, - { "sienna", { 160, 82, 45, 255 } }, - { "silver", { 192, 192, 192, 255 } }, - { "skyblue", { 135, 206, 235, 255 } }, - { "slateblue", { 106, 90, 205, 255 } }, - { "slategray", { 112, 128, 144, 255 } }, - { "slategrey", { 112, 128, 144, 255 } }, - { "snow", { 255, 250, 250, 255 } }, - { "springgreen", { 0, 255, 127, 255 } }, - { "steelblue", { 70, 130, 180, 255 } }, - { "tan", { 210, 180, 140, 255 } }, - { "teal", { 0, 128, 128, 255 } }, - { "thistle", { 216, 191, 216, 255 } }, - { "tomato", { 255, 99, 71, 255 } }, - { "turquoise", { 64, 224, 208, 255 } }, - { "violet", { 238, 130, 238, 255 } }, - { "wheat", { 245, 222, 179, 255 } }, - { "white", { 255, 255, 255, 255 } }, - { "whitesmoke", { 245, 245, 245, 255 } }, - { "yellow", { 255, 255, 0, 255 } }, - { "yellowgreen", { 154, 205, 50, 255 } }, - { NULL , { 0, 0, 0, 255 } }, -}; - -enum { - STROKE_FLAG = 0x01, - FILL_FLAG = 0x02, - STROKE_WIDTH_FLAG = 0x04, - LINE_MODE_FLAG = 0x08, - FONT_SIZE_FLAG = 0x10, - MATRIX_FLAG = 0x20, - -}; - -struct _state_ { - - _state_() { set_default_values(); } - _state_(_state_ &state) { *this = state; } - void set_default_values() - { - fFlags = 0; - fStrokeColor.red = 0; fStrokeColor.green = 0; - fStrokeColor.blue = 0; fStrokeColor.alpha = 255; - fStroke = false; - fFillColor.red = 0; fFillColor.green = 0; - fFillColor.blue = 0; fFillColor.alpha = 255; - fFill = true; - fStrokeWidth = 1.0f; - fLineCap = B_BUTT_CAP; - fLineJoin = B_MITER_JOIN; - fLineMiterLimit = B_DEFAULT_MITER_LIMIT; - fFontSize = 9.0f; - } - - uint32 fFlags; - rgb_color fStrokeColor; - bool fStroke; - rgb_color fFillColor; - bool fFill; - float fStrokeWidth; - cap_mode fLineCap; - join_mode fLineJoin; - float fLineMiterLimit; - float fFontSize; - BMatrix fMatrix; -}; - -_state_ fState; -BList fStack; -//BList fGradients; - -bool HasAttribute(const XML_Char **attributes, const char *name) { - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - return (*attributes); -} - -float GetFloatAttribute(const XML_Char **attributes, const char *name) { - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - return atof(*(attributes + 1)); - else - return 0; -} - -const char *GetStringAttribute(const XML_Char **attributes, const char *name) { - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - return *(attributes + 1); - else - return NULL; -} - -rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha) { - const char *attr = GetStringAttribute(attributes, name); - - if (!attr) - return colors[0].color; - - int32 red, green, blue; - - if (attr[0] == '#') { - if (strlen(attr) == 4) { - sscanf(attr, "#%1X%1X%1X", &red, &green, &blue); - red = (red << 4) + red; - green = (green << 4) + green; - blue = (blue << 4) + blue; - } - else - sscanf(attr, "#%2X%2X%2X", &red, &green, &blue); - - rgb_color color; - - color.red = red; - color.green = green; - color.blue = blue; - color.alpha = alpha; - - return color; - } - - if (sscanf(attr, "rgb(%d, %d, %d)", &red, &green, &blue) == 3) { - rgb_color color; - - color.red = red; - color.green = green; - color.blue = blue; - color.alpha = alpha; - - return color; - } - - float redf, greenf, bluef; - - if (sscanf(attr, "rgb(%f%%, %f%%, %f%%)", &redf, &greenf, &bluef) == 3) { - rgb_color color; - - color.red = (int32)(redf * 2.55f); - color.green = (int32)(greenf * 2.55f); - color.blue = (int32)(bluef * 2.55f); - color.alpha = alpha; - - return color; - } - - /*if (strcmpi(attr, "url")) { - const char *grad = strchr(attr, '#'); - - if (grad) { - for (int32 i = 0; i < fGradients.CountItems(); i++) { - named_color *item = (named_color*)fGradients.ItemAt(i); - - if (strstr(grad, item->name)) { - rgb_color color = item->color; - color.alpha = alpha; - return color; - } - } - } - }*/ - - for (int32 i = 0; colors[i].name != NULL; i++) - if (strcmpi(colors[i].name, attr) == 0) { - rgb_color color = colors[i].color; - color.alpha = alpha; - return color; - } - - rgb_color color = colors[0].color; - color.alpha = alpha; - return color; -} - -void GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape) { - const char *attr = NULL; - - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - attr = *(attributes + 1); - - if (!attr) - return; - - char *ptr = const_cast(attr); - BPoint point; - bool first = true; - - while (*ptr) { - // Skip white space and ',' - while (*ptr && (*ptr == ' ') || (*ptr == ',')) - ptr++; - - sscanf(ptr, "%f", &point.x); - - // Skip x - while (*ptr && *ptr != ',') - ptr++; - if (!*ptr || !*(ptr + 1)) - break; - ptr++; - - sscanf(ptr, "%f", &point.y); - - if (first) - { - shape.MoveTo(point); - first = false; - } - else - shape.LineTo(point); - - // Skip y - while (*ptr && (*ptr != ' ') && (*ptr != ',')) - ptr++; - } -} - -void GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix) { - const char *attr = NULL; - - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - attr = *(attributes + 1); - - if (!attr) - return; - - char *ptr = (char*)attr; - - while (*ptr) { - while (*ptr == ' ') - ptr++; - - char *transform_name = ptr; - - while (*ptr != '(') - ptr++; - - if (strncmp(transform_name, "translate", 9) == 0) { - float x, y; - - if (sscanf(ptr, "(%f %f)", &x, &y) != 2) - sscanf(ptr, "(%f,%f)", &x, &y); - - matrix->Translate(x, y); - } - else if (strncmp(transform_name, "rotate", 6) == 0) { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->Rotate(angle); - } - else if (strncmp(transform_name, "scale", 5) == 0) { - float sx, sy; - - if (sscanf(ptr, "(%f,%f)", &sx, &sy) == 2) - matrix->Scale(sx, sy); - else - { - sscanf(ptr, "(%f)", &sx); - matrix->Scale(sx, sx); - } - } - else if (strncmp(transform_name, "skewX", 5) == 0) { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->SkewX(angle); - } - else if (strncmp(transform_name, "skewY", 5) == 0) { - float angle; - - sscanf(ptr, "(%f)", &angle); - - matrix->SkewY(angle); - } - - while (*ptr != ')') - ptr++; - - ptr++; - } -} - -double CalcVectorAngle(double ux, double uy, double vx, double vy) { - double ta = atan2(uy, ux); - double tb = atan2(vy, vx); - - if (tb >= ta) - return tb - ta; - - return 6.28318530718 - (ta - tb); -} - -char *SkipFloat(char *string) { - if (*string == '-') - string++; - - int32 len = strspn(string, "1234567890."); - - return string + len; -} - -char *FindFloat(char *string) { - return strpbrk(string, "1234567890-."); -} - -float GetFloat(char **string) { - *string = FindFloat(*string); - float f = atof(*string); - *string = SkipFloat(*string); - return f; -} - -void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &shape) { - const char *attr = NULL; - - while (*attributes && strcmpi(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - attr = *(attributes + 1); - - if (!attr) - return; - - char *ptr = const_cast(attr); - float x, y, x1, y1, x2, y2, rx, ry, angle; - bool largeArcFlag, sweepFlag; - char command, prevCommand = 0; - BPoint prevCtlPt; - BPoint pos, startPos; - bool canMove = true; - - while (*ptr) { - ptr = strpbrk(ptr, "ZzMmLlCcQqAaHhVvSsTt"); - - if (ptr == NULL) - break; - - command = *ptr; - - switch (command) { - case 'Z': - case 'z': - { - pos.Set(startPos.x, startPos.y); - canMove = true; - shape.Close(); - ptr++; - break; - } - case 'M': - { - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - pos.Set(x, y); - if (canMove) - startPos = pos; - shape.MoveTo(pos); - break; - } - case 'm': - { - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - pos.x += x; - pos.y += y; - if (canMove) - startPos = pos; - shape.MoveTo(pos); - break; - } - case 'L': - { - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - pos.Set(x, y); - canMove = false; - shape.LineTo(pos); - break; - } - case 'l': - { - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - pos.x += x; - pos.y += y; - canMove = false; - shape.LineTo(pos); - break; - } - case 'C': - case 'c': - { - if (command == 'C') { - x1 = GetFloat(&ptr); - y1 = GetFloat(&ptr); - x2 = GetFloat(&ptr); - y2 = GetFloat(&ptr); - x = GetFloat(&ptr); - y = GetFloat(&ptr); - } - else { - x1 = GetFloat(&ptr); - y1 = GetFloat(&ptr); - x2 = GetFloat(&ptr); - y2 = GetFloat(&ptr); - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - x1 += pos.x; - y1 += pos.y; - x2 += pos.x; - y2 += pos.y; - x += pos.x; - y += pos.y; - } - - BPoint controlPoints[3]; - - controlPoints[0].Set(x1, y1); - controlPoints[1].Set(x2, y2); - controlPoints[2].Set(x, y); - - pos.Set(x, y); - prevCtlPt = controlPoints[1]; - canMove = false; - shape.BezierTo(controlPoints); - break; - } - case 'Q': - case 'q': - { - if (command == 'Q') { - if (sscanf(ptr, "Q %f %f %f %f", &x1, &y1, &x, &y) != 4) - sscanf(ptr, "Q %f,%f %f,%f", &x1, &y1, &x, &y); - } - else { - if (sscanf(ptr, "q %f %f %f %f", &x1, &y1, &x, &y) != 4) - sscanf(ptr, "q %f,%f %f,%f", &x1, &y1, &x, &y); - - x1 += pos.x; - y1 += pos.y; - x += pos.x; - y += pos.y; - } - - BPoint controlPoints[3]; - - controlPoints[0].Set(pos.x + 2.0f / 3.0f * (x1 - pos.x), - pos.y + 2.0f / 3.0f * (y1 - pos.y)); - controlPoints[1].Set(x1 + 1.0f / 3.0f * (x - x1), - y1 + 1.0f / 3.0f * (y - y1)); - controlPoints[2].Set(x, y); - - pos.Set(x, y); - prevCtlPt.Set(x1, y1); - canMove = false; - shape.BezierTo(controlPoints); - break; - } - case 'A': - case 'a': - { - x1 = pos.x; - y1 = pos.y; - - if (command == 'A') { - if (sscanf(ptr, "A %f %f %f %d %d %f %f", &rx, &ry, &angle, - &largeArcFlag, &sweepFlag, &x, &y) != 7) - sscanf(ptr, "A %f,%f %f %d,%d %f,%f", &rx, &ry, &angle, - &largeArcFlag, &sweepFlag, &x, &y); - - x2 = x; - y2 = y; - } - else { - if (sscanf(ptr, "a %f %f %f %d %d %f %f", &rx, &ry, &angle, - &largeArcFlag, &sweepFlag, &x, &y) != 7) - sscanf(ptr, "a %f,%f %f %d,%d %f,%f", &rx, &ry, &angle, - &largeArcFlag, &sweepFlag, &x, &y); - - x2 = x + pos.x; - y2 = y + pos.y; - } - - const double pi = 3.14159265359; - const double radPerDeg = pi / 180.0; - - if (x1 == x2 && y1 == y2) - break; - - if (rx == 0.0f || ry == 0.0f) { - shape.LineTo(BPoint((float)x2, (float)y2)); - break; - } - - if (rx < 0.0) - rx = -rx; - - if (ry < 0.0) - ry = -ry; - - double sinPhi = sin(angle * radPerDeg); - double cosPhi = cos(angle * radPerDeg); - - double x1dash = cosPhi * (x1 - x2) / 2.0 + - sinPhi * (y1 - y2) / 2.0; - double y1dash = -sinPhi * (x1 - x2) / 2.0 + - cosPhi * (y1 - y2) / 2.0; - - double root, numerator = rx * rx * ry * ry - rx * rx * y1dash * y1dash - - ry * ry * x1dash * x1dash; - - if (numerator < 0.0) { - double s = (float)sqrt(1.0 - numerator / (rx * rx * ry * ry)); - - rx *= s; - ry *= s; - root = 0.0; - } - else { - root = (largeArcFlag == sweepFlag ? -1.0 : 1.0) * - sqrt(numerator / - (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash)); - } - - double cxdash = root * rx * y1dash / ry, cydash = -root * ry * x1dash / rx; - - double cx = cosPhi * cxdash - sinPhi * cydash + (x1 + x2) / 2.0; - double cy = sinPhi * cxdash + cosPhi * cydash + (y1 + y2) / 2.0; - - double theta1 = CalcVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, - (y1dash - cydash) / ry ), - dtheta = CalcVectorAngle((x1dash - cxdash) / rx, - (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, - (-y1dash - cydash) / ry); - - if (!sweepFlag && dtheta > 0) - dtheta -= 2.0 * pi; - else if (sweepFlag && dtheta < 0) - dtheta += 2.0 * pi; - - int segments = (int)ceil (fabs(dtheta / (pi / 2.0))); - double delta = dtheta / segments; - double t = 8.0/3.0 * sin(delta / 4.0) * sin( delta / 4.0) / - sin(delta / 2.0); - - BPoint controlPoints[3]; - - for (int n = 0; n < segments; ++n) { - double cosTheta1 = cos(theta1); - double sinTheta1 = sin(theta1); - double theta2 = theta1 + delta; - double cosTheta2 = cos(theta2); - double sinTheta2 = sin(theta2); - - double xe = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx; - double ye = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy; - - double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1); - double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1); - - double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2); - double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2); - - controlPoints[0].Set((float)(x1 + dx1), (float)(y1 + dy1)); - controlPoints[1].Set((float)(xe + dxe), (float)(ye + dye)); - controlPoints[2].Set((float)xe, (float)ye ); - - shape.BezierTo(controlPoints); - - theta1 = theta2; - x1 = (float)xe; - y1 = (float)ye; - } - - pos.Set(x2, y2); - break; - } - case 'H': - { - x = GetFloat(&ptr); - - pos.x = x; - canMove = false; - shape.LineTo(pos); - break; - } - case 'h': - { - x = GetFloat(&ptr); - - pos.x += x; - canMove = false; - shape.LineTo(pos); - break; - } - case 'V': - { - y = GetFloat(&ptr); - - pos.y = y; - canMove = false; - shape.LineTo(pos); - break; - } - case 'v': - { - y = GetFloat(&ptr); - - pos.y += y; - canMove = false; - shape.LineTo(pos); - break; - } - case 'S': - case 's': - { - if (command == 'S') { - x2 = GetFloat(&ptr); - y2 = GetFloat(&ptr); - x = GetFloat(&ptr); - y = GetFloat(&ptr); - } - else { - x2 = GetFloat(&ptr); - y2 = GetFloat(&ptr); - x = GetFloat(&ptr); - y = GetFloat(&ptr); - - x2 += pos.x; - y2 += pos.y; - x += pos.x; - y += pos.y; - } - - if (prevCommand == 'C' || prevCommand == 'c' || - prevCommand == 'S' || prevCommand == 's') { - x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); - y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); - } - else { - x1 = pos.x; - y1 = pos.y; - } - - BPoint controlPoints[3]; - - controlPoints[0].Set(x1, y1); - controlPoints[1].Set(x2, y2); - controlPoints[2].Set(x, y); - - pos.Set(x, y); - prevCtlPt.Set(x2, y2); - canMove = false; - shape.BezierTo(controlPoints); - break; - } - case 'T': - case 't': - { - if (command == 'T') { - if (sscanf(ptr, "T %f %f", &x, &y) != 2) - sscanf(ptr, "T %f,%f", &x, &y); - } - else { - if (sscanf(ptr, "t %f %f", &x, &y) != 2) - sscanf(ptr, "t %f,%f", &x, &y); - - x += pos.x; - y += pos.y; - } - - if (prevCommand == 'Q' || prevCommand == 'q' || - prevCommand == 'T' || prevCommand == 't') { - x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); - y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); - } - else { - x1 = pos.x; - y1 = pos.y; - } - - BPoint controlPoints[3]; - - controlPoints[0].Set(pos.x + 2.0f / 3.0f * (x1 - pos.x), - pos.y + 2.0f / 3.0f * (y1 - pos.y)); - controlPoints[1].Set(x1 + 1.0f / 3.0f * (x - x1), - y1 + 1.0f / 3.0f * (y - y1)); - controlPoints[2].Set(x, y); - - pos.Set(x, y); - prevCtlPt.Set(x1, y1); - canMove = false; - shape.BezierTo(controlPoints); - break; - } - } - - prevCommand = command; - } -} - -void CheckAttributes(const XML_Char **attributes, BView *view) { - uint8 alpha = fState.fStrokeColor.alpha; - - if (HasAttribute(attributes, "opacity")) { - float opacity = GetFloatAttribute(attributes, "opacity"); - fState.fStrokeColor.alpha = (uint8)(opacity * alpha); - fState.fFlags |= STROKE_FLAG; - fState.fFillColor.alpha = (uint8)(opacity * alpha); - fState.fFlags |= FILL_FLAG; - } - - if (HasAttribute(attributes, "stroke")) { - const char *stroke = GetStringAttribute(attributes, "stroke"); - if (strcmpi(stroke, "none") == 0) - fState.fStroke = false; - else { - fState.fStrokeColor = GetColorAttribute(attributes, "stroke", fState.fFillColor.alpha); - fState.fStroke = true; - view->SetHighColor(fState.fStrokeColor); - } - fState.fFlags |= STROKE_FLAG; - } - - if (HasAttribute(attributes, "stroke-opacity")) { - fState.fStrokeColor.alpha = (uint8)(GetFloatAttribute(attributes, "stroke-opacity") * alpha); - fState.fFlags |= STROKE_FLAG; - } - - if (HasAttribute(attributes, "fill")) { - const char *fill = GetStringAttribute(attributes, "fill"); - if (strcmpi(fill, "none") == 0) - fState.fFill = false; - else { - fState.fFillColor = GetColorAttribute(attributes, "fill", fState.fFillColor.alpha); - fState.fFill = true; - } - fState.fFlags |= FILL_FLAG; - } - - if (HasAttribute(attributes, "fill-opacity")) { - fState.fFillColor.alpha = (uint8)(GetFloatAttribute(attributes, "fill-opacity") * alpha); - fState.fFlags |= FILL_FLAG; - } - - if (HasAttribute(attributes, "stroke-width")) { - fState.fStrokeWidth = GetFloatAttribute(attributes, "stroke-width"); - view->SetPenSize(fState.fStrokeWidth); - fState.fFlags |= STROKE_WIDTH_FLAG; - } - - if (HasAttribute(attributes, "stroke-linecap")) { - const char *stroke_linecap = GetStringAttribute(attributes, "stroke-linecap"); - - if (strcmpi(stroke_linecap, "but") == 0) - fState.fLineCap = B_BUTT_CAP; - else if (strcmpi(stroke_linecap, "round") == 0) - fState.fLineCap = B_ROUND_CAP; - else if (strcmpi(stroke_linecap, "square") == 0) - fState.fLineCap = B_SQUARE_CAP; - - view->SetLineMode(fState.fLineCap, view->LineJoinMode(), view->LineMiterLimit()); - fState.fFlags |= LINE_MODE_FLAG; - } - - if (HasAttribute(attributes, "stroke-linejoin")) { - const char *stroke_linejoin = GetStringAttribute(attributes, "stroke-linejoin"); - - if (strcmpi(stroke_linejoin, "miter") == 0) - fState.fLineJoin = B_MITER_JOIN; - else if (strcmpi(stroke_linejoin, "round") == 0) - fState.fLineJoin = B_ROUND_JOIN; - else if (strcmpi(stroke_linejoin, "bevel") == 0) - fState.fLineJoin = B_BEVEL_JOIN; - - view->SetLineMode(view->LineCapMode(), fState.fLineJoin, view->LineMiterLimit()); - fState.fFlags |= LINE_MODE_FLAG; - } - - if (HasAttribute(attributes, "stroke-miterlimit")) { - fState.fLineMiterLimit = GetFloatAttribute(attributes, "stroke-miterlimit"); - view->SetLineMode(view->LineCapMode(), view->LineJoinMode(), fState.fLineMiterLimit); - fState.fFlags |= LINE_MODE_FLAG; - } - - if (HasAttribute(attributes, "font-size")) { - fState.fFontSize = GetFloatAttribute(attributes, "font-size"); - view->SetFontSize(fState.fFontSize); - fState.fFlags |= FONT_SIZE_FLAG; - } - - if (HasAttribute(attributes, "transform")) { - BMatrix matrix; - GetMatrixAttribute(attributes, "transform", &matrix); - fState.fMatrix *= matrix; - fState.fFlags |= MATRIX_FLAG; - } -} - -void Push() { - _state_ *state = new _state_(fState); - - fStack.AddItem(state); -} - -void Pop(BView *view) { - if (fStack.CountItems() == 0) - printf("Unbalance Push/Pop\n"); - - _state_ *state = (_state_*)fStack.LastItem(); - - if (fState.fFlags & STROKE_FLAG) - { - if (state->fStroke) - view->SetHighColor(state->fStrokeColor); - } - - if (fState.fFlags & FILL_FLAG) - { - if (state->fFill) - view->SetHighColor(state->fFillColor); - } - - if (fState.fFlags & STROKE_WIDTH_FLAG) - view->SetPenSize(state->fStrokeWidth); - - if (fState.fFlags & LINE_MODE_FLAG) - view->SetLineMode(state->fLineCap, state->fLineJoin, state->fLineMiterLimit); - - if (fState.fFlags & FONT_SIZE_FLAG) - view->SetFontSize(state->fFontSize); - - fState = *state; - - fStack.RemoveItem(state); - delete state; -} - -void startElement(BView *view, const XML_Char *name, const XML_Char **attributes) { - Push(); - CheckAttributes(attributes, view); - - if (strcmpi(name, "circle") == 0) { - BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); - float r = GetFloatAttribute(attributes, "r"); - - if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillEllipse(c, r, r); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeEllipse(c, r, r); - } - else if (strcmpi(name, "ellipse") == 0) { - BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); - float rx = GetFloatAttribute(attributes, "rx"); - float ry = GetFloatAttribute(attributes, "ry"); - - if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillEllipse(c, rx, ry); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeEllipse(c, rx, ry); - } - else if (strcmpi(name, "image") == 0) { - BPoint topLeft(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); - BPoint bottomRight(topLeft.x + GetFloatAttribute(attributes, "width"), - topLeft.y + GetFloatAttribute(attributes, "height")); - - fState.fMatrix.Transform(&topLeft); - fState.fMatrix.Transform(&bottomRight); - - const char *href = GetStringAttribute(attributes, "xlink:href"); - - if (href) { - BBitmap *bitmap = BTranslationUtils::GetBitmap(href); - - if (bitmap) { - view->DrawBitmap(bitmap, BRect(topLeft, bottomRight)); - delete bitmap; - } - } - } - else if (strcmpi(name, "line") == 0){ - BPoint from(GetFloatAttribute(attributes, "x1"), GetFloatAttribute(attributes, "y1")); - BPoint to(GetFloatAttribute(attributes, "x2"), GetFloatAttribute(attributes, "y2")); - - fState.fMatrix.Transform(&from); - fState.fMatrix.Transform(&to); - - view->StrokeLine(from, to); - } - /*else if (strcmpi(name, "linearGradient") == 0) { - named_color *gradient = GetFloatAttribute(element); - - if (gradient) - fGradients.AddItem(gradient); - }*/ - else if (strcmpi(name, "path") == 0) { - BShape shape; - GetShapeAttribute(attributes, "d", shape); - fState.fMatrix.Transform(shape); - - if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeShape(&shape); - } - else if (strcmpi(name, "polygon") == 0) { - BShape shape; - GetPolygonAttribute(attributes, "points", shape); - shape.Close(); - fState.fMatrix.Transform(shape); - - if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeShape(&shape); - } - else if (strcmpi(name, "polyline") == 0) { - BShape shape; - GetPolygonAttribute(attributes, "points", shape); - fState.fMatrix.Transform(shape); - - if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeShape(&shape); - } - else if (strcmpi(name, "rect") == 0) { - BPoint points[4]; - - points[0].x = points[3].x = GetFloatAttribute(attributes, "x"); - points[0].y= points[1].y = GetFloatAttribute(attributes, "y"); - points[1].x = points[2].x = points[0].x + GetFloatAttribute(attributes, "width"); - points[2].y = points[3].y = points[0].y + GetFloatAttribute(attributes, "height"); - - /*const char *_rx = element->Attribute("rx"); - const char *_ry = element->Attribute("ry"); - - if (_rx || _ry) - { - float rx, ry; - - if (_rx) - { - rx = atof(_rx); - - if (_ry) - ry = atof(_ry); - else - ry = rx; - } - else - rx = ry = atof(_ry); - - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillRoundRect(rect, rx, ry); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeRoundRect(rect, rx, ry); - } - else - { - if (fState.fFill) - { - SetHighColor(fState.fFillColor); - FillRect(rect); - SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - StrokeRect(rect); - }*/ - - BShape shape; - - shape.MoveTo(points[0]); - shape.LineTo(points[1]); - shape.LineTo(points[2]); - shape.LineTo(points[3]); - shape.Close(); - - fState.fMatrix.Transform(shape); - - if (fState.fFill) - { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->StrokeShape(&shape); - } - /*else if (strcmpi(name, "text") == 0) { - BPoint point(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); - - fState.fMatrix.Transform(&point); - - if (fState.fFill) - { - view->SetHighColor(fState.fFillColor); - view->DrawString(GetText(element), point); // We need to get the text using another callback - view->SetHighColor(fState.fStrokeColor); - } - if (fState.fStroke) - view->DrawString(GetText(element), point); - - }*/ -} - -void endElement(BView *view, const XML_Char *name){ - Pop(view); -} - -class Svg2PictureView : public BView { -public: - Svg2PictureView(BRect frame, const char *filename) - : BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), - fPicture(NULL) { - fFilename = filename; - fPicture = new BPicture; - } - ~Svg2PictureView() { - delete fPicture; - } - - virtual void AttachedToWindow() { - BeginPicture(fPicture); - - char buf[256]; - bool done = false; - FILE *file = fopen(fFilename.String(), "rb"); - - if (file) { - XML_Parser parser = XML_ParserCreate("UTF-8"); - XML_SetUserData(parser, this); - XML_SetElementHandler(parser, (XML_StartElementHandler)startElement, (XML_EndElementHandler)endElement); - - while (!done) { - size_t len = fread(buf, 1, sizeof(buf), file); - done = len < sizeof(buf); - if (!XML_Parse(parser, buf, len, done)) - break; - } - - XML_ParserFree(parser); - fclose(file); - } - - EndPicture(); - } - - virtual void Draw(BRect updateRect) { - DrawPicture(fPicture); - } - -private: - BString fFilename; - BPicture *fPicture; -}; - -class Svg2PictureWindow : public BWindow -{ -public: - Svg2PictureWindow(BRect frame, const char *filename) - : BWindow(frame, "Svg2Picture", B_TITLED_WINDOW, 0) { - Lock(); - - BView *view = new Svg2PictureView(Bounds(), filename); - AddChild(view); - - Unlock(); - } - ~Svg2PictureWindow() {} - -private: -}; - -int main() { - BApplication *app = new BApplication("application/x-vnd.Be-SVG2"); - BRect frame = BRect(100, 50, 300, 400); - Svg2PictureWindow *w = new Svg2PictureWindow(frame, "lion.svg"); - w->Show(); - app->Run(); - - return 0; -}