420 def handleShapeDescription(self, shape, list, textOnly=False):
421 if (shape.type() != "KoSvgTextShapeID" and textOnly is True):
422 return
423 shapeDesc = {}
424 shapeDesc["name"] = shape.name()
425 rect = shape.boundingBox()
426 listOfPoints = [rect.topLeft(), rect.topRight(), rect.bottomRight(), rect.bottomLeft()]
427 shapeDesc["boundingBox"] = listOfPoints
428 if (shape.type() == "KoSvgTextShapeID" and textOnly is True):
429 shapeDesc["text"] = shape.toSvg()
430 list.append(shapeDesc)
431 return
432
433 r"""
434 shapeDesc = {}
435 shapeDesc["name"] = shape.name()
436 rect = shape.boundingBox()
437 listOfPoints = [rect.topLeft(), rect.topRight(), rect.bottomRight(), rect.bottomLeft()]
438 shapeDoc = minidom.parseString(shape.toSvg())
439 docElem = shapeDoc.documentElement
440 svgRegExp = re.compile(r'[MLCSQHVATmlzcqshva]\d+\.?\d* \d+\.?\d*')
441 transform = docElem.getAttribute("transform")
442 coord = []
443 adjust = QTransform()
444 # TODO: If we get global transform api, use that instead of parsing manually.
445 if "translate" in transform:
446 transform = transform.replace('translate(', '')
447 for c in transform[:-1].split(" "):
448 if "," in c:
449 c = c.replace(",", "")
450 coord.append(float(c))
451 if len(coord) < 2:
452 coord.append(coord[0])
453 adjust = QTransform(1, 0, 0, 1, coord[0], coord[1])
454 if "matrix" in transform:
455 transform = transform.replace('matrix(', '')
456 for c in transform[:-1].split(" "):
457 if "," in c:
458 c = c.replace(",", "")
459 coord.append(float(c))
460 adjust = QTransform(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5])
461 path = QPainterPath()
462 if docElem.localName == "path":
463 dVal = docElem.getAttribute("d")
464 listOfSvgStrings = [" "]
465 listOfSvgStrings = svgRegExp.findall(dVal)
466 if listOfSvgStrings:
467 listOfPoints = []
468 for l in listOfSvgStrings:
469 line = l[1:]
470 coordinates = line.split(" ")
471 if len(coordinates) < 2:
472 coordinates.append(coordinates[0])
473 x = float(coordinates[-2])
474 y = float(coordinates[-1])
475 offset = QPointF()
476 if l.islower():
477 offset = listOfPoints[0]
478 if l.lower().startswith("m"):
479 path.moveTo(QPointF(x, y) + offset)
480 elif l.lower().startswith("h"):
481 y = listOfPoints[-1].y()
482 path.lineTo(QPointF(x, y) + offset)
483 elif l.lower().startswith("v"):
484 x = listOfPoints[-1].x()
485 path.lineTo(QPointF(x, y) + offset)
486 elif l.lower().startswith("c"):
487 path.cubicTo(coordinates[0], coordinates[1], coordinates[2], coordinates[3], x, y)
488 else:
489 path.lineTo(QPointF(x, y) + offset)
490 path.setFillRule(Qt.FillRule.WindingFill)
491 for polygon in path.simplified().toSubpathPolygons(adjust):
492 for point in polygon:
493 listOfPoints.append(point)
494 elif docElem.localName == "rect":
495 listOfPoints = []
496 if (docElem.hasAttribute("x")):
497 x = float(docElem.getAttribute("x"))
498 else:
499 x = 0
500 if (docElem.hasAttribute("y")):
501 y = float(docElem.getAttribute("y"))
502 else:
503 y = 0
504 w = float(docElem.getAttribute("width"))
505 h = float(docElem.getAttribute("height"))
506 path.addRect(QRectF(x, y, w, h))
507 for point in path.toFillPolygon(adjust):
508 listOfPoints.append(point)
509 elif docElem.localName == "ellipse":
510 listOfPoints = []
511 if (docElem.hasAttribute("cx")):
512 x = float(docElem.getAttribute("cx"))
513 else:
514 x = 0
515 if (docElem.hasAttribute("cy")):
516 y = float(docElem.getAttribute("cy"))
517 else:
518 y = 0
519 ry = float(docElem.getAttribute("ry"))
520 rx = float(docElem.getAttribute("rx"))
521 path.addEllipse(QPointF(x, y), rx, ry)
522 for point in path.toFillPolygon(adjust):
523 listOfPoints.append(point)
524 elif docElem.localName == "text":
525 # NOTE: This only works for horizontal preformated text. Vertical text needs a different
526 # ordering of the rects, and wraparound should try to take the shape it is wrapped in.
527 family = "sans-serif"
528 if docElem.hasAttribute("font-family"):
529 family = docElem.getAttribute("font-family")
530 size = "11"
531 if docElem.hasAttribute("font-size"):
532 size = docElem.getAttribute("font-size")
533 multilineText = True
534 for el in docElem.childNodes:
535 if el.nodeType == minidom.Node.TEXT_NODE:
536 multilineText = False
537 if multilineText:
538 listOfPoints = []
539 listOfRects = []
540
541 # First we collect all the possible line-rects.
542 for el in docElem.childNodes:
543 if docElem.hasAttribute("font-family"):
544 family = docElem.getAttribute("font-family")
545 if docElem.hasAttribute("font-size"):
546 size = docElem.getAttribute("font-size")
547 fontsize = int(size)
548 font = QFont(family, fontsize)
549 string = el.toxml()
550 string = re.sub(r"<.*?>", " ", string)
551 string = string.replace(" ", " ")
552 width = min(QFontMetrics(font).horizontalAdvance(string.strip()), rect.width())
553 height = QFontMetrics(font).height()
554 anchor = "start"
555 if docElem.hasAttribute("text-anchor"):
556 anchor = docElem.getAttribute("text-anchor")
557 top = rect.top()
558 if len(listOfRects)>0:
559 top = listOfRects[-1].bottom()
560 if anchor == "start":
561 spanRect = QRectF(rect.left(), top, width, height)
562 listOfRects.append(spanRect)
563 elif anchor == "end":
564 spanRect = QRectF(rect.right()-width, top, width, height)
565 listOfRects.append(spanRect)
566 else:
567 # Middle
568 spanRect = QRectF(rect.center().x()-(width*0.5), top, width, height)
569 listOfRects.append(spanRect)
570 # Now we have all the rects, we can check each and draw a
571 # polygon around them.
572 heightAdjust = (rect.height()-(listOfRects[-1].bottom()-rect.top()))/len(listOfRects)
573 for i in range(len(listOfRects)):
574 span = listOfRects[i]
575 addtionalHeight = i*heightAdjust
576 if i == 0:
577 listOfPoints.append(span.topLeft())
578 listOfPoints.append(span.topRight())
579 else:
580 if listOfRects[i-1].width()< span.width():
581 listOfPoints.append(QPointF(span.right(), span.top()+addtionalHeight))
582 listOfPoints.insert(0, QPointF(span.left(), span.top()+addtionalHeight))
583 else:
584 bottom = listOfRects[i-1].bottom()+addtionalHeight-heightAdjust
585 listOfPoints.append(QPointF(listOfRects[i-1].right(), bottom))
586 listOfPoints.insert(0, QPointF(listOfRects[i-1].left(), bottom))
587 listOfPoints.append(QPointF(span.right(), rect.bottom()))
588 listOfPoints.insert(0, QPointF(span.left(), rect.bottom()))
589 path = QPainterPath()
590 path.moveTo(listOfPoints[0])
591 for p in range(1, len(listOfPoints)):
592 path.lineTo(listOfPoints[p])
593 path.closeSubpath()
594 listOfPoints = []
595 for point in path.toFillPolygon(adjust):
596 listOfPoints.append(point)
597 shapeDesc["boundingBox"] = listOfPoints
598 if (shape.type() == "KoSvgTextShapeID" and textOnly is True):
599 shapeDesc["text"] = shape.toSvg()
600 list.append(shapeDesc)
601 """
602