1 /* 2 * Copyright 2006, Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 */ 8 9 10 #include "SVGViewView.h" 11 12 13 named_color colors[] = { 14 { "aliceblue", { 240, 248, 255, 255 } }, 15 { "antiquewhite", { 250, 235, 215, 255 } }, 16 { "aqua", { 0, 255, 255, 255 } }, 17 { "aquamarine", { 127, 255, 212, 255 } }, 18 { "azure", { 240, 255, 255, 255 } }, 19 { "beige", { 245, 245, 220, 255 } }, 20 { "bisque", { 255, 228, 196, 255 } }, 21 { "black", { 0, 0, 0, 255 } }, 22 { "blanchedalmond", { 255, 235, 205, 255 } }, 23 { "blue", { 0, 0, 255, 255 } }, 24 { "blueviolet", { 138, 43, 226, 255 } }, 25 { "brown", { 165, 42, 42, 255 } }, 26 { "burlywood", { 222, 184, 135, 255 } }, 27 { "cadetblue", { 95, 158, 160, 255 } }, 28 { "chartreuse", { 127, 255, 0, 255 } }, 29 { "chocolate", { 210, 105, 30, 255 } }, 30 { "coral", { 255, 127, 80, 255 } }, 31 { "cornflowerblue", { 100, 149, 237, 255 } }, 32 { "cornsilk", { 255, 248, 220, 255 } }, 33 { "crimson", { 220, 20, 60, 255 } }, 34 { "cyan", { 0, 255, 255, 255 } }, 35 { "darkblue", { 0, 0, 139, 255 } }, 36 { "darkcyan", { 0, 139, 139, 255 } }, 37 { "darkgoldenrod", { 184, 134, 11, 255 } }, 38 { "darkgray", { 169, 169, 169, 255 } }, 39 { "darkgreen", { 0, 100, 0, 255 } }, 40 { "darkgrey", { 169, 169, 169, 255 } }, 41 { "darkkhaki", { 189, 183, 107, 255 } }, 42 { "darkmagenta", { 139, 0, 139, 255 } }, 43 { "darkolivegreen", { 85, 107, 47, 255 } }, 44 { "darkorange", { 255, 140, 0, 255 } }, 45 { "darkorchid", { 153, 50, 204, 255 } }, 46 { "darkred", { 139, 0, 0, 255 } }, 47 { "darksalmon", { 233, 150, 122, 255 } }, 48 { "darkseagreen", { 143, 188, 143, 255 } }, 49 { "darkslateblue", { 72, 61, 139, 255 } }, 50 { "darkslategray", { 47, 79, 79, 255 } }, 51 { "darkslategrey", { 47, 79, 79, 255 } }, 52 { "darkturquoise", { 0, 206, 209, 255 } }, 53 { "darkviolet", { 148, 0, 211, 255 } }, 54 { "deeppink", { 255, 20, 147, 255 } }, 55 { "deepskyblue", { 0, 191, 255, 255 } }, 56 { "dimgray", { 105, 105, 105, 255 } }, 57 { "dimgrey", { 105, 105, 105, 255 } }, 58 { "dodgerblue", { 30, 144, 255, 255 } }, 59 { "firebrick", { 178, 34, 34, 255 } }, 60 { "floralwhite", { 255, 250, 240, 255 } }, 61 { "forestgreen", { 34, 139, 34, 255 } }, 62 { "fuchsia", { 255, 0, 255, 255 } }, 63 { "gainsboro", { 220, 220, 220, 255 } }, 64 { "ghostwhite", { 248, 248, 255, 255 } }, 65 { "gold", { 255, 215, 0, 255 } }, 66 { "goldenrod", { 218, 165, 32, 255 } }, 67 { "gray", { 128, 128, 128, 255 } }, 68 { "grey", { 128, 128, 128, 255 } }, 69 { "green", { 0, 128, 0, 255 } }, 70 { "greenyellow", { 173, 255, 47, 255 } }, 71 { "honeydew", { 240, 255, 240, 255 } }, 72 { "hotpink", { 255, 105, 180, 255 } }, 73 { "indianred", { 205, 92, 92, 255 } }, 74 { "indigo", { 75, 0, 130, 255 } }, 75 { "ivory", { 255, 255, 240, 255 } }, 76 { "khaki", { 240, 230, 140, 255 } }, 77 { "lavender", { 230, 230, 250, 255 } }, 78 { "lavenderblush", { 255, 240, 245, 255 } }, 79 { "lawngreen", { 124, 252, 0, 255 } }, 80 { "lemonchiffon", { 255, 250, 205, 255 } }, 81 { "lightblue", { 173, 216, 230, 255 } }, 82 { "lightcoral", { 240, 128, 128, 255 } }, 83 { "lightcyan", { 224, 255, 255, 255 } }, 84 { "lightgoldenrodyellow",{ 250, 250, 210, 255 } }, 85 { "lightgray", { 211, 211, 211, 255 } }, 86 { "lightgreen", { 144, 238, 144, 255 } }, 87 { "lightgrey", { 211, 211, 211, 255 } }, 88 { "lightpink", { 255, 182, 193, 255 } }, 89 { "lightsalmon", { 255, 160, 122, 255 } }, 90 { "lightseagreen", { 32, 178, 170, 255 } }, 91 { "lightskyblue", { 135, 206, 250, 255 } }, 92 { "lightslategray", { 119, 136, 153, 255 } }, 93 { "lightslategrey", { 119, 136, 153, 255 } }, 94 { "lightsteelblue", { 176, 196, 222, 255 } }, 95 { "lightyellow", { 255, 255, 224, 255 } }, 96 { "lime", { 0, 255, 0, 255 } }, 97 { "limegreen", { 50, 205, 50, 255 } }, 98 { "linen", { 250, 240, 230, 255 } }, 99 { "magenta", { 255, 0, 255, 255 } }, 100 { "maroon", { 128, 0, 0, 255 } }, 101 { "mediumaquamarine", { 102, 205, 170, 255 } }, 102 { "mediumblue", { 0, 0, 205, 255 } }, 103 { "mediumorchid", { 186, 85, 211, 255 } }, 104 { "mediumpurple", { 147, 112, 219, 255 } }, 105 { "mediumseagreen", { 60, 179, 113, 255 } }, 106 { "mediumslateblue", { 123, 104, 238, 255 } }, 107 { "mediumspringgreen", { 0, 250, 154, 255 } }, 108 { "mediumturquoise", { 72, 209, 204, 255 } }, 109 { "mediumvioletred", { 199, 21, 133, 255 } }, 110 { "midnightblue", { 25, 25, 112, 255 } }, 111 { "mintcream", { 245, 255, 250, 255 } }, 112 { "mistyrose", { 255, 228, 225, 255 } }, 113 { "moccasin", { 255, 228, 181, 255 } }, 114 { "navajowhite", { 255, 222, 173, 255 } }, 115 { "navy", { 0, 0, 128, 255 } }, 116 { "oldlace", { 253, 245, 230, 255 } }, 117 { "olive", { 128, 128, 0, 255 } }, 118 { "olivedrab", { 107, 142, 35, 255 } }, 119 { "orange", { 255, 165, 0, 255 } }, 120 { "orangered", { 255, 69, 0, 255 } }, 121 { "orchid", { 218, 112, 214, 255 } }, 122 { "palegoldenrod", { 238, 232, 170, 255 } }, 123 { "palegreen", { 152, 251, 152, 255 } }, 124 { "paleturquoise", { 175, 238, 238, 255 } }, 125 { "palevioletred", { 219, 112, 147, 255 } }, 126 { "papayawhip", { 255, 239, 213, 255 } }, 127 { "peachpuff", { 255, 218, 185, 255 } }, 128 { "peru", { 205, 133, 63, 255 } }, 129 { "pink", { 255, 192, 203, 255 } }, 130 { "plum", { 221, 160, 221, 255 } }, 131 { "powderblue", { 176, 224, 230, 255 } }, 132 { "purple", { 128, 0, 128, 255 } }, 133 { "red", { 255, 0, 0, 255 } }, 134 { "rosybrown", { 188, 143, 143, 255 } }, 135 { "royalblue", { 65, 105, 225, 255 } }, 136 { "saddlebrown", { 139, 69, 19, 255 } }, 137 { "salmon", { 250, 128, 114, 255 } }, 138 { "sandybrown", { 244, 164, 96, 255 } }, 139 { "seagreen", { 46, 139, 87, 255 } }, 140 { "seashell", { 255, 245, 238, 255 } }, 141 { "sienna", { 160, 82, 45, 255 } }, 142 { "silver", { 192, 192, 192, 255 } }, 143 { "skyblue", { 135, 206, 235, 255 } }, 144 { "slateblue", { 106, 90, 205, 255 } }, 145 { "slategray", { 112, 128, 144, 255 } }, 146 { "slategrey", { 112, 128, 144, 255 } }, 147 { "snow", { 255, 250, 250, 255 } }, 148 { "springgreen", { 0, 255, 127, 255 } }, 149 { "steelblue", { 70, 130, 180, 255 } }, 150 { "tan", { 210, 180, 140, 255 } }, 151 { "teal", { 0, 128, 128, 255 } }, 152 { "thistle", { 216, 191, 216, 255 } }, 153 { "tomato", { 255, 99, 71, 255 } }, 154 { "turquoise", { 64, 224, 208, 255 } }, 155 { "violet", { 238, 130, 238, 255 } }, 156 { "wheat", { 245, 222, 179, 255 } }, 157 { "white", { 255, 255, 255, 255 } }, 158 { "whitesmoke", { 245, 245, 245, 255 } }, 159 { "yellow", { 255, 255, 0, 255 } }, 160 { "yellowgreen", { 154, 205, 50, 255 } }, 161 { NULL , { 0, 0, 0, 255 } }, 162 }; 163 164 // Globals --------------------------------------------------------------------- 165 166 // Svg2PictureView class ------------------------------------------------------- 167 Svg2PictureView::Svg2PictureView(BRect frame, const char *filename) 168 : BView(frame, "", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), 169 fFileName(filename), 170 fPicture(NULL) 171 { 172 fPicture = new BPicture(); 173 } 174 175 176 Svg2PictureView::~Svg2PictureView() 177 { 178 delete fPicture; 179 } 180 181 182 void 183 Svg2PictureView::AttachedToWindow() 184 { 185 BeginPicture(fPicture); 186 187 bool done = false; 188 FILE *file = fopen(fFileName.String(), "rb"); 189 190 if (file) { 191 XML_Parser parser = XML_ParserCreate("UTF-8"); 192 XML_SetUserData(parser, this); 193 XML_SetElementHandler(parser, (XML_StartElementHandler)_StartElement, (XML_EndElementHandler)_EndElement); 194 XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler)_CharacterDataHandler); 195 196 while (!done) { 197 char buf[256]; 198 size_t len = fread(buf, 1, sizeof(buf), file); 199 done = len < sizeof(buf); 200 if (!XML_Parse(parser, buf, len, done)) 201 break; 202 } 203 204 XML_ParserFree(parser); 205 fclose(file); 206 } 207 fPicture = EndPicture(); 208 } 209 210 211 void 212 Svg2PictureView::Draw(BRect updateRect) 213 { 214 if (fPicture) 215 DrawPicture(fPicture); 216 } 217 218 219 //------------------------------------------------------------------------------ 220 bool Svg2PictureView::HasAttribute(const XML_Char **attributes, const char *name) { 221 while (*attributes && strcasecmp(*attributes, name) != 0) 222 attributes += 2; 223 224 return (*attributes); 225 } 226 //------------------------------------------------------------------------------ 227 float Svg2PictureView::GetFloatAttribute(const XML_Char **attributes, const char *name) { 228 while (*attributes && strcasecmp(*attributes, name) != 0) 229 attributes += 2; 230 231 if (*attributes) 232 return atof(*(attributes + 1)); 233 else 234 return 0; 235 } 236 //------------------------------------------------------------------------------ 237 const char *Svg2PictureView::GetStringAttribute(const XML_Char **attributes, const char *name) { 238 while (*attributes && strcasecmp(*attributes, name) != 0) 239 attributes += 2; 240 241 if (*attributes) 242 return *(attributes + 1); 243 else 244 return NULL; 245 } 246 //------------------------------------------------------------------------------ 247 rgb_color Svg2PictureView::GetColorAttribute(const XML_Char **attributes, const char *name, uint8 alpha) { 248 const char *attr = GetStringAttribute(attributes, name); 249 250 if (!attr) 251 return colors[0].color; 252 253 int32 red, green, blue; 254 255 if (attr[0] == '#') { 256 if (strlen(attr) == 4) { 257 sscanf(attr, "#%1X%1X%1X", &red, &green, &blue); 258 red = (red << 4) + red; 259 green = (green << 4) + green; 260 blue = (blue << 4) + blue; 261 } 262 else 263 sscanf(attr, "#%2X%2X%2X", &red, &green, &blue); 264 265 rgb_color color; 266 267 color.red = red; 268 color.green = green; 269 color.blue = blue; 270 color.alpha = alpha; 271 272 return color; 273 } 274 275 if (sscanf(attr, "rgb(%d, %d, %d)", &red, &green, &blue) == 3) { 276 rgb_color color; 277 278 color.red = red; 279 color.green = green; 280 color.blue = blue; 281 color.alpha = alpha; 282 283 return color; 284 } 285 286 float redf, greenf, bluef; 287 288 if (sscanf(attr, "rgb(%f%%, %f%%, %f%%)", &redf, &greenf, &bluef) == 3) { 289 rgb_color color; 290 291 color.red = (int32)(redf * 2.55f); 292 color.green = (int32)(greenf * 2.55f); 293 color.blue = (int32)(bluef * 2.55f); 294 color.alpha = alpha; 295 296 return color; 297 } 298 299 if (strcasecmp(attr, "url")) { 300 const char *grad = strchr(attr, '#'); 301 302 if (grad) { 303 for (int32 i = 0; i < fGradients.CountItems(); i++) { 304 named_color *item = (named_color*)fGradients.ItemAt(i); 305 306 if (strstr(grad, item->name)) { 307 rgb_color color = item->color; 308 color.alpha = alpha; 309 return color; 310 } 311 } 312 } 313 } 314 315 for (int32 i = 0; colors[i].name != NULL; i++) 316 if (strcasecmp(colors[i].name, attr) == 0) { 317 rgb_color color = colors[i].color; 318 color.alpha = alpha; 319 return color; 320 } 321 322 rgb_color color = colors[0].color; 323 color.alpha = alpha; 324 return color; 325 } 326 //------------------------------------------------------------------------------ 327 void Svg2PictureView::GetPolygonAttribute(const XML_Char **attributes, const char *name, BShape &shape) { 328 const char *attr = NULL; 329 330 while (*attributes && strcasecmp(*attributes, name) != 0) 331 attributes += 2; 332 333 if (*attributes) 334 attr = *(attributes + 1); 335 336 if (!attr) 337 return; 338 339 char *ptr = const_cast<char*>(attr); 340 BPoint point; 341 bool first = true; 342 343 while (*ptr) { 344 // Skip white space and ',' 345 while (*ptr && (*ptr == ' ') || (*ptr == ',')) 346 ptr++; 347 348 sscanf(ptr, "%f", &point.x); 349 350 // Skip x 351 while (*ptr && *ptr != ',') 352 ptr++; 353 if (!*ptr || !*(ptr + 1)) 354 break; 355 ptr++; 356 357 sscanf(ptr, "%f", &point.y); 358 359 if (first) 360 { 361 shape.MoveTo(point); 362 first = false; 363 } 364 else 365 shape.LineTo(point); 366 367 // Skip y 368 while (*ptr && (*ptr != ' ') && (*ptr != ',')) 369 ptr++; 370 } 371 } 372 //------------------------------------------------------------------------------ 373 void Svg2PictureView::GetMatrixAttribute(const XML_Char **attributes, const char *name, BMatrix *matrix) { 374 const char *attr = NULL; 375 376 while (*attributes && strcasecmp(*attributes, name) != 0) 377 attributes += 2; 378 379 if (*attributes) 380 attr = *(attributes + 1); 381 382 if (!attr) 383 return; 384 385 char *ptr = (char*)attr; 386 387 while (*ptr) { 388 while (*ptr == ' ') 389 ptr++; 390 391 char *transform_name = ptr; 392 393 while (*ptr != '(') 394 ptr++; 395 396 if (strncmp(transform_name, "translate", 9) == 0) { 397 float x, y; 398 399 if (sscanf(ptr, "(%f %f)", &x, &y) != 2) 400 sscanf(ptr, "(%f,%f)", &x, &y); 401 402 matrix->Translate(x, y); 403 } 404 else if (strncmp(transform_name, "rotate", 6) == 0) { 405 float angle; 406 407 sscanf(ptr, "(%f)", &angle); 408 409 matrix->Rotate(angle); 410 } 411 else if (strncmp(transform_name, "scale", 5) == 0) { 412 float sx, sy; 413 414 if (sscanf(ptr, "(%f,%f)", &sx, &sy) == 2) 415 matrix->Scale(sx, sy); 416 else 417 { 418 sscanf(ptr, "(%f)", &sx); 419 matrix->Scale(sx, sx); 420 } 421 } 422 else if (strncmp(transform_name, "skewX", 5) == 0) { 423 float angle; 424 425 sscanf(ptr, "(%f)", &angle); 426 427 matrix->SkewX(angle); 428 } 429 else if (strncmp(transform_name, "skewY", 5) == 0) { 430 float angle; 431 432 sscanf(ptr, "(%f)", &angle); 433 434 matrix->SkewY(angle); 435 } 436 437 while (*ptr != ')') 438 ptr++; 439 440 ptr++; 441 } 442 } 443 //------------------------------------------------------------------------------ 444 double CalcVectorAngle(double ux, double uy, double vx, double vy) { 445 double ta = atan2(uy, ux); 446 double tb = atan2(vy, vx); 447 448 if (tb >= ta) 449 return tb - ta; 450 451 return 6.28318530718 - (ta - tb); 452 } 453 //------------------------------------------------------------------------------ 454 char *SkipFloat(char *string) { 455 if (*string == '-') 456 string++; 457 458 int32 len = strspn(string, "1234567890."); 459 460 return string + len; 461 } 462 //------------------------------------------------------------------------------ 463 char *FindFloat(char *string) { 464 return strpbrk(string, "1234567890-."); 465 } 466 //------------------------------------------------------------------------------ 467 float GetFloat(char **string) { 468 *string = FindFloat(*string); 469 float f = atof(*string); 470 *string = SkipFloat(*string); 471 return f; 472 } 473 //------------------------------------------------------------------------------ 474 void Svg2PictureView::GetShapeAttribute(const XML_Char **attributes, const char *name, BShape &shape) { 475 const char *attr = GetStringAttribute(attributes, name); 476 477 if (!attr) 478 return; 479 480 char *ptr = const_cast<char*>(attr); 481 float x, y, x1, y1, x2, y2, rx, ry, angle; 482 bool largeArcFlag, sweepFlag; 483 char command, prevCommand = 0; 484 BPoint prevCtlPt; 485 BPoint pos, startPos; 486 bool canMove = true; 487 488 while (*ptr) { 489 ptr = strpbrk(ptr, "ZzMmLlCcQqAaHhVvSsTt"); 490 491 if (ptr == NULL) 492 break; 493 494 command = *ptr; 495 496 switch (command) { 497 case 'Z': 498 case 'z': 499 { 500 pos.Set(startPos.x, startPos.y); 501 canMove = true; 502 shape.Close(); 503 ptr++; 504 break; 505 } 506 case 'M': 507 { 508 x = GetFloat(&ptr); 509 y = GetFloat(&ptr); 510 511 pos.Set(x, y); 512 if (canMove) 513 startPos = pos; 514 shape.MoveTo(pos); 515 break; 516 } 517 case 'm': 518 { 519 x = GetFloat(&ptr); 520 y = GetFloat(&ptr); 521 522 pos.x += x; 523 pos.y += y; 524 if (canMove) 525 startPos = pos; 526 shape.MoveTo(pos); 527 break; 528 } 529 case 'L': 530 { 531 x = GetFloat(&ptr); 532 y = GetFloat(&ptr); 533 534 pos.Set(x, y); 535 canMove = false; 536 shape.LineTo(pos); 537 break; 538 } 539 case 'l': 540 { 541 x = GetFloat(&ptr); 542 y = GetFloat(&ptr); 543 544 pos.x += x; 545 pos.y += y; 546 canMove = false; 547 shape.LineTo(pos); 548 break; 549 } 550 case 'C': 551 case 'c': 552 { 553 if (command == 'C') { 554 x1 = GetFloat(&ptr); 555 y1 = GetFloat(&ptr); 556 x2 = GetFloat(&ptr); 557 y2 = GetFloat(&ptr); 558 x = GetFloat(&ptr); 559 y = GetFloat(&ptr); 560 } 561 else { 562 x1 = GetFloat(&ptr); 563 y1 = GetFloat(&ptr); 564 x2 = GetFloat(&ptr); 565 y2 = GetFloat(&ptr); 566 x = GetFloat(&ptr); 567 y = GetFloat(&ptr); 568 569 x1 += pos.x; 570 y1 += pos.y; 571 x2 += pos.x; 572 y2 += pos.y; 573 x += pos.x; 574 y += pos.y; 575 } 576 577 BPoint controlPoints[3]; 578 579 controlPoints[0].Set(x1, y1); 580 controlPoints[1].Set(x2, y2); 581 controlPoints[2].Set(x, y); 582 583 pos.Set(x, y); 584 prevCtlPt = controlPoints[1]; 585 canMove = false; 586 shape.BezierTo(controlPoints); 587 break; 588 } 589 case 'Q': 590 case 'q': 591 { 592 if (command == 'Q') { 593 x1 = GetFloat(&ptr); 594 y1 = GetFloat(&ptr); 595 x = GetFloat(&ptr); 596 y = GetFloat(&ptr); 597 } 598 else { 599 x1 = GetFloat(&ptr); 600 y1 = GetFloat(&ptr); 601 x = GetFloat(&ptr); 602 y = GetFloat(&ptr); 603 604 x1 += pos.x; 605 y1 += pos.y; 606 x += pos.x; 607 y += pos.y; 608 } 609 610 BPoint controlPoints[3]; 611 612 controlPoints[0].Set(pos.x + 2.0f / 3.0f * (x1 - pos.x), 613 pos.y + 2.0f / 3.0f * (y1 - pos.y)); 614 controlPoints[1].Set(x1 + 1.0f / 3.0f * (x - x1), 615 y1 + 1.0f / 3.0f * (y - y1)); 616 controlPoints[2].Set(x, y); 617 618 pos.Set(x, y); 619 prevCtlPt.Set(x1, y1); 620 canMove = false; 621 shape.BezierTo(controlPoints); 622 break; 623 } 624 case 'A': 625 case 'a': 626 { 627 x1 = pos.x; 628 y1 = pos.y; 629 630 if (command == 'A') { 631 rx = GetFloat(&ptr); 632 ry = GetFloat(&ptr); 633 angle = GetFloat(&ptr); 634 largeArcFlag = GetFloat(&ptr); 635 sweepFlag = GetFloat(&ptr); 636 x = GetFloat(&ptr); 637 y = GetFloat(&ptr); 638 639 x2 = x; 640 y2 = y; 641 } 642 else { 643 rx = GetFloat(&ptr); 644 ry = GetFloat(&ptr); 645 angle = GetFloat(&ptr); 646 largeArcFlag = GetFloat(&ptr); 647 sweepFlag = GetFloat(&ptr); 648 x = GetFloat(&ptr); 649 y = GetFloat(&ptr); 650 651 x2 = x + pos.x; 652 y2 = y + pos.y; 653 } 654 655 const double pi = 3.14159265359; 656 const double radPerDeg = pi / 180.0; 657 658 if (x1 == x2 && y1 == y2) 659 break; 660 661 if (rx == 0.0f || ry == 0.0f) { 662 shape.LineTo(BPoint((float)x2, (float)y2)); 663 break; 664 } 665 666 if (rx < 0.0) 667 rx = -rx; 668 669 if (ry < 0.0) 670 ry = -ry; 671 672 double sinPhi = sin(angle * radPerDeg); 673 double cosPhi = cos(angle * radPerDeg); 674 675 double x1dash = cosPhi * (x1 - x2) / 2.0 + 676 sinPhi * (y1 - y2) / 2.0; 677 double y1dash = -sinPhi * (x1 - x2) / 2.0 + 678 cosPhi * (y1 - y2) / 2.0; 679 680 double root, numerator = rx * rx * ry * ry - rx * rx * y1dash * y1dash - 681 ry * ry * x1dash * x1dash; 682 683 if (numerator < 0.0) { 684 double s = (float)sqrt(1.0 - numerator / (rx * rx * ry * ry)); 685 686 rx *= s; 687 ry *= s; 688 root = 0.0; 689 } 690 else { 691 root = (largeArcFlag == sweepFlag ? -1.0 : 1.0) * 692 sqrt(numerator / 693 (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash)); 694 } 695 696 double cxdash = root * rx * y1dash / ry, cydash = -root * ry * x1dash / rx; 697 698 double cx = cosPhi * cxdash - sinPhi * cydash + (x1 + x2) / 2.0; 699 double cy = sinPhi * cxdash + cosPhi * cydash + (y1 + y2) / 2.0; 700 701 double theta1 = CalcVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, 702 (y1dash - cydash) / ry ), 703 dtheta = CalcVectorAngle((x1dash - cxdash) / rx, 704 (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, 705 (-y1dash - cydash) / ry); 706 707 if (!sweepFlag && dtheta > 0) 708 dtheta -= 2.0 * pi; 709 else if (sweepFlag && dtheta < 0) 710 dtheta += 2.0 * pi; 711 712 int segments = (int)ceil (fabs(dtheta / (pi / 2.0))); 713 double delta = dtheta / segments; 714 double t = 8.0/3.0 * sin(delta / 4.0) * sin( delta / 4.0) / 715 sin(delta / 2.0); 716 717 BPoint controlPoints[3]; 718 719 for (int n = 0; n < segments; ++n) { 720 double cosTheta1 = cos(theta1); 721 double sinTheta1 = sin(theta1); 722 double theta2 = theta1 + delta; 723 double cosTheta2 = cos(theta2); 724 double sinTheta2 = sin(theta2); 725 726 double xe = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx; 727 double ye = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy; 728 729 double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1); 730 double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1); 731 732 double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2); 733 double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2); 734 735 controlPoints[0].Set((float)(x1 + dx1), (float)(y1 + dy1)); 736 controlPoints[1].Set((float)(xe + dxe), (float)(ye + dye)); 737 controlPoints[2].Set((float)xe, (float)ye ); 738 739 shape.BezierTo(controlPoints); 740 741 theta1 = theta2; 742 x1 = (float)xe; 743 y1 = (float)ye; 744 } 745 746 pos.Set(x2, y2); 747 break; 748 } 749 case 'H': 750 { 751 x = GetFloat(&ptr); 752 753 pos.x = x; 754 canMove = false; 755 shape.LineTo(pos); 756 break; 757 } 758 case 'h': 759 { 760 x = GetFloat(&ptr); 761 762 pos.x += x; 763 canMove = false; 764 shape.LineTo(pos); 765 break; 766 } 767 case 'V': 768 { 769 y = GetFloat(&ptr); 770 771 pos.y = y; 772 canMove = false; 773 shape.LineTo(pos); 774 break; 775 } 776 case 'v': 777 { 778 y = GetFloat(&ptr); 779 780 pos.y += y; 781 canMove = false; 782 shape.LineTo(pos); 783 break; 784 } 785 case 'S': 786 case 's': 787 { 788 if (command == 'S') { 789 x2 = GetFloat(&ptr); 790 y2 = GetFloat(&ptr); 791 x = GetFloat(&ptr); 792 y = GetFloat(&ptr); 793 } 794 else { 795 x2 = GetFloat(&ptr); 796 y2 = GetFloat(&ptr); 797 x = GetFloat(&ptr); 798 y = GetFloat(&ptr); 799 800 x2 += pos.x; 801 y2 += pos.y; 802 x += pos.x; 803 y += pos.y; 804 } 805 806 if (prevCommand == 'C' || prevCommand == 'c' || 807 prevCommand == 'S' || prevCommand == 's') { 808 x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); 809 y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); 810 } 811 else { 812 x1 = pos.x; 813 y1 = pos.y; 814 } 815 816 BPoint controlPoints[3]; 817 818 controlPoints[0].Set(x1, y1); 819 controlPoints[1].Set(x2, y2); 820 controlPoints[2].Set(x, y); 821 822 pos.Set(x, y); 823 prevCtlPt.Set(x2, y2); 824 canMove = false; 825 shape.BezierTo(controlPoints); 826 break; 827 } 828 case 'T': 829 case 't': 830 { 831 if (command == 'T') { 832 x = GetFloat(&ptr); 833 y = GetFloat(&ptr); 834 } 835 else { 836 x = GetFloat(&ptr); 837 y = GetFloat(&ptr); 838 839 x += pos.x; 840 y += pos.y; 841 } 842 843 if (prevCommand == 'Q' || prevCommand == 'q' || 844 prevCommand == 'T' || prevCommand == 't') { 845 x1 = prevCtlPt.x + 2 * (pos.x - prevCtlPt.x); 846 y1 = prevCtlPt.y + 2 * (pos.y - prevCtlPt.y); 847 } 848 else { 849 x1 = pos.x; 850 y1 = pos.y; 851 } 852 853 BPoint controlPoints[3]; 854 855 controlPoints[0].Set(pos.x + 2.0f / 3.0f * (x1 - pos.x), 856 pos.y + 2.0f / 3.0f * (y1 - pos.y)); 857 controlPoints[1].Set(x1 + 1.0f / 3.0f * (x - x1), 858 y1 + 1.0f / 3.0f * (y - y1)); 859 controlPoints[2].Set(x, y); 860 861 pos.Set(x, y); 862 prevCtlPt.Set(x1, y1); 863 canMove = false; 864 shape.BezierTo(controlPoints); 865 break; 866 } 867 } 868 869 prevCommand = command; 870 } 871 } 872 //------------------------------------------------------------------------------ 873 void Svg2PictureView::CheckAttributes(const XML_Char **attributes) { 874 uint8 alpha = fState.fStrokeColor.alpha; 875 876 if (HasAttribute(attributes, "opacity")) { 877 float opacity = GetFloatAttribute(attributes, "opacity"); 878 fState.fStrokeColor.alpha = (uint8)(opacity * alpha); 879 fState.fFlags |= STROKE_FLAG; 880 fState.fFillColor.alpha = (uint8)(opacity * alpha); 881 fState.fFlags |= FILL_FLAG; 882 } 883 884 if (HasAttribute(attributes, "color")) { 885 fState.fCurrentColor = GetColorAttribute(attributes, "color", fState.fCurrentColor.alpha); 886 } 887 888 if (HasAttribute(attributes, "stroke")) { 889 const char *stroke = GetStringAttribute(attributes, "stroke"); 890 if (strcasecmp(stroke, "none") == 0) 891 fState.fStroke = false; 892 else if (strcasecmp(stroke, "currentColor") == 0) { 893 fState.fStrokeColor = fState.fCurrentColor; 894 fState.fStroke = true; 895 } 896 else { 897 fState.fStrokeColor = GetColorAttribute(attributes, "stroke", fState.fFillColor.alpha); 898 fState.fStroke = true; 899 SetHighColor(fState.fStrokeColor); 900 } 901 fState.fFlags |= STROKE_FLAG; 902 } 903 904 if (HasAttribute(attributes, "stroke-opacity")) { 905 fState.fStrokeColor.alpha = (uint8)(GetFloatAttribute(attributes, "stroke-opacity") * alpha); 906 fState.fFlags |= STROKE_FLAG; 907 } 908 909 if (HasAttribute(attributes, "fill")) { 910 const char *fill = GetStringAttribute(attributes, "fill"); 911 if (strcasecmp(fill, "none") == 0) 912 fState.fFill = false; 913 else if (strcasecmp(fill, "currentColor") == 0) { 914 fState.fFillColor = fState.fCurrentColor; 915 fState.fFill = true; 916 } 917 else { 918 fState.fFillColor = GetColorAttribute(attributes, "fill", fState.fFillColor.alpha); 919 fState.fFill = true; 920 } 921 fState.fFlags |= FILL_FLAG; 922 } 923 924 if (HasAttribute(attributes, "fill-opacity")) { 925 fState.fFillColor.alpha = (uint8)(GetFloatAttribute(attributes, "fill-opacity") * alpha); 926 fState.fFlags |= FILL_FLAG; 927 } 928 929 if (HasAttribute(attributes, "stroke-width")) { 930 fState.fStrokeWidth = GetFloatAttribute(attributes, "stroke-width"); 931 SetPenSize(fState.fStrokeWidth); 932 fState.fFlags |= STROKE_WIDTH_FLAG; 933 } 934 935 if (HasAttribute(attributes, "stroke-linecap")) { 936 const char *stroke_linecap = GetStringAttribute(attributes, "stroke-linecap"); 937 938 if (strcasecmp(stroke_linecap, "but") == 0) 939 fState.fLineCap = B_BUTT_CAP; 940 else if (strcasecmp(stroke_linecap, "round") == 0) 941 fState.fLineCap = B_ROUND_CAP; 942 else if (strcasecmp(stroke_linecap, "square") == 0) 943 fState.fLineCap = B_SQUARE_CAP; 944 945 SetLineMode(fState.fLineCap, LineJoinMode(), LineMiterLimit()); 946 fState.fFlags |= LINE_MODE_FLAG; 947 } 948 949 if (HasAttribute(attributes, "stroke-linejoin")) { 950 const char *stroke_linejoin = GetStringAttribute(attributes, "stroke-linejoin"); 951 952 if (strcasecmp(stroke_linejoin, "miter") == 0) 953 fState.fLineJoin = B_MITER_JOIN; 954 else if (strcasecmp(stroke_linejoin, "round") == 0) 955 fState.fLineJoin = B_ROUND_JOIN; 956 else if (strcasecmp(stroke_linejoin, "bevel") == 0) 957 fState.fLineJoin = B_BEVEL_JOIN; 958 959 SetLineMode(LineCapMode(), fState.fLineJoin, LineMiterLimit()); 960 fState.fFlags |= LINE_MODE_FLAG; 961 } 962 963 if (HasAttribute(attributes, "stroke-miterlimit")) { 964 fState.fLineMiterLimit = GetFloatAttribute(attributes, "stroke-miterlimit"); 965 SetLineMode(LineCapMode(), LineJoinMode(), fState.fLineMiterLimit); 966 fState.fFlags |= LINE_MODE_FLAG; 967 } 968 969 if (HasAttribute(attributes, "font-size")) { 970 fState.fFontSize = GetFloatAttribute(attributes, "font-size"); 971 SetFontSize(fState.fFontSize); 972 fState.fFlags |= FONT_SIZE_FLAG; 973 } 974 975 if (HasAttribute(attributes, "transform")) { 976 BMatrix matrix; 977 GetMatrixAttribute(attributes, "transform", &matrix); 978 fState.fMatrix *= matrix; 979 fState.fFlags |= MATRIX_FLAG; 980 } 981 } 982 //------------------------------------------------------------------------------ 983 void Svg2PictureView::StartElement(const XML_Char *name, const XML_Char **attributes) { 984 Push(); 985 CheckAttributes(attributes); 986 987 if (strcasecmp(name, "circle") == 0) { 988 BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); 989 float r = GetFloatAttribute(attributes, "r"); 990 991 if (fState.fFill) { 992 SetHighColor(fState.fFillColor); 993 FillEllipse(c, r, r); 994 SetHighColor(fState.fStrokeColor); 995 } 996 if (fState.fStroke) 997 StrokeEllipse(c, r, r); 998 } 999 else if (strcasecmp(name, "ellipse") == 0) { 1000 BPoint c(GetFloatAttribute(attributes, "cx"), GetFloatAttribute(attributes, "cy")); 1001 float rx = GetFloatAttribute(attributes, "rx"); 1002 float ry = GetFloatAttribute(attributes, "ry"); 1003 1004 if (fState.fFill) { 1005 SetHighColor(fState.fFillColor); 1006 FillEllipse(c, rx, ry); 1007 SetHighColor(fState.fStrokeColor); 1008 } 1009 if (fState.fStroke) 1010 StrokeEllipse(c, rx, ry); 1011 } 1012 else if (strcasecmp(name, "image") == 0) { 1013 BPoint topLeft(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); 1014 BPoint bottomRight(topLeft.x + GetFloatAttribute(attributes, "width"), 1015 topLeft.y + GetFloatAttribute(attributes, "height")); 1016 1017 fState.fMatrix.Transform(&topLeft); 1018 fState.fMatrix.Transform(&bottomRight); 1019 1020 const char *href = GetStringAttribute(attributes, "xlink:href"); 1021 1022 if (href) { 1023 BBitmap *bitmap = BTranslationUtils::GetBitmap(href); 1024 1025 if (bitmap) { 1026 DrawBitmap(bitmap, BRect(topLeft, bottomRight)); 1027 delete bitmap; 1028 } 1029 } 1030 } 1031 else if (strcasecmp(name, "line") == 0){ 1032 BPoint from(GetFloatAttribute(attributes, "x1"), GetFloatAttribute(attributes, "y1")); 1033 BPoint to(GetFloatAttribute(attributes, "x2"), GetFloatAttribute(attributes, "y2")); 1034 1035 fState.fMatrix.Transform(&from); 1036 fState.fMatrix.Transform(&to); 1037 1038 StrokeLine(from, to); 1039 } 1040 else if (strcasecmp(name, "linearGradient") == 0) { 1041 fGradient = new named_gradient; 1042 1043 fGradient->name = strdup(GetStringAttribute(attributes, "id")); 1044 fGradient->color.red = 0; 1045 fGradient->color.green = 0; 1046 fGradient->color.blue = 0; 1047 fGradient->color.alpha = 255; 1048 fGradient->started = false; 1049 } 1050 else if (strcasecmp(name, "path") == 0) { 1051 BShape shape; 1052 GetShapeAttribute(attributes, "d", shape); 1053 fState.fMatrix.Transform(shape); 1054 1055 if (fState.fFill) { 1056 SetHighColor(fState.fFillColor); 1057 FillShape(&shape); 1058 SetHighColor(fState.fStrokeColor); 1059 } 1060 if (fState.fStroke) 1061 StrokeShape(&shape); 1062 } 1063 else if (strcasecmp(name, "polygon") == 0) { 1064 BShape shape; 1065 GetPolygonAttribute(attributes, "points", shape); 1066 shape.Close(); 1067 fState.fMatrix.Transform(shape); 1068 1069 if (fState.fFill) { 1070 SetHighColor(fState.fFillColor); 1071 FillShape(&shape); 1072 SetHighColor(fState.fStrokeColor); 1073 } 1074 if (fState.fStroke) 1075 StrokeShape(&shape); 1076 } 1077 else if (strcasecmp(name, "polyline") == 0) { 1078 BShape shape; 1079 GetPolygonAttribute(attributes, "points", shape); 1080 fState.fMatrix.Transform(shape); 1081 1082 if (fState.fFill) { 1083 SetHighColor(fState.fFillColor); 1084 FillShape(&shape); 1085 SetHighColor(fState.fStrokeColor); 1086 } 1087 if (fState.fStroke) 1088 StrokeShape(&shape); 1089 } 1090 else if (strcasecmp(name, "radialGradient") == 0) { 1091 fGradient = new named_gradient; 1092 1093 fGradient->name = strdup(GetStringAttribute(attributes, "id")); 1094 fGradient->color.red = 0; 1095 fGradient->color.green = 0; 1096 fGradient->color.blue = 0; 1097 fGradient->color.alpha = 255; 1098 fGradient->started = false; 1099 } 1100 else if (strcasecmp(name, "stop") == 0) { 1101 rgb_color color = GetColorAttribute(attributes, "stop-color", 255); 1102 1103 if (fGradient) { 1104 if (fGradient->started) { 1105 fGradient->color.red = (int8)(((int32)fGradient->color.red + (int32)color.red) / 2); 1106 fGradient->color.green = (int8)(((int32)fGradient->color.green + (int32)color.green) / 2); 1107 fGradient->color.blue = (int8)(((int32)fGradient->color.blue + (int32)color.blue) / 2); 1108 } 1109 else { 1110 fGradient->color = color; 1111 fGradient->started = true; 1112 } 1113 } 1114 } 1115 else if (strcasecmp(name, "rect") == 0) { 1116 BPoint points[4]; 1117 1118 points[0].x = points[3].x = GetFloatAttribute(attributes, "x"); 1119 points[0].y= points[1].y = GetFloatAttribute(attributes, "y"); 1120 points[1].x = points[2].x = points[0].x + GetFloatAttribute(attributes, "width"); 1121 points[2].y = points[3].y = points[0].y + GetFloatAttribute(attributes, "height"); 1122 1123 /*const char *_rx = element->Attribute("rx"); 1124 const char *_ry = element->Attribute("ry"); 1125 1126 if (_rx || _ry) 1127 { 1128 float rx, ry; 1129 1130 if (_rx) 1131 { 1132 rx = atof(_rx); 1133 1134 if (_ry) 1135 ry = atof(_ry); 1136 else 1137 ry = rx; 1138 } 1139 else 1140 rx = ry = atof(_ry); 1141 1142 if (fState.fFill) 1143 { 1144 SetHighColor(fState.fFillColor); 1145 FillRoundRect(rect, rx, ry); 1146 SetHighColor(fState.fStrokeColor); 1147 } 1148 if (fState.fStroke) 1149 StrokeRoundRect(rect, rx, ry); 1150 } 1151 else 1152 { 1153 if (fState.fFill) 1154 { 1155 SetHighColor(fState.fFillColor); 1156 FillRect(rect); 1157 SetHighColor(fState.fStrokeColor); 1158 } 1159 if (fState.fStroke) 1160 StrokeRect(rect); 1161 }*/ 1162 1163 BShape shape; 1164 1165 shape.MoveTo(points[0]); 1166 shape.LineTo(points[1]); 1167 shape.LineTo(points[2]); 1168 shape.LineTo(points[3]); 1169 shape.Close(); 1170 1171 fState.fMatrix.Transform(shape); 1172 1173 if (fState.fFill) 1174 { 1175 SetHighColor(fState.fFillColor); 1176 FillShape(&shape); 1177 SetHighColor(fState.fStrokeColor); 1178 } 1179 if (fState.fStroke) 1180 StrokeShape(&shape); 1181 } 1182 else if (strcasecmp(name, "text") == 0) { 1183 fTextPosition.Set(GetFloatAttribute(attributes, "x"), GetFloatAttribute(attributes, "y")); 1184 fState.fMatrix.Transform(&fTextPosition); 1185 } 1186 } 1187 //------------------------------------------------------------------------------ 1188 void Svg2PictureView::EndElement(const XML_Char *name) { 1189 if (strcasecmp(name, "linearGradient") == 0) { 1190 if (fGradient) 1191 fGradients.AddItem(fGradient); 1192 fGradient = NULL; 1193 } 1194 else if (strcasecmp(name, "radialGradient") == 0) { 1195 if (fGradient) 1196 fGradients.AddItem(fGradient); 1197 fGradient = NULL; 1198 } 1199 else if (strcasecmp(name, "text") == 0) { 1200 if (fState.fFill) 1201 { 1202 SetHighColor(fState.fFillColor); 1203 DrawString(fText.String(), fTextPosition); 1204 SetHighColor(fState.fStrokeColor); 1205 } 1206 if (fState.fStroke) 1207 DrawString(fText.String(), fTextPosition); 1208 printf("%f, %f\n", fTextPosition.x, fTextPosition.y); 1209 } 1210 1211 Pop(); 1212 } 1213 //------------------------------------------------------------------------------ 1214 void Svg2PictureView::CharacterDataHandler(const XML_Char *s, int len) { 1215 fText.SetTo(s, len); 1216 } 1217 //------------------------------------------------------------------------------ 1218 void Svg2PictureView::Push() { 1219 _state_ *state = new _state_(fState); 1220 1221 fStack.AddItem(state); 1222 } 1223 //------------------------------------------------------------------------------ 1224 void Svg2PictureView::Pop() { 1225 if (fStack.CountItems() == 0) 1226 printf("Unbalanced Push/Pop\n"); 1227 1228 _state_ *state = (_state_*)fStack.LastItem(); 1229 1230 if (fState.fFlags & STROKE_FLAG) 1231 { 1232 if (state->fStroke) 1233 SetHighColor(state->fStrokeColor); 1234 } 1235 1236 if (fState.fFlags & FILL_FLAG) 1237 { 1238 if (state->fFill) 1239 SetHighColor(state->fFillColor); 1240 } 1241 1242 if (fState.fFlags & STROKE_WIDTH_FLAG) 1243 SetPenSize(state->fStrokeWidth); 1244 1245 if (fState.fFlags & LINE_MODE_FLAG) 1246 SetLineMode(state->fLineCap, state->fLineJoin, state->fLineMiterLimit); 1247 1248 if (fState.fFlags & FONT_SIZE_FLAG) 1249 SetFontSize(state->fFontSize); 1250 1251 fState = *state; 1252 1253 fStack.RemoveItem(state); 1254 delete state; 1255 } 1256 //------------------------------------------------------------------------------ 1257 void Svg2PictureView::_StartElement(Svg2PictureView *view, const XML_Char *name, const XML_Char **attributes) { 1258 view->StartElement(name, attributes); 1259 } 1260 //------------------------------------------------------------------------------ 1261 void Svg2PictureView::_EndElement(Svg2PictureView *view, const XML_Char *name) { 1262 view->EndElement(name); 1263 } 1264 //------------------------------------------------------------------------------ 1265 void Svg2PictureView::_CharacterDataHandler(Svg2PictureView *view, const XML_Char *s, int len) { 1266 view->CharacterDataHandler(s, len); 1267 } 1268 //------------------------------------------------------------------------------ 1269