From 3f4cc718ebbb601b4846d8d389f5d345ede5c646 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Tue, 14 Nov 2006 14:15:03 +0000 Subject: [PATCH] Some more updates from Marc Flerackers. Text drawing should work git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19277 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kits/interface/picture/SVGViewView.cpp | 495 +++++++++--------- .../kits/interface/picture/SVGViewView.h | 129 ++++- 2 files changed, 373 insertions(+), 251 deletions(-) diff --git a/src/tests/kits/interface/picture/SVGViewView.cpp b/src/tests/kits/interface/picture/SVGViewView.cpp index f925f6e7f7..3daf810b55 100755 --- a/src/tests/kits/interface/picture/SVGViewView.cpp +++ b/src/tests/kits/interface/picture/SVGViewView.cpp @@ -1,18 +1,15 @@ -#include -#include -#include -#include -#include -#include +/* + * Copyright 2006, Haiku Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Marc Flerackers (mflerackers@androme.be) + */ -#include "Matrix.h" -#include "SVGViewView.h" -struct named_color { - const char *name; - rgb_color color; -}; +#include "SVGViewView.h" + named_color colors[] = { { "aliceblue", { 240, 248, 255, 255 } }, { "antiquewhite", { 250, 235, 215, 255 } }, @@ -164,61 +161,69 @@ named_color colors[] = { { 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, +// Globals --------------------------------------------------------------------- -}; +// Svg2PictureView class ------------------------------------------------------- +Svg2PictureView::Svg2PictureView(BRect frame, const char *filename) + : BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), + fFileName(filename), + fPicture(NULL) +{ + fPicture = new BPicture(); +} + + +Svg2PictureView::~Svg2PictureView() +{ + delete fPicture; +} + + +void +Svg2PictureView::AttachedToWindow() +{ + BeginPicture(fPicture); + + 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); + XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler)_CharacterDataHandler); -struct _state_ { + while (!done) { + char buf[256]; + size_t len = fread(buf, 1, sizeof(buf), file); + done = len < sizeof(buf); + if (!XML_Parse(parser, buf, len, done)) + break; + } - _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; - } + XML_ParserFree(parser); + fclose(file); + } + fPicture = EndPicture(); +} + + +void +Svg2PictureView::Draw(BRect updateRect) +{ + if (fPicture) + DrawPicture(fPicture); +} + - 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) { +//------------------------------------------------------------------------------ +bool Svg2PictureView::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) { +//------------------------------------------------------------------------------ +float Svg2PictureView::GetFloatAttribute(const XML_Char **attributes, const char *name) { while (*attributes && strcasecmp(*attributes, name) != 0) attributes += 2; @@ -227,8 +232,8 @@ float GetFloatAttribute(const XML_Char **attributes, const char *name) { else return 0; } - -const char *GetStringAttribute(const XML_Char **attributes, const char *name) { +//------------------------------------------------------------------------------ +const char *Svg2PictureView::GetStringAttribute(const XML_Char **attributes, const char *name) { while (*attributes && strcasecmp(*attributes, name) != 0) attributes += 2; @@ -237,8 +242,8 @@ const char *GetStringAttribute(const XML_Char **attributes, const char *name) { else return NULL; } - -rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha) { +//------------------------------------------------------------------------------ +rgb_color Svg2PictureView::GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha) { const char *attr = GetStringAttribute(attributes, name); if (!attr) @@ -290,7 +295,7 @@ rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 return color; } - /*if (strcasecmp(attr, "url")) { + if (strcasecmp(attr, "url")) { const char *grad = strchr(attr, '#'); if (grad) { @@ -304,7 +309,7 @@ rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 } } } - }*/ + } for (int32 i = 0; colors[i].name != NULL; i++) if (strcasecmp(colors[i].name, attr) == 0) { @@ -317,8 +322,8 @@ rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 color.alpha = alpha; return color; } - -void GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape) { +//------------------------------------------------------------------------------ +void Svg2PictureView::GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape) { const char *attr = NULL; while (*attributes && strcasecmp(*attributes, name) != 0) @@ -363,8 +368,8 @@ void GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape & ptr++; } } - -void GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix) { +//------------------------------------------------------------------------------ +void Svg2PictureView::GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix) { const char *attr = NULL; while (*attributes && strcasecmp(*attributes, name) != 0) @@ -434,7 +439,7 @@ void GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix * ptr++; } } - +//------------------------------------------------------------------------------ double CalcVectorAngle(double ux, double uy, double vx, double vy) { double ta = atan2(uy, ux); double tb = atan2(vy, vx); @@ -444,7 +449,7 @@ double CalcVectorAngle(double ux, double uy, double vx, double vy) { return 6.28318530718 - (ta - tb); } - +//------------------------------------------------------------------------------ char *SkipFloat(char *string) { if (*string == '-') string++; @@ -453,26 +458,20 @@ char *SkipFloat(char *string) { 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 && strcasecmp(*attributes, name) != 0) - attributes += 2; - - if (*attributes) - attr = *(attributes + 1); +//------------------------------------------------------------------------------ +void Svg2PictureView::GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &shape) { + const char *attr = GetStringAttribute(attributes, name); if (!attr) return; @@ -590,12 +589,16 @@ void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &sh 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); + x1 = GetFloat(&ptr); + y1 = GetFloat(&ptr); + x = GetFloat(&ptr); + y = GetFloat(&ptr); } 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 = GetFloat(&ptr); + y1 = GetFloat(&ptr); + x = GetFloat(&ptr); + y = GetFloat(&ptr); x1 += pos.x; y1 += pos.y; @@ -624,19 +627,25 @@ void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &sh 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); + rx = GetFloat(&ptr); + ry = GetFloat(&ptr); + angle = GetFloat(&ptr); + largeArcFlag = GetFloat(&ptr); + sweepFlag = GetFloat(&ptr); + x = GetFloat(&ptr); + y = GetFloat(&ptr); 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); + rx = GetFloat(&ptr); + ry = GetFloat(&ptr); + angle = GetFloat(&ptr); + largeArcFlag = GetFloat(&ptr); + sweepFlag = GetFloat(&ptr); + x = GetFloat(&ptr); + y = GetFloat(&ptr); x2 = x + pos.x; y2 = y + pos.y; @@ -819,12 +828,12 @@ void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &sh case 't': { if (command == 'T') { - if (sscanf(ptr, "T %f %f", &x, &y) != 2) - sscanf(ptr, "T %f,%f", &x, &y); + x = GetFloat(&ptr); + y = GetFloat(&ptr); } else { - if (sscanf(ptr, "t %f %f", &x, &y) != 2) - sscanf(ptr, "t %f,%f", &x, &y); + x = GetFloat(&ptr); + y = GetFloat(&ptr); x += pos.x; y += pos.y; @@ -859,8 +868,8 @@ void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &sh prevCommand = command; } } - -void CheckAttributes(const XML_Char **attributes, BView *view) { +//------------------------------------------------------------------------------ +void Svg2PictureView::CheckAttributes(const XML_Char **attributes) { uint8 alpha = fState.fStrokeColor.alpha; if (HasAttribute(attributes, "opacity")) { @@ -871,14 +880,22 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { fState.fFlags |= FILL_FLAG; } + if (HasAttribute(attributes, "color")) { + fState.fCurrentColor = GetColorAttribute(attributes, "color", fState.fCurrentColor.alpha); + } + if (HasAttribute(attributes, "stroke")) { const char *stroke = GetStringAttribute(attributes, "stroke"); if (strcasecmp(stroke, "none") == 0) fState.fStroke = false; + else if (strcasecmp(stroke, "currentColor") == 0) { + fState.fStrokeColor = fState.fCurrentColor; + fState.fStroke = true; + } else { fState.fStrokeColor = GetColorAttribute(attributes, "stroke", fState.fFillColor.alpha); fState.fStroke = true; - view->SetHighColor(fState.fStrokeColor); + SetHighColor(fState.fStrokeColor); } fState.fFlags |= STROKE_FLAG; } @@ -892,6 +909,10 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { const char *fill = GetStringAttribute(attributes, "fill"); if (strcasecmp(fill, "none") == 0) fState.fFill = false; + else if (strcasecmp(fill, "currentColor") == 0) { + fState.fFillColor = fState.fCurrentColor; + fState.fFill = true; + } else { fState.fFillColor = GetColorAttribute(attributes, "fill", fState.fFillColor.alpha); fState.fFill = true; @@ -906,7 +927,7 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { if (HasAttribute(attributes, "stroke-width")) { fState.fStrokeWidth = GetFloatAttribute(attributes, "stroke-width"); - view->SetPenSize(fState.fStrokeWidth); + SetPenSize(fState.fStrokeWidth); fState.fFlags |= STROKE_WIDTH_FLAG; } @@ -920,7 +941,7 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { else if (strcasecmp(stroke_linecap, "square") == 0) fState.fLineCap = B_SQUARE_CAP; - view->SetLineMode(fState.fLineCap, view->LineJoinMode(), view->LineMiterLimit()); + SetLineMode(fState.fLineCap, LineJoinMode(), LineMiterLimit()); fState.fFlags |= LINE_MODE_FLAG; } @@ -934,19 +955,19 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { else if (strcasecmp(stroke_linejoin, "bevel") == 0) fState.fLineJoin = B_BEVEL_JOIN; - view->SetLineMode(view->LineCapMode(), fState.fLineJoin, view->LineMiterLimit()); + SetLineMode(LineCapMode(), fState.fLineJoin, 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); + SetLineMode(LineCapMode(), LineJoinMode(), fState.fLineMiterLimit); fState.fFlags |= LINE_MODE_FLAG; } if (HasAttribute(attributes, "font-size")) { fState.fFontSize = GetFloatAttribute(attributes, "font-size"); - view->SetFontSize(fState.fFontSize); + SetFontSize(fState.fFontSize); fState.fFlags |= FONT_SIZE_FLAG; } @@ -957,61 +978,22 @@ void CheckAttributes(const XML_Char **attributes, BView *view) { 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) { +//------------------------------------------------------------------------------ +void Svg2PictureView::StartElement(const XML_Char *name, const XML_Char **attributes) { Push(); - CheckAttributes(attributes, view); + CheckAttributes(attributes); 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); + SetHighColor(fState.fFillColor); + FillEllipse(c, r, r); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeEllipse(c, r, r); + StrokeEllipse(c, r, r); } else if (strcasecmp(name, "ellipse") == 0) { BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); @@ -1019,12 +1001,12 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes float ry = GetFloatAttribute(attributes, "ry"); if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillEllipse(c, rx, ry); - view->SetHighColor(fState.fStrokeColor); + SetHighColor(fState.fFillColor); + FillEllipse(c, rx, ry); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeEllipse(c, rx, ry); + StrokeEllipse(c, rx, ry); } else if (strcasecmp(name, "image") == 0) { BPoint topLeft(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); @@ -1040,7 +1022,7 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes BBitmap *bitmap = BTranslationUtils::GetBitmap(href); if (bitmap) { - view->DrawBitmap(bitmap, BRect(topLeft, bottomRight)); + DrawBitmap(bitmap, BRect(topLeft, bottomRight)); delete bitmap; } } @@ -1052,26 +1034,30 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes fState.fMatrix.Transform(&from); fState.fMatrix.Transform(&to); - view->StrokeLine(from, to); + StrokeLine(from, to); } - /*else if (strcasecmp(name, "linearGradient") == 0) { - named_color *gradient = GetFloatAttribute(element); + else if (strcasecmp(name, "linearGradient") == 0) { + fGradient = new named_gradient; - if (gradient) - fGradients.AddItem(gradient); - }*/ + fGradient->name = strdup(GetStringAttribute(attributes, "id")); + fGradient->color.red = 0; + fGradient->color.green = 0; + fGradient->color.blue = 0; + fGradient->color.alpha = 255; + fGradient->started = false; + } 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); + SetHighColor(fState.fFillColor); + FillShape(&shape); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeShape(&shape); + StrokeShape(&shape); } else if (strcasecmp(name, "polygon") == 0) { BShape shape; @@ -1080,12 +1066,12 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes fState.fMatrix.Transform(shape); if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); + SetHighColor(fState.fFillColor); + FillShape(&shape); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeShape(&shape); + StrokeShape(&shape); } else if (strcasecmp(name, "polyline") == 0) { BShape shape; @@ -1093,12 +1079,37 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes fState.fMatrix.Transform(shape); if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); + SetHighColor(fState.fFillColor); + FillShape(&shape); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeShape(&shape); + StrokeShape(&shape); + } + else if (strcasecmp(name, "radialGradient") == 0) { + fGradient = new named_gradient; + + fGradient->name = strdup(GetStringAttribute(attributes, "id")); + fGradient->color.red = 0; + fGradient->color.green = 0; + fGradient->color.blue = 0; + fGradient->color.alpha = 255; + fGradient->started = false; + } + else if (strcasecmp(name, "stop") == 0) { + rgb_color color = GetColorAttribute(attributes, "stop-color", 255); + + if (fGradient) { + if (fGradient->started) { + fGradient->color.red = (int8)(((int32)fGradient->color.red + (int32)color.red) / 2); + fGradient->color.green = (int8)(((int32)fGradient->color.green + (int32)color.green) / 2); + fGradient->color.blue = (int8)(((int32)fGradient->color.blue + (int32)color.blue) / 2); + } + else { + fGradient->color = color; + fGradient->started = true; + } + } } else if (strcasecmp(name, "rect") == 0) { BPoint points[4]; @@ -1160,83 +1171,97 @@ void startElement(BView *view, const XML_Char *name, const XML_Char **attributes if (fState.fFill) { - view->SetHighColor(fState.fFillColor); - view->FillShape(&shape); - view->SetHighColor(fState.fStrokeColor); + SetHighColor(fState.fFillColor); + FillShape(&shape); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->StrokeShape(&shape); + StrokeShape(&shape); } - /*else if (strcasecmp(name, "text") == 0) { - BPoint point(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); - - fState.fMatrix.Transform(&point); - + else if (strcasecmp(name, "text") == 0) { + fTextPosition.Set(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); + fState.fMatrix.Transform(&fTextPosition); + } +} +//------------------------------------------------------------------------------ +void Svg2PictureView::EndElement(const XML_Char *name) { + if (strcasecmp(name, "linearGradient") == 0) { + if (fGradient) + fGradients.AddItem(fGradient); + fGradient = NULL; + } + else if (strcasecmp(name, "radialGradient") == 0) { + if (fGradient) + fGradients.AddItem(fGradient); + fGradient = NULL; + } + else if (strcasecmp(name, "text") == 0) { 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); + SetHighColor(fState.fFillColor); + DrawString(fText.String(), fTextPosition); + SetHighColor(fState.fStrokeColor); } if (fState.fStroke) - view->DrawString(GetText(element), point); + DrawString(fText.String(), fTextPosition); + printf("%f, %f\n", fTextPosition.x, fTextPosition.y); + } - }*/ + Pop(); } - - -void -endElement(BView *view, const XML_Char *name) -{ - Pop(view); +//------------------------------------------------------------------------------ +void Svg2PictureView::CharacterDataHandler(const XML_Char *s, int len) { + fText.SetTo(s, len); } - - -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; -} - +//------------------------------------------------------------------------------ +void Svg2PictureView::Push() { + _state_ *state = new _state_(fState); -Svg2PictureView::~Svg2PictureView() -{ - delete fPicture; + fStack.AddItem(state); } +//------------------------------------------------------------------------------ +void Svg2PictureView::Pop() { + if (fStack.CountItems() == 0) + printf("Unbalanced Push/Pop\n"); - -void -Svg2PictureView::AttachedToWindow() -{ - BeginPicture(fPicture); - char buf[256]; - bool done = false; - FILE *file = fopen(fFilename.String(), "rb"); + _state_ *state = (_state_*)fStack.LastItem(); - if (file) { - XML_Parser parser = XML_ParserCreate("UTF-8"); - XML_SetUserData(parser, this); - XML_SetElementHandler(parser, (XML_StartElementHandler)startElement, (XML_EndElementHandler)endElement); + if (fState.fFlags & STROKE_FLAG) + { + if (state->fStroke) + SetHighColor(state->fStrokeColor); + } - while (!done) { - size_t len = fread(buf, 1, sizeof(buf), file); - done = len < sizeof(buf); - if (!XML_Parse(parser, buf, len, done)) - break; - } + if (fState.fFlags & FILL_FLAG) + { + if (state->fFill) + SetHighColor(state->fFillColor); + } - XML_ParserFree(parser); - fclose(file); - } + if (fState.fFlags & STROKE_WIDTH_FLAG) + SetPenSize(state->fStrokeWidth); - EndPicture(); + if (fState.fFlags & LINE_MODE_FLAG) + SetLineMode(state->fLineCap, state->fLineJoin, state->fLineMiterLimit); + + if (fState.fFlags & FONT_SIZE_FLAG) + SetFontSize(state->fFontSize); + + fState = *state; + + fStack.RemoveItem(state); + delete state; } - - -void -Svg2PictureView::Draw(BRect updateRect) -{ - DrawPicture(fPicture); +//------------------------------------------------------------------------------ +void Svg2PictureView::_StartElement(Svg2PictureView *view, const XML_Char *name, const XML_Char **attributes) { + view->StartElement(name, attributes); } +//------------------------------------------------------------------------------ +void Svg2PictureView::_EndElement(Svg2PictureView *view, const XML_Char *name) { + view->EndElement(name); +} +//------------------------------------------------------------------------------ +void Svg2PictureView::_CharacterDataHandler(Svg2PictureView *view, const XML_Char *s, int len) { + view->CharacterDataHandler(s, len); +} +//------------------------------------------------------------------------------ diff --git a/src/tests/kits/interface/picture/SVGViewView.h b/src/tests/kits/interface/picture/SVGViewView.h index c279ff825d..b70307da07 100755 --- a/src/tests/kits/interface/picture/SVGViewView.h +++ b/src/tests/kits/interface/picture/SVGViewView.h @@ -1,22 +1,119 @@ -#ifndef _SVG_VIEW_VIEW_H -#define _SVG_VIEW_VIEW_H - -#include -#include +#ifndef _SVGVIEW_VIEW_H +#define _SVGVIEW_VIEW_H +// Standard Includes ----------------------------------------------------------- +#include -class BPicture; -class Svg2PictureView : public BView { -public: - Svg2PictureView(BRect frame, const char *filename); - ~Svg2PictureView(); +// System Includes ------------------------------------------------------------- +#include +#include +#include - virtual void AttachedToWindow(); - virtual void Draw(BRect updateRect); +// Project Includes ------------------------------------------------------------ +#include "Matrix.h" -private: - BString fFilename; - BPicture *fPicture; +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- +struct named_color { + const char *name; + rgb_color color; }; -#endif // _SVG_VIEW_VIEW_H +struct named_gradient { + const char *name; + rgb_color color; + bool started; +}; + +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; + fCurrentColor.red = 0; fCurrentColor.green = 0; + fCurrentColor.blue = 0; fCurrentColor.alpha = 255; + 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 fCurrentColor; + rgb_color fStrokeColor; + bool fStroke; + rgb_color fFillColor; + bool fFill; + float fStrokeWidth; + cap_mode fLineCap; + join_mode fLineJoin; + float fLineMiterLimit; + float fFontSize; + BMatrix fMatrix; +}; + +// Globals --------------------------------------------------------------------- + +// Svg2PictureView class ------------------------------------------------------- +class Svg2PictureView : public BView { + +public: + Svg2PictureView(BRect frame, const char *fileName); + ~Svg2PictureView(); + + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + +private: + bool HasAttribute(const XML_Char **attributes, const char *name); + float GetFloatAttribute(const XML_Char **attributes, const char *name); + const char *GetStringAttribute(const XML_Char **attributes, const char *name); + rgb_color GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha); + void GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape); + void GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix); + void GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &shape); + void CheckAttributes(const XML_Char **attributes); + void StartElement(const XML_Char *name, const XML_Char **attributes); + void EndElement(const XML_Char *name); + void CharacterDataHandler(const XML_Char *s, int len); + + void Push(); + void Pop(); + +static void _StartElement(Svg2PictureView *view, const XML_Char *name, const XML_Char **attributes); +static void _EndElement(Svg2PictureView *view, const XML_Char *name); +static void _CharacterDataHandler(Svg2PictureView *view, const XML_Char *s, int len); + + _state_ fState; + BList fStack; + named_gradient *fGradient; + BList fGradients; + BPoint fTextPosition; + BString fText; + + BString fFileName; + BPicture *fPicture; +}; +//------------------------------------------------------------------------------ + +#endif // _SVGVIEW_VIEW_H