X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fextension%2Finternal%2Flatex-text-renderer.cpp;h=fd99afe31b71f2fedd8c9dd503d97e277ce4d44d;hb=9dc68827cbd515262ecb8d5ae8547d9e82c72e00;hp=94e1d98934c5d58bba204755fc018be02e42985c;hpb=14ac5d5ac7f9ee938d810194eefdba7bcfda3722;p=inkscape.git diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index 94e1d9893..fd99afe31 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -1,5 +1,3 @@ -#define EXTENSION_INTERNAL_LATEX_TEXT_RENDERER_CPP - /** \file * Rendering LaTeX file (pdf/eps/ps+latex output) * @@ -9,6 +7,8 @@ * Authors: * Johan Engelen * Miklos Erdelyi + * Jon A. Cruz + * Abhishek Sharma * * Copyright (C) 2006-2010 Authors * @@ -36,6 +36,7 @@ #include "sp-use.h" #include "sp-text.h" #include "sp-flowtext.h" +#include "sp-rect.h" #include "text-editing.h" #include @@ -50,13 +51,14 @@ namespace Internal { /** * This method is called by the PDF, EPS and PS output extensions. - * @param filename This should be the filename without extension to which the tex code should be written. Output goes to .tex. + * @param filename This should be the filename without '_tex' extension to which the tex code should be written. Output goes to _tex, note the underscore instead of period. */ bool latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, - const gchar * const exportId, bool exportDrawing, bool exportCanvas) + const gchar * const exportId, bool exportDrawing, bool exportCanvas, + bool pdflatex) { - sp_document_ensure_up_to_date(doc); + doc->ensureUpToDate(); SPItem *base = NULL; @@ -68,7 +70,7 @@ latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, } else { // we want to export the entire document from root - base = SP_ITEM(sp_document_root(doc)); + base = SP_ITEM(doc->getRoot()); pageBoundingBox = !exportDrawing; } @@ -76,7 +78,7 @@ latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, return false; /* Create renderer */ - LaTeXTextRenderer *renderer = new LaTeXTextRenderer(); + LaTeXTextRenderer *renderer = new LaTeXTextRenderer(pdflatex); bool ret = renderer->setTargetFile(filename); if (ret) { @@ -92,9 +94,10 @@ latex_render_document_text_to_file( SPDocument *doc, gchar const *filename, return ret; } -LaTeXTextRenderer::LaTeXTextRenderer(void) +LaTeXTextRenderer::LaTeXTextRenderer(bool pdflatex) : _stream(NULL), - _filename(NULL) + _filename(NULL), + _pdflatex(pdflatex) { push_transform(Geom::identity()); } @@ -129,7 +132,7 @@ LaTeXTextRenderer::setTargetFile(gchar const *filename) { _filename = g_path_get_basename(filename); - gchar *filename_ext = g_strdup_printf("%s.tex", filename); + gchar *filename_ext = g_strdup_printf("%s_tex", filename); Inkscape::IO::dump_fopen_call(filename_ext, "K"); FILE *osf = Inkscape::IO::fopen_utf8name(filename_ext, "w+"); if (!osf) { @@ -173,24 +176,37 @@ LaTeXTextRenderer::setTargetFile(gchar const *filename) { static char const preamble[] = "%% To include the image in your LaTeX document, write\n" -"%% \\input{.tex}\n" +"%% \\input{.pdf_tex}\n" "%% instead of\n" "%% \\includegraphics{.pdf}\n" "%% To scale the image, write\n" -"%% \\def{\\svgwidth}{}\n" -"%% \\input{.tex}\n" +"%% \\def\\svgwidth{}\n" +"%% \\input{.pdf_tex}\n" "%% instead of\n" "%% \\includegraphics[width=]{.pdf}\n" +"%%\n" +"%% Images with a different path to the parent latex file can\n" +"%% be accessed with the `import' package (which may need to be\n" +"%% installed) using\n" +"%% \\usepackage{import}\n" +"%% in the preamble, and then including the image with\n" +"%% \\import{}{.pdf_tex}\n" +"%% Alternatively, one can specify\n" +"%% \\graphicspath{{/}}\n" +"%% \n" +"%% For more information, please see info/svg-inkscape on CTAN:\n" +"%% http://tug.ctan.org/tex-archive/info/svg-inkscape\n" "\n" "\\begingroup\n" " \\makeatletter\n" " \\providecommand\\color[2][]{%\n" -" \\GenericError{(Inkscape) \\space\\space\\@spaces}{%\n" -" Color is used for the text in Inkscape, but the color package color is not loaded.\n" -" }{Either use black text in Inkscape or load the package\n" -" color.sty in LaTeX.}%\n" +" \\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package \'color.sty\' is not loaded}\n" " \\renewcommand\\color[2][]{}%\n" " }\n" +" \\providecommand\\transparent[1]{%\n" +" \\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package \'transparent.sty\' is not loaded}\n" +" \\renewcommand\\transparent[1]{}%\n" +" }\n" " \\providecommand\\rotatebox[2]{#2}\n"; static char const postamble[] = @@ -258,7 +274,7 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) // get position and alignment // Align vertically on the baseline of the font (retreived from the anchor point) // Align horizontally on anchorpoint - gchar *alignment = NULL; + gchar const *alignment = NULL; switch (style->text_anchor.computed) { case SP_CSS_TEXT_ANCHOR_START: alignment = "[lb]"; @@ -274,22 +290,28 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) Geom::Point anchor = textobj->attributes.firstXY() * transform(); Geom::Point pos(anchor); - // determine color (for now, use rgb color model as it is most native to Inkscape) + // determine color and transparency (for now, use rgb color model as it is most native to Inkscape) bool has_color = false; // if the item has no color set, don't force black color + bool has_transparency = false; // TODO: how to handle ICC colors? // give priority to fill color guint32 rgba = 0; + float opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); if (style->fill.set && style->fill.isColor()) { has_color = true; rgba = style->fill.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value); } else if (style->stroke.set && style->stroke.isColor()) { has_color = true; rgba = style->stroke.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); + } + if (opacity < 1.0) { + has_transparency = true; } - // get rotation - Geom::Matrix i2doc = sp_item_i2doc_affine(item); + Geom::Matrix i2doc = item->i2doc_affine(); Geom::Matrix wotransl = i2doc.without_translation(); double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); bool has_rotation = !Geom::are_near(degrees,0.); @@ -302,6 +324,9 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) if (has_color) { os << "\\color[rgb]{" << SP_RGBA32_R_F(rgba) << "," << SP_RGBA32_G_F(rgba) << "," << SP_RGBA32_B_F(rgba) << "}"; } + if (_pdflatex && has_transparency) { + os << "\\transparent{" << opacity << "}"; + } if (has_rotation) { os << "\\rotatebox{" << degrees << "}{"; } @@ -317,21 +342,107 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) } void -LaTeXTextRenderer::sp_flowtext_render(SPItem *item) +LaTeXTextRenderer::sp_flowtext_render(SPItem * item) { -/* SPFlowtext *group = SP_FLOWTEXT(item); +/* +Flowtext is possible by using a minipage! :) +Flowing in rectangle is possible, not in arb shape. +*/ + + SPFlowtext *flowtext = SP_FLOWTEXT(item); + SPStyle *style = SP_OBJECT_STYLE (SP_OBJECT(item)); + + gchar *strtext = sp_te_get_string_multiline(item); + if (!strtext) { + return; + } + // replace carriage return with double slash + gchar ** splitstr = g_strsplit(strtext, "\n", -1); + gchar *str = g_strjoinv("\\\\ ", splitstr); + g_free(strtext); + g_strfreev(splitstr); + + SPItem *frame_item = flowtext->get_frame(NULL); + if (!frame_item || !SP_IS_RECT(frame_item)) { + g_warning("LaTeX export: non-rectangular flowed text shapes are not supported, skipping text."); + return; // don't know how to handle non-rect frames yet. is quite uncommon for latex users i think + } + + SPRect *frame = SP_RECT(frame_item); + Geom::Rect framebox = sp_rect_get_rect(frame) * transform(); + + // get position and alignment + // Align on topleft corner. + gchar const *alignment = "[lt]"; + gchar const *justification = ""; + switch (flowtext->layout.paragraphAlignment(flowtext->layout.begin())) { + case Inkscape::Text::Layout::LEFT: + justification = "\\raggedright "; + break; + case Inkscape::Text::Layout::RIGHT: + justification = "\\raggedleft "; + break; + case Inkscape::Text::Layout::CENTER: + justification = "\\centering "; + case Inkscape::Text::Layout::FULL: + default: + // no need to add LaTeX code for standard justified output :) + break; + } + Geom::Point pos(framebox.corner(3)); //topleft corner + + // determine color and transparency (for now, use rgb color model as it is most native to Inkscape) + bool has_color = false; // if the item has no color set, don't force black color + bool has_transparency = false; + // TODO: how to handle ICC colors? + // give priority to fill color + guint32 rgba = 0; + float opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); + if (style->fill.set && style->fill.isColor()) { + has_color = true; + rgba = style->fill.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->fill_opacity.value); + } else if (style->stroke.set && style->stroke.isColor()) { + has_color = true; + rgba = style->stroke.value.color.toRGBA32(1.); + opacity *= SP_SCALE24_TO_FLOAT(style->stroke_opacity.value); + } + if (opacity < 1.0) { + has_transparency = true; + } + + // get rotation + Geom::Matrix i2doc = item->i2doc_affine(); + Geom::Matrix wotransl = i2doc.without_translation(); + double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); + bool has_rotation = !Geom::are_near(degrees,0.); // write to LaTeX Inkscape::SVGOStringStream os; - os.setf(std::ios::fixed); // no scientific notation + os.setf(std::ios::fixed); // don't use scientific notation - os << " \\begin{picture}(" << _width << "," << _height << ")%%\n"; - os << " \\gplgaddtomacro\\gplbacktext{%%\n"; - os << " \\csname LTb\\endcsname%%\n"; - os << "\\put(0,0){\\makebox(0,0)[lb]{\\strut{}Position}}%%\n"; + os << " \\put(" << pos[Geom::X] << "," << pos[Geom::Y] << "){"; + if (has_color) { + os << "\\color[rgb]{" << SP_RGBA32_R_F(rgba) << "," << SP_RGBA32_G_F(rgba) << "," << SP_RGBA32_B_F(rgba) << "}"; + } + if (_pdflatex && has_transparency) { + os << "\\transparent{" << opacity << "}"; + } + if (has_rotation) { + os << "\\rotatebox{" << degrees << "}{"; + } + os << "\\makebox(0,0)" << alignment << "{"; + os << "\\begin{minipage}{" << framebox.width() << "\\unitlength}"; + os << justification; + os << str; + os << "\\end{minipage}"; + if (has_rotation) { + os << "}"; // rotatebox end + } + os << "}"; //makebox end + os << "}%\n"; // put end fprintf(_stream, "%s", os.str().c_str()); -*/ } void @@ -379,15 +490,16 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * { // The boundingbox calculation here should be exactly the same as the one by CairoRenderer::setupDocument ! - if (!base) - base = SP_ITEM(sp_document_root(doc)); + if (!base) { + base = SP_ITEM(doc->getRoot()); + } Geom::OptRect d; if (pageBoundingBox) { d = Geom::Rect( Geom::Point(0,0), - Geom::Point(sp_document_width(doc), sp_document_height(doc)) ); + Geom::Point(doc->getWidth(), doc->getHeight()) ); } else { - sp_item_invoke_bbox(base, d, sp_item_i2d_affine(base), TRUE, SPItem::RENDERING_BBOX); + base->invoke_bbox( d, base->i2d_affine(), TRUE, SPItem::RENDERING_BBOX); } if (!d) { g_message("LaTeXTextRenderer: could not retrieve boundingbox."); @@ -402,13 +514,11 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * if (!pageBoundingBox) { - double high = sp_document_height(doc); - push_transform( Geom::Translate( - d->min() ) ); } // flip y-axis - push_transform( Geom::Scale(1,-1) * Geom::Translate(0, sp_document_height(doc)) ); + push_transform( Geom::Scale(1,-1) * Geom::Translate(0, doc->getHeight()) ); // write the info to LaTeX Inkscape::SVGOStringStream os; @@ -416,12 +526,12 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * // scaling of the image when including it in LaTeX - os << " \\ifx \\svgwidth \\@empty\n"; + os << " \\ifx\\svgwidth\\undefined\n"; os << " \\setlength{\\unitlength}{" << d->width() * PT_PER_PX << "pt}\n"; os << " \\else\n"; os << " \\setlength{\\unitlength}{\\svgwidth}\n"; os << " \\fi\n"; - os << " \\global\\let\\svgwidth\\@empty\n"; + os << " \\global\\let\\svgwidth\\undefined\n"; os << " \\makeatother\n"; os << " \\begin{picture}(" << _width << "," << _height << ")%\n"; @@ -469,4 +579,4 @@ LaTeXTextRenderer::pop_transform() fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :