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