#include "slaoutput.h" #include #include #include "commonstrings.h" #include "loadsaveplugin.h" #include "sccolorengine.h" #include "util.h" #include "util_math.h" SlaOutputDev::SlaOutputDev(ScribusDoc* doc, QList *Elements, QStringList *importedColors, int flags) { m_doc = doc; m_Elements = Elements; m_groupStack.clear(); pushGroup(); m_clipStack.clear(); m_currentMask = ""; m_importedColors = importedColors; CurrColorStroke = "Black"; CurrColorFill = "Black"; Coords = ""; pathIsClosed = false; tmpSel = new Selection(m_doc, false); grStackDepth = 0; firstLayer = true; layerNum = 1; importerFlags = flags; currentLayer = m_doc->activeLayer(); xref = NULL; m_fontEngine = 0; m_font = 0; firstPage = true; pagecount = 1; } SlaOutputDev::~SlaOutputDev() { m_groupStack.clear(); tmpSel->clear(); delete tmpSel; delete m_fontEngine; } void SlaOutputDev::startDoc(XRef *xrefA, Catalog *catA) { xref = xrefA; catalog = catA; firstPage = true; pagecount = 1; m_fontEngine = new SplashFontEngine( #if HAVE_T1LIB_H globalParams->getEnableT1lib(), #endif #if HAVE_FREETYPE_H globalParams->getEnableFreeType(), true, true, #endif true); } void SlaOutputDev::startPage(int pageNum, GfxState *state) { // qDebug() << "starting page" << pageNum; if (firstPage) firstPage = false; else { if (importerFlags & LoadSavePlugin::lfCreateDoc) { m_doc->addPage(pagecount); m_doc->view()->addPage(pagecount, true); pagecount++; } } // qDebug() << "page size =" << pageSize; } void SlaOutputDev::endPage() { // qDebug() << "ending page"; } void SlaOutputDev::saveState(GfxState *state) { // qDebug() << "saveState" << grStackDepth; grStackDepth++; } void SlaOutputDev::restoreState(GfxState *state) { // qDebug() << "restoreState" << grStackDepth; grStackDepth--; if (m_groupStack.count() != 0) m_groupStack.top().maskName = ""; if (m_clipStack.count() != 0) { while (m_clipStack.top().grStackDepth > grStackDepth) { clipEntry clp = m_clipStack.pop(); PageItem *ite = clp.ClipItem; if (m_groupStack.count() != 0) { groupEntry gElements = m_groupStack.pop(); if (gElements.Items.count() > 0) { for (int d = 0; d < gElements.Items.count(); d++) { m_Elements->removeAll(gElements.Items.at(d)); } m_doc->groupObjectsToItem(ite, gElements.Items); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); } else { m_Elements->removeAll(ite); m_doc->Items->removeAll(ite); m_groupStack.top().Items.removeAll(ite); } } if (m_clipStack.count() == 0) break; } } } void SlaOutputDev::updateFillColor(GfxState *state) { int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); } void SlaOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, GfxColorSpace * /*blendingColorSpace*/, GBool /*isolated*/, GBool /*knockout*/, GBool forSoftMask) { // qDebug() << "Start Group"; pushGroup("", forSoftMask); } void SlaOutputDev::endTransparencyGroup(GfxState *state) { // qDebug() << "End Group"; if (m_groupStack.count() != 0) { groupEntry gElements = m_groupStack.pop(); tmpSel->clear(); if (gElements.Items.count() > 0) { for (int dre = 0; dre < gElements.Items.count(); ++dre) { tmpSel->addItem(gElements.Items.at(dre), true); m_Elements->removeAll(gElements.Items.at(dre)); } PageItem *ite = m_doc->groupObjectsSelection(tmpSel); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); if (gElements.forSoftMask) { ScPattern pat = ScPattern(); pat.setDoc(m_doc); m_doc->DoDrawing = true; pat.pattern = ite->DrawObj_toImage(qMax(ite->width(), ite->height())); pat.xoffset = 0; pat.yoffset = 0; m_doc->DoDrawing = false; pat.width = ite->width(); pat.height = ite->height(); pat.items.append(ite); m_doc->Items->removeAll(ite); QString id = QString("Pattern_from_PDF_%1S").arg(m_doc->docPatterns.count() + 1); m_doc->addPattern(id, pat); m_currentMask = id; tmpSel->clear(); return; } else { for (int as = 0; as < tmpSel->count(); ++as) { m_Elements->append(tmpSel->itemAt(as)); } } if (m_groupStack.count() != 0) applyMask(ite); } if (m_groupStack.count() != 0) { for (int as = 0; as < tmpSel->count(); ++as) { m_groupStack.top().Items.append(tmpSel->itemAt(as)); } } tmpSel->clear(); } } void SlaOutputDev::setSoftMask(GfxState * /*state*/, double * /*bbox*/, GBool alpha, Function *transferFunc, GfxColor * /*backdropColor*/) { if (m_groupStack.count() != 0) { double lum = 0; double lum2 = 0; if (transferFunc) transferFunc->transform(&lum, &lum2); else lum2 = lum; if (lum == lum2) m_groupStack.top().inverted = false; else m_groupStack.top().inverted = true; // qDebug() << "Inverted Softmask" << m_groupStack.top().inverted; m_groupStack.top().maskName = m_currentMask; m_groupStack.top().alpha = alpha; } } void SlaOutputDev::clearSoftMask(GfxState * /*state*/) { if (m_groupStack.count() != 0) { m_groupStack.top().maskName = ""; } } void SlaOutputDev::clip(GfxState *state) { // qDebug() << "Clip"; double *ctm; ctm = state->getCTM(); QString output = convertPath(state->getPath()); FPointArray out; out.parseSVG(output); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); out.map(m_ctm); double xmin, ymin, xmax, ymax; state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); int z = m_doc->itemAdd(PageItem::Group, PageItem::Rectangle, crect.x() + m_doc->currentPage()->xOffset(), crect.y() + m_doc->currentPage()->yOffset(), crect.width(), crect.height(), 0, CommonStrings::None, CommonStrings::None, true); PageItem *ite = m_doc->Items->at(z); FPoint wh(getMinClipF(&out)); out.translate(-wh.x(), -wh.y()); ite->PoLine = out.copy(); //FIXME: try to avoid copy if FPointArray when properly shared ite->ClipEdited = true; ite->FrameType = 3; ite->setFillEvenOdd(false); ite->Clip = FlattenPath(ite->PoLine, ite->Segments); ite->ContourLine = ite->PoLine.copy(); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } clipEntry clp; clp.ClipCoords = out.copy(); clp.ClipItem = ite; clp.grStackDepth = grStackDepth; m_clipStack.push(clp); m_doc->GroupCounter++; pushGroup(); } void SlaOutputDev::eoClip(GfxState *state) { // qDebug() << "EoClip"; double *ctm; ctm = state->getCTM(); QString output = convertPath(state->getPath()); FPointArray out; out.parseSVG(output); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); out.map(m_ctm); double xmin, ymin, xmax, ymax; state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); int z = m_doc->itemAdd(PageItem::Group, PageItem::Rectangle, crect.x() + m_doc->currentPage()->xOffset(), crect.y() + m_doc->currentPage()->yOffset(), crect.width(), crect.height(), 0, CommonStrings::None, CommonStrings::None, true); PageItem *ite = m_doc->Items->at(z); FPoint wh(getMinClipF(&out)); out.translate(-wh.x(), -wh.y()); ite->PoLine = out.copy(); //FIXME: try to avoid copy if FPointArray when properly shared ite->ClipEdited = true; ite->FrameType = 3; ite->setFillEvenOdd(true); ite->Clip = FlattenPath(ite->PoLine, ite->Segments); ite->ContourLine = ite->PoLine.copy(); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } clipEntry clp; clp.ClipCoords = out.copy(); clp.ClipItem = ite; clp.grStackDepth = grStackDepth; m_clipStack.push(clp); m_doc->GroupCounter++; pushGroup(); } void SlaOutputDev::stroke(GfxState *state) { // qDebug() << "Stroke"; double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &shade); QString output = convertPath(state->getPath()); getPenState(state); if ((m_Elements->count() != 0) && (output == Coords)) // Path is the same as in last fill { PageItem* ite = m_Elements->at(m_Elements->count()-1); ite->setLineColor(CurrColorStroke); ite->setLineShade(shade); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setLineWidth(state->getTransformedLineWidth()); ite->setDashes(DashValues); ite->setDashOffset(DashOffset); ite->setLineTransparency(1.0 - state->getStrokeOpacity()); } else { FPointArray out; out.parseSVG(output); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); out.map(m_ctm); FPoint wh = out.WidthHeight(); if ((out.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0))) { int z; if (pathIsClosed) z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, CurrColorStroke, true); else z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, state->getTransformedLineWidth(), CommonStrings::None, CurrColorStroke, true); PageItem* ite = m_doc->Items->at(z); ite->PoLine = out.copy(); ite->ClipEdited = true; ite->FrameType = 3; ite->setLineShade(shade); ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ite->setLineBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setDashes(DashValues); ite->setDashOffset(DashOffset); ite->setWidthHeight(wh.x(),wh.y()); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) m_groupStack.top().Items.append(ite); } } } void SlaOutputDev::fill(GfxState *state) { // qDebug() << "Fill"; double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); FPointArray out; QString output = convertPath(state->getPath()); out.parseSVG(output); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); out.map(m_ctm); Coords = output; FPoint wh = out.WidthHeight(); if ((out.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0))) { int z; if (pathIsClosed) z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None, true); else z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->PoLine = out.copy(); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setWidthHeight(wh.x(),wh.y()); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } } } void SlaOutputDev::eoFill(GfxState *state) { // qDebug() << "EoFill"; double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); FPointArray out; QString output = convertPath(state->getPath()); out.parseSVG(output); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); out.map(m_ctm); Coords = output; FPoint wh = out.WidthHeight(); if ((out.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0))) { int z; if (pathIsClosed) z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None, true); else z = m_doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->PoLine = out.copy(); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(true); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setWidthHeight(wh.x(),wh.y()); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } } } GBool SlaOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) { double GrStartX; double GrStartY; double GrEndX; double GrEndY; int shade = 100; Function *func = shading->getFunc(0); VGradient FillGradient = VGradient(VGradient::linear); FillGradient.clearStops(); GfxColorSpace *color_space = shading->getColorSpace(); if (func->getType() == 3) { StitchingFunction *stitchingFunc = (StitchingFunction*)func; double *bounds = stitchingFunc->getBounds(); int num_funcs = stitchingFunc->getNumFuncs(); // Add stops from all the stitched functions for ( int i = 0 ; i < num_funcs ; i++ ) { GfxColor temp; ((GfxAxialShading*)shading)->getColor(bounds[i], &temp); QString stopColor = getColor(color_space, &temp, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor], m_doc), bounds[i], 0.5, 1.0, stopColor, shade ); if (i == num_funcs - 1) { ((GfxAxialShading*)shading)->getColor(bounds[i+1], &temp); QString stopColor = getColor(color_space, &temp, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor], m_doc), bounds[i+1], 0.5, 1.0, stopColor, shade ); } } } else if (func->getType() == 2) { GfxColor stop1; ((GfxAxialShading*)shading)->getColor(0.0, &stop1); QString stopColor1 = getColor(color_space, &stop1, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor1], m_doc), 0.0, 0.5, 1.0, stopColor1, shade ); GfxColor stop2; ((GfxAxialShading*)shading)->getColor(1.0, &stop2); QString stopColor2 = getColor(color_space, &stop2, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor2], m_doc), 1.0, 0.5, 1.0, stopColor2, shade ); } ((GfxAxialShading*)shading)->getCoords(&GrStartX, &GrStartY, &GrEndX, &GrEndY); double xmin, ymin, xmax, ymax; // get the clip region bbox state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); FPointArray gr; gr.addPoint(GrStartX, GrStartY); gr.addPoint(GrEndX, GrEndY); gr.map(m_ctm); GrStartX = gr.point(0).x() - crect.x(); GrStartY = gr.point(0).y() - crect.y(); GrEndX = gr.point(1).x() - crect.x(); GrEndY = gr.point(1).y() - crect.y(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); QString output = QString("M %1 %2").arg(0.0).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(0.0); output += QString("Z"); pathIsClosed = true; Coords = output; int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->GrType = 6; ite->fill_gradient = FillGradient; ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, 0, 0, 1, 0); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } return gTrue; } GBool SlaOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) { double GrStartX; double GrStartY; double GrEndX; double GrEndY; int shade = 100; Function *func = shading->getFunc(0); VGradient FillGradient = VGradient(VGradient::linear); FillGradient.clearStops(); GfxColorSpace *color_space = shading->getColorSpace(); if (func->getType() == 3) { StitchingFunction *stitchingFunc = (StitchingFunction*)func; double *bounds = stitchingFunc->getBounds(); int num_funcs = stitchingFunc->getNumFuncs(); // Add stops from all the stitched functions for ( int i = 0 ; i < num_funcs ; i++ ) { GfxColor temp; ((GfxRadialShading*)shading)->getColor(bounds[i], &temp); QString stopColor = getColor(color_space, &temp, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor], m_doc), bounds[i], 0.5, 1.0, stopColor, shade ); if (i == num_funcs - 1) { ((GfxRadialShading*)shading)->getColor(bounds[i+1], &temp); QString stopColor = getColor(color_space, &temp, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor], m_doc), bounds[i+1], 0.5, 1.0, stopColor, shade ); } } } else if (func->getType() == 2) { GfxColor stop1; ((GfxRadialShading*)shading)->getColor(0.0, &stop1); QString stopColor1 = getColor(color_space, &stop1, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor1], m_doc), 0.0, 0.5, 1.0, stopColor1, shade ); GfxColor stop2; ((GfxRadialShading*)shading)->getColor(1.0, &stop2); QString stopColor2 = getColor(color_space, &stop2, &shade); FillGradient.addStop( ScColorEngine::getRGBColor(m_doc->PageColors[stopColor2], m_doc), 1.0, 0.5, 1.0, stopColor2, shade ); } double r0, x1, y1, r1; ((GfxRadialShading*)shading)->getCoords(&GrStartX, &GrStartY, &r0, &x1, &y1, &r1); double xmin, ymin, xmax, ymax; // get the clip region bbox state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); double GrFocalX = x1; double GrFocalY = y1; GrEndX = GrFocalX + r1; GrEndY = GrFocalY; double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); FPointArray gr; gr.addPoint(GrStartX, GrStartY); gr.addPoint(GrEndX, GrEndY); gr.addPoint(GrFocalX, GrFocalY); gr.map(m_ctm); GrStartX = gr.point(0).x() - crect.x(); GrStartY = gr.point(0).y() - crect.y(); GrEndX = gr.point(1).x() - crect.x(); GrEndY = gr.point(1).y() - crect.y(); GrFocalX = gr.point(2).x() - crect.x(); GrFocalY = gr.point(2).y() - crect.y(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); QString output = QString("M %1 %2").arg(0.0).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(0.0); output += QString("Z"); pathIsClosed = true; Coords = output; int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->GrType = 7; ite->fill_gradient = FillGradient; ite->setGradientVector(GrStartX, GrStartY, GrEndX, GrEndY, GrFocalX, GrFocalY, 1, 0); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } return gTrue; } GBool SlaOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) { double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); double xmin, ymin, xmax, ymax; // get the clip region bbox state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); QString output = QString("M %1 %2").arg(0.0).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(0.0); output += QString("Z"); pathIsClosed = true; Coords = output; double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(100); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } GfxColor color[3]; double x0, y0, x1, y1, x2, y2; for (int i = 0; i < shading->getNTriangles(); i++) { meshGradientPatch patchM; shading->getTriangle(i, &x0, &y0, &color[0], &x1, &y1, &color[1], &x2, &y2, &color[2]); patchM.BL.resetTo(FPoint(x0, y0)); patchM.BL.shade = 100; patchM.BL.transparency = 1.0; patchM.BL.colorName = getColor(shading->getColorSpace(), &color[0], &shade); patchM.BL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BL.colorName], m_doc, shade); patchM.TL.resetTo(FPoint(x1, y1)); patchM.TL.shade = 100; patchM.TL.transparency = 1.0; patchM.TL.colorName = getColor(shading->getColorSpace(), &color[1], &shade); patchM.TL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TL.colorName], m_doc, shade); patchM.TR.resetTo(FPoint(x2, y2)); patchM.TR.shade = 100; patchM.TR.transparency = 1.0; patchM.TR.colorName = getColor(shading->getColorSpace(), &color[2], &shade); patchM.TR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TR.colorName], m_doc, shade); patchM.BR.resetTo(FPoint(x0, y0)); patchM.BR.shade = 100; patchM.BR.transparency = 1.0; patchM.BR.colorName = getColor(shading->getColorSpace(), &color[0], &shade); patchM.BR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BR.colorName], m_doc, shade); patchM.TL.transform(m_ctm); patchM.TL.moveRel(-crect.x(), -crect.y()); patchM.TR.transform(m_ctm); patchM.TR.moveRel(-crect.x(), -crect.y()); patchM.BR.transform(m_ctm); patchM.BR.moveRel(-crect.x(), -crect.y()); patchM.BL.transform(m_ctm); patchM.BL.moveRel(-crect.x(), -crect.y()); ite->meshGradientPatches.append(patchM); } ite->GrType = 12; return gTrue; } GBool SlaOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) { // qDebug() << "mesh shaded fill"; double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); double xmin, ymin, xmax, ymax; // get the clip region bbox state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); QString output = QString("M %1 %2").arg(0.0).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(0.0); output += QString("Z"); pathIsClosed = true; Coords = output; double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } // qDebug() << "Mesh of" << shading->getNPatches() << "Patches"; for (int i = 0; i < shading->getNPatches(); i++) { GfxPatch *patch = shading->getPatch(i); GfxColor color; meshGradientPatch patchM; int u, v; patchM.BL.resetTo(FPoint(patch->x[0][0], patch->y[0][0])); patchM.BL.controlTop = FPoint(patch->x[0][1], patch->y[0][1]); patchM.BL.controlRight = FPoint(patch->x[1][0], patch->y[1][0]); u = 0; v = 0; if (shading->isParameterized()) { shading->getParameterizedColor (patch->color[u][v].c[0], &color); } else { for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) { color.c[k] = GfxColorComp (patch->color[u][v].c[k]); } } patchM.BL.colorName = getColor(shading->getColorSpace(), &color, &shade); patchM.BL.shade = 100; patchM.BL.transparency = 1.0; patchM.BL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BL.colorName], m_doc, shade); u = 0; v = 1; patchM.TL.resetTo(FPoint(patch->x[0][3], patch->y[0][3])); patchM.TL.controlRight = FPoint(patch->x[1][3], patch->y[1][3]); patchM.TL.controlBottom = FPoint(patch->x[0][2], patch->y[0][2]); if (shading->isParameterized()) { shading->getParameterizedColor (patch->color[u][v].c[0], &color); } else { for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) { color.c[k] = GfxColorComp (patch->color[u][v].c[k]); } } patchM.TL.colorName = getColor(shading->getColorSpace(), &color, &shade); patchM.TL.shade = 100; patchM.TL.transparency = 1.0; patchM.TL.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TL.colorName], m_doc, shade); u = 1; v = 1; patchM.TR.resetTo(FPoint(patch->x[3][3], patch->y[3][3])); patchM.TR.controlBottom = FPoint(patch->x[3][2], patch->y[3][2]); patchM.TR.controlLeft = FPoint(patch->x[2][3], patch->y[2][3]); if (shading->isParameterized()) { shading->getParameterizedColor (patch->color[u][v].c[0], &color); } else { for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) { color.c[k] = GfxColorComp (patch->color[u][v].c[k]); } } patchM.TR.colorName = getColor(shading->getColorSpace(), &color, &shade); patchM.TR.shade = 100; patchM.TR.transparency = 1.0; patchM.TR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.TR.colorName], m_doc, shade); u = 1; v = 0; patchM.BR.resetTo(FPoint(patch->x[3][0], patch->y[3][0])); patchM.BR.controlLeft = FPoint(patch->x[2][0], patch->y[2][0]); patchM.BR.controlTop = FPoint(patch->x[3][1], patch->y[3][1]); if (shading->isParameterized()) { shading->getParameterizedColor (patch->color[u][v].c[0], &color); } else { for (int k = 0; k < shading->getColorSpace()->getNComps(); k++) { color.c[k] = GfxColorComp (patch->color[u][v].c[k]); } } patchM.BR.colorName = getColor(shading->getColorSpace(), &color, &shade); patchM.BR.shade = 100; patchM.BR.transparency = 1.0; patchM.BR.color = ScColorEngine::getShadeColorProof(m_doc->PageColors[patchM.BR.colorName], m_doc, shade); patchM.TL.transform(m_ctm); patchM.TL.moveRel(-crect.x(), -crect.y()); patchM.TR.transform(m_ctm); patchM.TR.moveRel(-crect.x(), -crect.y()); patchM.BR.transform(m_ctm); patchM.BR.moveRel(-crect.x(), -crect.y()); patchM.BL.transform(m_ctm); patchM.BL.moveRel(-crect.x(), -crect.y()); ite->meshGradientPatches.append(patchM); } ite->GrType = 12; return gTrue; } GBool SlaOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *str, double *pmat, int paintType, Dict *resDict, double *mat, double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep) { PDFRectangle box; Gfx *gfx; QString id; PageItem *ite; groupEntry gElements; gElements.forSoftMask = gFalse; gElements.alpha = gFalse; gElements.inverted = false; gElements.maskName = ""; gElements.Items.clear(); m_groupStack.push(gElements); double width, height; width = bbox[2] - bbox[0]; height = bbox[3] - bbox[1]; if (xStep != width || yStep != height) return gFalse; box.x1 = bbox[0]; box.y1 = bbox[1]; box.x2 = bbox[2]; box.y2 = bbox[3]; double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); QTransform mm = QTransform(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); QTransform mmx = mm * m_ctm; gfx = new Gfx(xref, this, resDict, catalog, &box, NULL); gfx->display(str); gElements = m_groupStack.pop(); tmpSel->clear(); double pwidth = 0; double pheight = 0; if (gElements.Items.count() > 0) { for (int dre = 0; dre < gElements.Items.count(); ++dre) { tmpSel->addItem(gElements.Items.at(dre), true); m_Elements->removeAll(gElements.Items.at(dre)); } ite = m_doc->groupObjectsSelection(tmpSel); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); m_doc->m_Selection->addItem(ite, true); m_doc->itemSelection_FlipV(); m_doc->m_Selection->clear(); ScPattern pat = ScPattern(); pat.setDoc(m_doc); m_doc->DoDrawing = true; pat.pattern = ite->DrawObj_toImage(qMax(ite->width(), ite->height())); pat.xoffset = 0; pat.yoffset = 0; m_doc->DoDrawing = false; pat.width = ite->width(); pat.height = ite->height(); pwidth = ite->width(); pheight = ite->height(); pat.items.append(ite); m_doc->Items->removeAll(ite); id = QString("Pattern_from_PDF_%1").arg(m_doc->docPatterns.count() + 1); m_doc->addPattern(id, pat); tmpSel->clear(); } double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); double xmin, ymin, xmax, ymax; // get the clip region bbox state->getClipBBox(&xmin, &ymin, &xmax, &ymax); QRectF crect = QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax)); crect = crect.normalized(); QString output = QString("M %1 %2").arg(0.0).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(0.0); output += QString("L %1 %2").arg(crect.width()).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(crect.height()); output += QString("L %1 %2").arg(0.0).arg(0.0); output += QString("Z"); pathIsClosed = true; Coords = output; int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + crect.x(), yCoor + crect.y(), crect.width(), crect.height(), 0, CurrColorFill, CommonStrings::None, true); ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->GrType = 8; ite->setPattern(id); ite->setPatternTransform(fabs(pmat[0]) * 100, fabs(pmat[3]) * 100, mmx.dx() - ctm[4], mmx.dy() - ctm[5], 0, -1 * pmat[1], pmat[2]); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } delete gfx; return gTrue; } void SlaOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool interpolate, GBool inlineImg) { // qDebug() << "Draw Image Mask"; QImage * image = 0; int invert_bit; int row_stride; int x, y, i, bit; unsigned char *dest = 0; unsigned char *buffer; Guchar *pix; ImageStream * imgStr = new ImageStream(str, width, 1, 1); imgStr->reset(); #ifdef WORDS_BIGENDIAN image = new QImage(width, height, QImage::Format_Mono); #else image = new QImage(width, height, QImage::Format_MonoLSB); #endif invert_bit = invert ? 1 : 0; buffer = image->bits(); row_stride = image->bytesPerLine(); for (y = 0; y < height; y++) { pix = imgStr->getLine(); dest = buffer + y * row_stride; i = 0; bit = 0; for (x = 0; x < width; x++) { if (bit == 0) dest[i] = 0; if (!(pix[x] ^ invert_bit)) { #ifdef WORDS_BIGENDIAN dest[i] |= (1 << (7 - bit)); #else dest[i] |= (1 << bit); #endif } bit++; if (bit > 7) { bit = 0; i++; } } } QImage res = image->convertToFormat(QImage::Format_ARGB32); double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); QRectF crect = QRectF(0, 0, width, height); m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]); QLineF cline = QLineF(0, 0, width, 0); QLineF tline = m_ctm.map(cline); QRectF trect = m_ctm.mapRect(crect); double sx = m_ctm.m11(); double sy = m_ctm.m22(); QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0); if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate)) { mm.reset(); mm.rotate(-tline.angle()); } else { mm.reset(); if (sx < 0) mm.scale(-1, 1); if (sy < 0) mm.scale(1, -1); } QImage img = res.transformed(mm); int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->SetRectFrame(); m_doc->setRedrawBounding(ite); ite->Clip = FlattenPath(ite->PoLine, ite->Segments); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->setFillShade(100); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png"); ite->tempImageFile->open(); QString fileName = getLongPathName(ite->tempImageFile->fileName()); ite->tempImageFile->close(); ite->isInlineImage = true; img.save(fileName, "PNG"); m_doc->LoadPict(fileName, z); ite->setImageScalingMode(false, true); m_doc->AdjustItemSize(ite); // Now creating patttern out of the image; ScPattern pat = ScPattern(); pat.setDoc(m_doc); m_doc->DoDrawing = true; pat.pattern = ite->DrawObj_toImage(qMax(ite->width(), ite->height())); pat.xoffset = 0; pat.yoffset = 0; m_doc->DoDrawing = false; pat.width = pat.pattern.width(); pat.height = pat.pattern.height(); pat.items.append(ite); m_doc->Items->removeAll(ite); QString id = QString("Pattern_from_PDF_%1M").arg(m_doc->docPatterns.count() + 1); m_doc->addPattern(id, pat); // create the real item int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); z = m_doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CurrColorFill, CommonStrings::None, true); ite = m_doc->Items->at(z); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->setPatternMask(id); ite->setMaskTransform(ite->width() / pat.width * 100, ite->height() / pat.height * 100, 0, 0, 0, 0, 0); ite->setMaskType(6); m_Elements->append(ite); if (m_groupStack.count() != 0) m_groupStack.top().Items.append(ite); imgStr->close(); delete imgStr; delete image; } void SlaOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, Stream *maskStr, int maskWidth, int maskHeight, GfxImageColorMap *maskColorMap, GBool maskInterpolate) { ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); imgStr->reset(); unsigned int *dest = 0; unsigned char * buffer = new unsigned char[width * height * 4]; QImage * image = 0; for (int y = 0; y < height; y++) { dest = (unsigned int *)(buffer + y * 4 * width); Guchar * pix = imgStr->getLine(); colorMap->getRGBLine(pix, dest, width); } image = new QImage(buffer, width, height, QImage::Format_RGB32); if (image == NULL || image->isNull()) { delete imgStr; delete[] buffer; delete image; return; } ImageStream *mskStr = new ImageStream(maskStr, maskWidth, maskColorMap->getNumPixelComps(), maskColorMap->getBits()); mskStr->reset(); Guchar *mdest = 0; unsigned char * mbuffer = new unsigned char[maskWidth * maskHeight]; for (int y = 0; y < maskHeight; y++) { mdest = (Guchar *)(mbuffer + y * maskWidth); Guchar * pix = mskStr->getLine(); maskColorMap->getGrayLine(pix, mdest, maskWidth); } if ((maskWidth != width) || (maskHeight != height)) { delete imgStr; delete[] buffer; delete image; delete mskStr; delete[] mbuffer; return; } QImage res = image->convertToFormat(QImage::Format_ARGB32); unsigned char cc, cm, cy, ck; int s = 0; for( int yi=0; yi < res.height(); ++yi ) { QRgb *t = (QRgb*)(res.scanLine( yi )); for(int xi=0; xi < res.width(); ++xi ) { cc = qRed(*t); cm = qGreen(*t); cy = qBlue(*t); ck = mbuffer[s]; (*t) = qRgba(cc, cm, cy, ck); s++; t++; } } double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); QRectF crect = QRectF(0, 0, width, height); m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]); QLineF cline = QLineF(0, 0, width, 0); QLineF tline = m_ctm.map(cline); QRectF trect = m_ctm.mapRect(crect); double sx = m_ctm.m11(); double sy = m_ctm.m22(); QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0); if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate)) { mm.reset(); mm.rotate(-tline.angle()); } else { mm.reset(); if (sx < 0) mm.scale(-1, 1); if (sy < 0) mm.scale(1, -1); } QImage img = res.transformed(mm); int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->SetRectFrame(); m_doc->setRedrawBounding(ite); ite->Clip = FlattenPath(ite->PoLine, ite->Segments); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->setFillShade(100); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png"); ite->tempImageFile->open(); QString fileName = getLongPathName(ite->tempImageFile->fileName()); ite->tempImageFile->close(); ite->isInlineImage = true; img.save(fileName, "PNG"); m_doc->LoadPict(fileName, z); ite->setImageScalingMode(false, true); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } delete imgStr; delete[] buffer; delete image; delete mskStr; delete[] mbuffer; } void SlaOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool interpolate, int *maskColors, GBool inlineImg) { ImageStream * imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(), colorMap->getBits()); imgStr->reset(); unsigned int *dest = 0; unsigned char * buffer = new unsigned char[width * height * 4]; QImage * image = 0; if (maskColors) { for (int y = 0; y < height; y++) { dest = (unsigned int *)(buffer + y * 4 * width); Guchar * pix = imgStr->getLine(); colorMap->getRGBLine(pix, dest, width); for (int x = 0; x < width; x++) { for (int i = 0; i < colorMap->getNumPixelComps(); ++i) { if (pix[i] < maskColors[2*i] * 255 || pix[i] > maskColors[2*i+1] * 255) { *dest = *dest | 0xff000000; break; } } pix += colorMap->getNumPixelComps(); dest++; } } image = new QImage(buffer, width, height, QImage::Format_ARGB32); } else { for (int y = 0; y < height; y++) { dest = (unsigned int *)(buffer + y * 4 * width); Guchar * pix = imgStr->getLine(); colorMap->getRGBLine(pix, dest, width); } image = new QImage(buffer, width, height, QImage::Format_RGB32); } if (image == NULL || image->isNull()) { delete imgStr; delete[] buffer; delete image; return; } double *ctm; ctm = state->getCTM(); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); QRectF crect = QRectF(0, 0, width, height); m_ctm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, ctm[2] + ctm[4], ctm[3] + ctm[5]); QLineF cline = QLineF(0, 0, width, 0); QLineF tline = m_ctm.map(cline); QRectF trect = m_ctm.mapRect(crect); double sx = m_ctm.m11(); double sy = m_ctm.m22(); QTransform mm = QTransform(ctm[0] / width, ctm[1] / width, -ctm[2] / height, -ctm[3] / height, 0, 0); if ((mm.type() == QTransform::TxShear) || (mm.type() == QTransform::TxRotate)) { mm.reset(); mm.rotate(-tline.angle()); } else { mm.reset(); if (sx < 0) mm.scale(-1, 1); if (sy < 0) mm.scale(1, -1); } QImage img = image->transformed(mm); int z = m_doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, xCoor + trect.x(), yCoor + trect.y(), trect.width(), trect.height(), 0, CommonStrings::None, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); ite->SetRectFrame(); m_doc->setRedrawBounding(ite); ite->Clip = FlattenPath(ite->PoLine, ite->Segments); ite->setTextFlowMode(PageItem::TextFlowDisabled); ite->setFillShade(100); ite->setLineShade(100); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_pdf_XXXXXX.png"); ite->tempImageFile->open(); QString fileName = getLongPathName(ite->tempImageFile->fileName()); ite->tempImageFile->close(); ite->isInlineImage = true; img.save(fileName, "PNG"); m_doc->LoadPict(fileName, z); ite->setImageScalingMode(false, true); m_doc->AdjustItemSize(ite); m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } delete imgStr; delete[] buffer; delete image; } void SlaOutputDev::beginMarkedContent(char *name, Dict *properties) { // qDebug() << "Begin Marked Content with Name " << QString(name); if (importerFlags & LoadSavePlugin::lfCreateDoc) { if (QString(name) == "Layer") // Handle Adobe Illustrator Layer command { layerNum++; if (!firstLayer) currentLayer = m_doc->addLayer(QString("Layer_%1").arg(layerNum), true); firstLayer = false; Object obj; if (properties->lookup((char*)"Title", &obj)) { if (obj.isString()) { QString lName = QString(obj.getString()->getCString()); m_doc->changeLayerName(currentLayer, lName); } obj.free(); } if (properties->lookup((char*)"Visible", &obj)) { if (obj.isBool()) m_doc->setLayerVisible(currentLayer, obj.getBool()); obj.free(); } if (properties->lookup((char*)"Editable", &obj)) { if (obj.isBool()) m_doc->setLayerLocked(currentLayer, !obj.getBool()); obj.free(); } if (properties->lookup((char*)"Printed", &obj)) { if (obj.isBool()) m_doc->setLayerPrintable(currentLayer, obj.getBool()); obj.free(); } if (properties->lookup((char*)"Color", &obj)) { if (obj.isArray()) { Object obj1; obj.arrayGet(0, &obj1); int r = obj1.getNum() / 256; obj1.free(); obj.arrayGet(1, &obj1); int g = obj1.getNum() / 256; obj1.free(); obj.arrayGet(2, &obj1); int b = obj1.getNum() / 256; obj1.free(); m_doc->setLayerMarker(currentLayer, QColor(r, g, b)); } obj.free(); } } } } void SlaOutputDev::endMarkedContent(GfxState *state) { // qDebug() << "End Marked Content"; } void SlaOutputDev::updateFont(GfxState *state) { GfxFont *gfxFont; GfxFontType fontType; SplashOutFontFileID *id; SplashFontFile *fontFile; SplashFontSrc *fontsrc = NULL; FoFiTrueType *ff; Ref embRef; Object refObj, strObj; GooString *fileName; char *tmpBuf; int tmpBufLen; Gushort *codeToGID; DisplayFontParam *dfp; double *textMat; double m11, m12, m21, m22, fontSize; SplashCoord mat[4]; int n; int faceIndex = 0; SplashCoord matrix[6]; m_font = NULL; fileName = NULL; tmpBuf = NULL; if (!(gfxFont = state->getFont())) goto err1; fontType = gfxFont->getType(); if (fontType == fontType3) goto err1; // check the font file cache id = new SplashOutFontFileID(gfxFont->getID()); if ((fontFile = m_fontEngine->getFontFile(id))) { delete id; } else { // if there is an embedded font, write it to disk if (gfxFont->getEmbeddedFontID(&embRef)) { tmpBuf = gfxFont->readEmbFontFile(xref, &tmpBufLen); if (!tmpBuf) goto err2; // if there is an external font file, use it } else if (!(fileName = gfxFont->getExtFontFile())) { // look for a display font mapping or a substitute font dfp = NULL; if (gfxFont->getName()) { dfp = globalParams->getDisplayFont(gfxFont); } if (!dfp) { // error(-1, "Couldn't find a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } switch (dfp->kind) { case displayFontT1: fileName = dfp->t1.fileName; fontType = gfxFont->isCIDFont() ? fontCIDType0 : fontType1; break; case displayFontTT: fileName = dfp->tt.fileName; fontType = gfxFont->isCIDFont() ? fontCIDType2 : fontTrueType; faceIndex = dfp->tt.faceIndex; break; } } fontsrc = new SplashFontSrc; if (fileName) fontsrc->setFile(fileName, gFalse); else fontsrc->setBuf(tmpBuf, tmpBufLen, gTrue); // load the font file switch (fontType) { case fontType1: if (!(fontFile = m_fontEngine->loadType1Font( id, fontsrc, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontType1C: if (!(fontFile = m_fontEngine->loadType1CFont( id, fontsrc, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontType1COT: if (!(fontFile = m_fontEngine->loadOpenTypeT1CFont( id, fontsrc, ((Gfx8BitFont *)gfxFont)->getEncoding()))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontTrueType: case fontTrueTypeOT: if (fileName) ff = FoFiTrueType::load(fileName->getCString()); else ff = FoFiTrueType::make(tmpBuf, tmpBufLen); if (ff) { codeToGID = ((Gfx8BitFont *)gfxFont)->getCodeToGIDMap(ff); n = 256; delete ff; } else { codeToGID = NULL; n = 0; } if (!(fontFile = m_fontEngine->loadTrueTypeFont( id, fontsrc, codeToGID, n))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType0: case fontCIDType0C: if (!(fontFile = m_fontEngine->loadCIDFont( id, fontsrc))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType0COT: if (!(fontFile = m_fontEngine->loadOpenTypeCFFFont( id, fontsrc))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; case fontCIDType2: case fontCIDType2OT: codeToGID = NULL; n = 0; if (((GfxCIDFont *)gfxFont)->getCIDToGID()) { n = ((GfxCIDFont *)gfxFont)->getCIDToGIDLen(); if (n) { codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort)); memcpy(codeToGID, ((GfxCIDFont *)gfxFont)->getCIDToGID(), n * sizeof(Gushort)); } } else { if (fileName) ff = FoFiTrueType::load(fileName->getCString()); else ff = FoFiTrueType::make(tmpBuf, tmpBufLen); if (!ff) goto err2; codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); delete ff; } if (!(fontFile = m_fontEngine->loadTrueTypeFont( id, fontsrc, codeToGID, n, faceIndex))) { // error(-1, "Couldn't create a font for '%s'", gfxFont->getName() ? gfxFont->getName()->getCString() : "(unnamed)"); goto err2; } break; default: // this shouldn't happen goto err2; } } // get the font matrix textMat = state->getTextMat(); fontSize = state->getFontSize(); m11 = textMat[0] * fontSize * state->getHorizScaling(); m12 = textMat[1] * fontSize * state->getHorizScaling(); m21 = textMat[2] * fontSize; m22 = textMat[3] * fontSize; matrix[0] = 1; matrix[1] = 0; matrix[2] = 0; matrix[3] = 1; matrix[4] = 0; matrix[5] = 0; // create the scaled font mat[0] = m11; mat[1] = -m12; mat[2] = m21; mat[3] = -m22; m_font = m_fontEngine->getFont(fontFile, mat, matrix); if (fontsrc && !fontsrc->isFile) fontsrc->unref(); return; err2: delete id; err1: if (fontsrc && !fontsrc->isFile) fontsrc->unref(); return; } void SlaOutputDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, int nBytes, Unicode *u, int uLen) { double x1, y1, x2, y2; int render; updateFont(state); if (!m_font) return; // check for invisible text -- this is used by Acrobat Capture render = state->getRender(); if (render == 3) return; if (!(render & 1)) { SplashPath * fontPath; fontPath = m_font->getGlyphPath(code); if (fontPath) { QPainterPath qPath; qPath.setFillRule(Qt::WindingFill); for (int i = 0; i < fontPath->getLength(); ++i) { Guchar f; fontPath->getPoint(i, &x1, &y1, &f); if (f & splashPathFirst) qPath.moveTo(x1,y1); else if (f & splashPathCurve) { double x3, y3; ++i; fontPath->getPoint(i, &x2, &y2, &f); ++i; fontPath->getPoint(i, &x3, &y3, &f); qPath.cubicTo(x1,y1,x2,y2,x3,y3); } else qPath.lineTo(x1,y1); if (f & splashPathLast) qPath.closeSubpath(); } double *ctm; ctm = state->getCTM(); m_ctm = QTransform(ctm[0], ctm[1], ctm[2], ctm[3], ctm[4], ctm[5]); double xCoor = m_doc->currentPage()->xOffset(); double yCoor = m_doc->currentPage()->yOffset(); int shade = 100; CurrColorFill = getColor(state->getFillColorSpace(), state->getFillColor(), &shade); FPointArray textPath; textPath.fromQPainterPath(qPath); FPoint wh = textPath.WidthHeight(); if ((textPath.size() > 3) && ((wh.x() != 0.0) || (wh.y() != 0.0))) { int z = m_doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, xCoor, yCoor, 10, 10, 0, CurrColorFill, CommonStrings::None, true); PageItem* ite = m_doc->Items->at(z); FPoint tp2(getMinClipF(&textPath)); QTransform mm; mm.scale(1, -1); mm.translate(x, -y); textPath.map(mm); textPath.map(m_ctm); ite->PoLine = textPath.copy(); ite->ClipEdited = true; ite->FrameType = 3; ite->setFillShade(shade); ite->setFillEvenOdd(false); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); ite->setLineEnd(PLineEnd); ite->setLineJoin(PLineJoin); ite->setTextFlowMode(PageItem::TextFlowDisabled); m_doc->AdjustItemSize(ite); if ((render & 3) == 1 || (render & 3) == 2) { CurrColorStroke = getColor(state->getStrokeColorSpace(), state->getStrokeColor(), &shade); ite->setLineColor(CurrColorStroke); ite->setLineWidth(state->getTransformedLineWidth()); ite->setLineTransparency(1.0 - state->getStrokeOpacity()); ite->setLineBlendmode(getBlendMode(state)); ite->setLineShade(shade); } m_Elements->append(ite); if (m_groupStack.count() != 0) { m_groupStack.top().Items.append(ite); applyMask(ite); } delete fontPath; } } } } void SlaOutputDev::beginTextObject(GfxState *state) { // qDebug() << "Begin Text Object"; pushGroup(); } void SlaOutputDev::endTextObject(GfxState *state) { // qDebug() << "End Text Object"; if (m_groupStack.count() != 0) { groupEntry gElements = m_groupStack.pop(); tmpSel->clear(); if (gElements.Items.count() > 0) { for (int dre = 0; dre < gElements.Items.count(); ++dre) { tmpSel->addItem(gElements.Items.at(dre), true); m_Elements->removeAll(gElements.Items.at(dre)); } PageItem *ite = m_doc->groupObjectsSelection(tmpSel); ite->setFillTransparency(1.0 - state->getFillOpacity()); ite->setFillBlendmode(getBlendMode(state)); for (int as = 0; as < tmpSel->count(); ++as) { m_Elements->append(tmpSel->itemAt(as)); } if (m_groupStack.count() != 0) applyMask(ite); } if (m_groupStack.count() != 0) { for (int as = 0; as < tmpSel->count(); ++as) { m_groupStack.top().Items.append(tmpSel->itemAt(as)); } } tmpSel->clear(); } } QString SlaOutputDev::getColor(GfxColorSpace *color_space, GfxColor *color, int *shade) { QString fNam; QString namPrefix = "FromPDF"; ScColor tmp; tmp.setSpotColor(false); tmp.setRegistrationColor(false); *shade = 100; if ((color_space->getMode() == csDeviceRGB) || (color_space->getMode() == csCalRGB)) { GfxRGB rgb; color_space->getRGB(color, &rgb); int Rc = qRound(colToDbl(rgb.r) * 255); int Gc = qRound(colToDbl(rgb.g) * 255); int Bc = qRound(colToDbl(rgb.b) * 255); tmp.setColorRGB(Rc, Gc, Bc); fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); } else if (color_space->getMode() == csDeviceCMYK) { GfxCMYK cmyk; color_space->getCMYK(color, &cmyk); int Cc = qRound(colToDbl(cmyk.c) * 255); int Mc = qRound(colToDbl(cmyk.m) * 255); int Yc = qRound(colToDbl(cmyk.y) * 255); int Kc = qRound(colToDbl(cmyk.k) * 255); tmp.setColor(Cc, Mc, Yc, Kc); fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); } else if ((color_space->getMode() == csCalGray) || (color_space->getMode() == csDeviceGray)) { GfxGray gray; color_space->getGray(color, &gray); int Kc = 255 - qRound(colToDbl(gray) * 255); tmp.setColor(0, 0, 0, Kc); fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); } else if (color_space->getMode() == csSeparation) { GfxCMYK cmyk; color_space->getCMYK(color, &cmyk); int Cc = qRound(colToDbl(cmyk.c) * 255); int Mc = qRound(colToDbl(cmyk.m) * 255); int Yc = qRound(colToDbl(cmyk.y) * 255); int Kc = qRound(colToDbl(cmyk.k) * 255); tmp.setColor(Cc, Mc, Yc, Kc); tmp.setSpotColor(true); QString nam = QString(((GfxSeparationColorSpace*)color_space)->getName()->getCString()); fNam = m_doc->PageColors.tryAddColor(nam, tmp); *shade = qRound(colToDbl(color->c[0]) * 100); } else { GfxRGB rgb; color_space->getRGB(color, &rgb); int Rc = qRound(colToDbl(rgb.r) * 255); int Gc = qRound(colToDbl(rgb.g) * 255); int Bc = qRound(colToDbl(rgb.b) * 255); tmp.setColorRGB(Rc, Gc, Bc); fNam = m_doc->PageColors.tryAddColor(namPrefix+tmp.name(), tmp); // qDebug() << "update fill color other colorspace" << color_space->getMode() << "treating as rgb" << Rc << Gc << Bc; } if (fNam == namPrefix+tmp.name()) m_importedColors->append(fNam); return fNam; } QString SlaOutputDev::convertPath(GfxPath *path) { if (! path) return QString(); QString output; pathIsClosed = false; for (int i = 0; i < path->getNumSubpaths(); ++i) { GfxSubpath * subpath = path->getSubpath(i); if (subpath->getNumPoints() > 0) { output += QString("M %1 %2").arg(subpath->getX(0)).arg(subpath->getY(0)); int j = 1; while (j < subpath->getNumPoints()) { if (subpath->getCurve(j)) { output += QString("C %1 %2 %3 %4 %5 %6") .arg(subpath->getX(j)).arg(subpath->getY(j)) .arg(subpath->getX(j + 1)).arg(subpath->getY(j + 1)) .arg(subpath->getX(j + 2)).arg(subpath->getY(j + 2)); j += 3; } else { output += QString("L %1 %2").arg(subpath->getX(j)).arg(subpath->getY(j)); ++j; } } if (subpath->isClosed()) { output += QString("Z"); pathIsClosed = true; } } } return output; } void SlaOutputDev::getPenState(GfxState *state) { switch (state->getLineCap()) { case 0: PLineEnd = Qt::FlatCap; break; case 1: PLineEnd = Qt::RoundCap; break; case 2: PLineEnd = Qt::SquareCap; break; } switch (state->getLineJoin()) { case 0: PLineJoin = Qt::MiterJoin; break; case 1: PLineJoin = Qt::RoundJoin; break; case 2: PLineJoin = Qt::BevelJoin; break; } double *dashPattern; int dashLength; state->getLineDash(&dashPattern, &dashLength, &DashOffset); QVector pattern(dashLength); for (int i = 0; i < dashLength; ++i) { pattern[i] = dashPattern[i]; } DashValues = pattern; } int SlaOutputDev::getBlendMode(GfxState *state) { int mode = 0; switch (state->getBlendMode()) { default: case gfxBlendNormal: mode = 0; break; case gfxBlendDarken: mode = 1; break; case gfxBlendLighten: mode = 2; break; case gfxBlendMultiply: mode = 3; break; case gfxBlendScreen: mode = 4; break; case gfxBlendOverlay: mode = 5; break; case gfxBlendHardLight: mode = 6; break; case gfxBlendSoftLight: mode = 7; break; case gfxBlendDifference: mode = 8; break; case gfxBlendExclusion: mode = 9; break; case gfxBlendColorDodge: mode = 10; break; case gfxBlendColorBurn: mode = 11; break; case gfxBlendHue: mode = 12; break; case gfxBlendSaturation: mode = 13; break; case gfxBlendColor: mode = 14; break; case gfxBlendLuminosity: mode = 15; break; } return mode; } void SlaOutputDev::applyMask(PageItem *ite) { if (m_groupStack.count() != 0) { if (!m_groupStack.top().maskName.isEmpty()) { ite->setPatternMask(m_groupStack.top().maskName); if (m_groupStack.top().alpha) { if (m_groupStack.top().inverted) ite->setMaskType(8); else ite->setMaskType(3); } else { if (m_groupStack.top().inverted) ite->setMaskType(7); else ite->setMaskType(6); } } } } void SlaOutputDev::pushGroup(QString maskName, GBool forSoftMask, GBool alpha, bool inverted) { groupEntry gElements; gElements.forSoftMask = forSoftMask; gElements.alpha = alpha; gElements.inverted = inverted; gElements.maskName = maskName; m_groupStack.push(gElements); } WebSVN - Scribus - Blame - Rev 16751 - /trunk/Scribus/scribus/plugins/import/pdf/slaoutput.cpp

Subversion Repositories Scribus

Rev

Rev 16746 | Rev 16764 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line