void libcdr::CDRPolygon::create(libcdr::CDRPath &path) const { if (m_numAngles == 0) return; libcdr::CDRPath tmpPath(path); double step = 2*M_PI / (double)m_numAngles; if (m_nextPoint && m_numAngles % m_nextPoint) { libcdr::CDRTransform tmpTrafo(cos(m_nextPoint*step), sin(m_nextPoint*step), 0.0, -sin(m_nextPoint*step), cos(m_nextPoint*step), 0.0); for (unsigned i = 1; i < m_numAngles; ++i) { tmpPath.transform(tmpTrafo); path.appendPath(tmpPath); } } else { libcdr::CDRTransform tmpTrafo(cos(m_nextPoint*step), sin(m_nextPoint*step), 0.0, -sin(m_nextPoint*step), cos(m_nextPoint*step), 0.0); libcdr::CDRTransform tmpShift(cos(step), sin(step), 0.0, -sin(step), cos(step), 0.0); for (unsigned i = 0; i < m_nextPoint; ++i) { if (i) { tmpPath.transform(tmpShift); path.appendPath(tmpPath); } for (unsigned j=1; j < m_numAngles / m_nextPoint; ++j) { tmpPath.transform(tmpTrafo); path.appendPath(tmpPath); } path.appendClosePath(); } } path.appendClosePath(); libcdr::CDRTransform trafo(m_rx, 0.0, m_cx, 0.0, m_ry, m_cy); path.transform(trafo); }
void libcdr::CDRContentCollector::_flushCurrentPath() { CDR_DEBUG_MSG(("CDRContentCollector::_flushCurrentPath\n")); CDROutputElementList outputElement; if (!m_currentPath.empty() || (!m_splineData.empty() && m_isInSpline)) { if (m_polygon && m_isInPolygon) m_polygon->create(m_currentPath); if (m_polygon) { delete m_polygon; m_polygon = 0; } m_isInPolygon = false; if (!m_splineData.empty() && m_isInSpline) m_splineData.create(m_currentPath); m_splineData.clear(); m_isInSpline = false; bool firstPoint = true; bool wasMove = false; double initialX = 0.0; double initialY = 0.0; double previousX = 0.0; double previousY = 0.0; double x = 0.0; double y = 0.0; librevenge::RVNGPropertyList style; _fillProperties(style); _lineProperties(style); outputElement.addStyle(style); m_currentPath.transform(m_currentTransforms); if (!m_groupTransforms.empty()) m_currentPath.transform(m_groupTransforms.top()); CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY); m_currentPath.transform(tmpTrafo); tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height); m_currentPath.transform(tmpTrafo); std::vector<librevenge::RVNGPropertyList> tmpPath; librevenge::RVNGPropertyListVector path; m_currentPath.writeOut(path); bool isPathClosed = m_currentPath.isClosed(); librevenge::RVNGPropertyListVector::Iter i(path); for (i.rewind(); i.next();) { if (!i()["librevenge:path-action"]) continue; if (i()["svg:x"] && i()["svg:y"]) { bool ignoreM = false; x = i()["svg:x"]->getDouble(); y = i()["svg:y"]->getDouble(); if (firstPoint) { initialX = x; initialY = y; firstPoint = false; wasMove = true; } else if (i()["librevenge:path-action"]->getStr() == "M") { // This is needed for a good generation of path from polygon if (CDR_ALMOST_ZERO(previousX - x) && CDR_ALMOST_ZERO(previousY - y)) ignoreM = true; else { if (!tmpPath.empty()) { if (!wasMove) { if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || isPathClosed) { librevenge::RVNGPropertyList node; node.insert("librevenge:path-action", "Z"); tmpPath.push_back(node); } } else tmpPath.pop_back(); } } if (!ignoreM) { initialX = x; initialY = y; wasMove = true; } } else wasMove = false; if (!ignoreM) { tmpPath.push_back(i()); previousX = x; previousY = y; } } else if (i()["librevenge:path-action"]->getStr() == "Z") { if (tmpPath.back()["librevenge:path-action"] && tmpPath.back()["librevenge:path-action"]->getStr() != "Z") tmpPath.push_back(i()); } } if (!tmpPath.empty()) { if (!wasMove) { if ((CDR_ALMOST_ZERO(initialX - previousX) && CDR_ALMOST_ZERO(initialY - previousY)) || isPathClosed) { if (tmpPath.back()["librevenge:path-action"] && tmpPath.back()["librevenge:path-action"]->getStr() != "Z") { librevenge::RVNGPropertyList closedPath; closedPath.insert("librevenge:path-action", "Z"); tmpPath.push_back(closedPath); } } } else tmpPath.pop_back(); } if (!tmpPath.empty()) { librevenge::RVNGPropertyListVector outputPath; for (std::vector<librevenge::RVNGPropertyList>::const_iterator iter = tmpPath.begin(); iter != tmpPath.end(); ++iter) outputPath.append(*iter); librevenge::RVNGPropertyList propList; propList.insert("svg:d", outputPath); outputElement.addPath(propList); } m_currentPath.clear(); } if (m_currentImage.getImage().size()) { double cx = m_currentImage.getMiddleX(); double cy = m_currentImage.getMiddleY(); double corner1x = m_currentImage.m_x1; double corner1y = m_currentImage.m_y1; double corner2x = m_currentImage.m_x1; double corner2y = m_currentImage.m_y2; double corner3x = m_currentImage.m_x2; double corner3y = m_currentImage.m_y2; m_currentTransforms.applyToPoint(cx, cy); m_currentTransforms.applyToPoint(corner1x, corner1y); m_currentTransforms.applyToPoint(corner2x, corner2y); m_currentTransforms.applyToPoint(corner3x, corner3y); if (!m_groupTransforms.empty()) { m_groupTransforms.top().applyToPoint(cx, cy); m_groupTransforms.top().applyToPoint(corner1x, corner1y); m_groupTransforms.top().applyToPoint(corner2x, corner2y); m_groupTransforms.top().applyToPoint(corner3x, corner3y); } CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY); tmpTrafo.applyToPoint(cx, cy); tmpTrafo.applyToPoint(corner1x, corner1y); tmpTrafo.applyToPoint(corner2x, corner2y); tmpTrafo.applyToPoint(corner3x, corner3y); tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height); tmpTrafo.applyToPoint(cx, cy); tmpTrafo.applyToPoint(corner1x, corner1y); tmpTrafo.applyToPoint(corner2x, corner2y); tmpTrafo.applyToPoint(corner3x, corner3y); bool flipX(m_currentTransforms.getFlipX()); bool flipY(m_currentTransforms.getFlipY()); double width = sqrt((corner2x - corner3x)*(corner2x - corner3x) + (corner2y - corner3y)*(corner2y - corner3y)); double height = sqrt((corner2x - corner1x)*(corner2x - corner1x) + (corner2y - corner1y)*(corner2y - corner1y)); double rotate = atan2(corner3y-corner2y, corner3x-corner2x); librevenge::RVNGPropertyList propList; propList.insert("svg:x", cx - width / 2.0); propList.insert("svg:width", width); propList.insert("svg:y", cy - height / 2.0); propList.insert("svg:height", height); if (flipX) { propList.insert("draw:mirror-horizontal", true); rotate = M_PI - rotate; } if (flipY) { propList.insert("draw:mirror-vertical", true); rotate *= -1.0; } while (rotate < 0.0) rotate += 2.0*M_PI; while (rotate > 2.0*M_PI) rotate -= 2.0*M_PI; if (rotate != 0.0) propList.insert("librevenge:rotate", rotate * 180 / M_PI, librevenge::RVNG_GENERIC); propList.insert("librevenge:mime-type", "image/bmp"); propList.insert("office:binary-data", m_currentImage.getImage()); outputElement.addGraphicObject(propList); } if (m_currentText && !m_currentText->empty()) { double x1 = m_currentTextBox.m_x; double y1 = m_currentTextBox.m_y; double x2 = m_currentTextBox.m_x + m_currentTextBox.m_w; double y2 = m_currentTextBox.m_y - m_currentTextBox.m_h; if (!CDR_ALMOST_ZERO(m_currentTextBox.m_h) && !CDR_ALMOST_ZERO(m_currentTextBox.m_w)) { m_currentTransforms.applyToPoint(x1, y1); m_currentTransforms.applyToPoint(x2, y2); if (!m_groupTransforms.empty()) { m_groupTransforms.top().applyToPoint(x1, y1); m_groupTransforms.top().applyToPoint(x2, y2); } } else if (!CDR_ALMOST_ZERO(m_currentBBox.getWidth()) && !CDR_ALMOST_ZERO(m_currentBBox.getHeight())) { y1 = m_currentBBox.getMinY(); y2 = m_currentBBox.getMinY() + m_currentBBox.getHeight(); if ((*m_currentText)[0].m_line[0].m_charStyle.m_align == 2) // Center { x1 = m_currentBBox.getMinX() - m_currentBBox.getWidth() / 4.0; x2 = m_currentBBox.getMinX() + (3.0 * m_currentBBox.getWidth() / 4.0); } else if ((*m_currentText)[0].m_line[0].m_charStyle.m_align == 3) // Right { x1 = m_currentBBox.getMinX() - m_currentBBox.getWidth() / 2.0; x2 = m_currentBBox.getMinX() + m_currentBBox.getWidth() / 2.0; } else { x1 = m_currentBBox.getMinX(); x2 = m_currentBBox.getMinX() + m_currentBBox.getWidth(); } } CDRTransform tmpTrafo(1.0, 0.0, -m_page.offsetX, 0.0, 1.0, -m_page.offsetY); tmpTrafo.applyToPoint(x1, y1); tmpTrafo.applyToPoint(x2, y2); tmpTrafo = CDRTransform(1.0, 0.0, 0.0, 0.0, -1.0, m_page.height); tmpTrafo.applyToPoint(x1, y1); tmpTrafo.applyToPoint(x2, y2); if (x1 > x2) std::swap(x1, x2); if (y1 > y2) std::swap(y1, y2); librevenge::RVNGPropertyList textFrameProps; textFrameProps.insert("svg:width", fabs(x2-x1)); textFrameProps.insert("svg:height", fabs(y2-y1)); textFrameProps.insert("svg:x", x1); textFrameProps.insert("svg:y", y1); textFrameProps.insert("fo:padding-top", 0.0); textFrameProps.insert("fo:padding-bottom", 0.0); textFrameProps.insert("fo:padding-left", 0.0); textFrameProps.insert("fo:padding-right", 0.0); outputElement.addStartTextObject(textFrameProps); for (unsigned i = 0; i < m_currentText->size(); ++i) { const std::vector<CDRText> ¤tLine = (*m_currentText)[i].m_line; if (currentLine.empty()) continue; librevenge::RVNGPropertyList paraProps; bool rtl = false; switch (currentLine[0].m_charStyle.m_align) { case 1: // Left if (!rtl) paraProps.insert("fo:text-align", "left"); else paraProps.insert("fo:text-align", "end"); break; case 2: // Center paraProps.insert("fo:text-align", "center"); break; case 3: // Right if (!rtl) paraProps.insert("fo:text-align", "end"); else paraProps.insert("fo:text-align", "left"); break; case 4: // Full justify paraProps.insert("fo:text-align", "justify"); break; case 5: // Force justify paraProps.insert("fo:text-align", "full"); break; case 0: // None default: break; } outputElement.addOpenParagraph(paraProps); for (unsigned j = 0; j < currentLine.size(); ++j) { if (!currentLine[j].m_text.empty()) { librevenge::RVNGPropertyList spanProps; double fontSize = (double)cdr_round(144.0*currentLine[j].m_charStyle.m_fontSize) / 2.0; spanProps.insert("fo:font-size", fontSize, librevenge::RVNG_POINT); if (currentLine[j].m_charStyle.m_fontName.len()) spanProps.insert("style:font-name", currentLine[j].m_charStyle.m_fontName); if (currentLine[j].m_charStyle.m_fillStyle.fillType != (unsigned short)-1) spanProps.insert("fo:color", m_ps.getRGBColorString(currentLine[j].m_charStyle.m_fillStyle.color1)); outputElement.addOpenSpan(spanProps); outputElement.addInsertText(currentLine[j].m_text); outputElement.addCloseSpan(); } } outputElement.addCloseParagraph(); } outputElement.addEndTextObject(); } m_currentImage = libcdr::CDRImage(); if (!outputElement.empty()) m_outputElements->push(outputElement); m_currentTransforms.clear(); m_fillTransforms = libcdr::CDRTransforms(); m_fillOpacity = 1.0; m_currentText = 0; }