From e45563a3c46261d8c32014f8e516857ba01bd7b7 Mon Sep 17 00:00:00 2001 From: miklosh Date: Sat, 28 Jul 2007 13:49:57 +0000 Subject: [PATCH] Reworked text state handling so that now SvgBuilder keeps track of the current text position --- .../internal/pdfinput/pdf-parser.cpp | 10 ++- .../internal/pdfinput/svg-builder.cpp | 70 +++++++++++++++---- src/extension/internal/pdfinput/svg-builder.h | 8 ++- 3 files changed, 71 insertions(+), 17 deletions(-) diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 8d23b0bb3..a75f468d5 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -1962,6 +1962,7 @@ void PdfParser::opEOClip(Object args[], int numArgs) { void PdfParser::opBeginText(Object args[], int numArgs) { state->setTextMat(1, 0, 0, 1, 0, 0); state->textMoveTo(0, 0); + builder->updateTextPosition(0.0, 0.0); fontChanged = gTrue; builder->beginTextObject(state); } @@ -2029,6 +2030,7 @@ void PdfParser::opTextMove(Object args[], int numArgs) { tx = state->getLineX() + args[0].getNum(); ty = state->getLineY() + args[1].getNum(); state->textMoveTo(tx, ty); + builder->updateTextPosition(tx, ty); } void PdfParser::opTextMoveSet(Object args[], int numArgs) { @@ -2039,6 +2041,7 @@ void PdfParser::opTextMoveSet(Object args[], int numArgs) { state->setLeading(-ty); ty += state->getLineY(); state->textMoveTo(tx, ty); + builder->updateTextPosition(tx, ty); } void PdfParser::opSetTextMatrix(Object args[], int numArgs) { @@ -2047,6 +2050,7 @@ void PdfParser::opSetTextMatrix(Object args[], int numArgs) { args[4].getNum(), args[5].getNum()); state->textMoveTo(0, 0); builder->updateTextMatrix(state); + builder->updateTextPosition(0.0, 0.0); fontChanged = gTrue; } @@ -2056,6 +2060,7 @@ void PdfParser::opTextNextLine(Object args[], int numArgs) { tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); + builder->updateTextPosition(tx, ty); } //------------------------------------------------------------------------ @@ -2088,6 +2093,7 @@ void PdfParser::opMoveShowText(Object args[], int numArgs) { tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); + builder->updateTextPosition(tx, ty); doShowText(args[0].getString()); } @@ -2107,6 +2113,7 @@ void PdfParser::opMoveSetShowText(Object args[], int numArgs) { tx = state->getLineX(); ty = state->getLineY() - state->getLeading(); state->textMoveTo(tx, ty); + builder->updateTextPosition(tx, ty); doShowText(args[2].getString()); } @@ -2138,6 +2145,7 @@ void PdfParser::opShowSpaceText(Object args[], int numArgs) { state->textShift(-obj.getNum() * 0.001 * fabs(state->getFontSize()), 0); } + builder->updateTextShift(state, obj.getNum()); } else if (obj.isString()) { doShowText(obj.getString()); } else { @@ -2271,7 +2279,7 @@ void PdfParser::doShowText(GooString *s) { originY *= state->getFontSize(); state->textTransformDelta(originX, originY, &tOriginX, &tOriginY); builder->addChar(state, state->getCurX() + riseX, state->getCurY() + riseY, - tdx, tdy, tOriginX, tOriginY, code, n, u, uLen); + dx, dy, tOriginX, tOriginY, code, n, u, uLen); state->shift(tdx, tdy); p += n; len -= n; diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index bd66871a4..f640ded35 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -853,8 +853,16 @@ void SvgBuilder::updateFont(GfxState *state) { // Font size Inkscape::CSSOStringStream os_font_size; double *text_matrix = state->getTextMat(); - double text_descrim = sqrt( text_matrix[0] * text_matrix[3] - text_matrix[1] * text_matrix[2] ); - double css_font_size = text_descrim * state->getFontSize() * state->getHorizScaling(); + double w_scale = sqrt( text_matrix[0] * text_matrix[0] + text_matrix[2] * text_matrix[2] ); + double h_scale = sqrt( text_matrix[1] * text_matrix[1] + text_matrix[3] * text_matrix[3] ); + double max_scale; + if ( w_scale > h_scale ) { + max_scale = w_scale; + } else { + max_scale = h_scale; + } + double css_font_size = max_scale * state->getFontSize(); + os_font_size << css_font_size; sp_repr_css_set_property(_font_style, "font-size", os_font_size.str().c_str()); @@ -869,19 +877,43 @@ void SvgBuilder::updateFont(GfxState *state) { double *font_matrix = font->getFontMatrix(); NR::Matrix nr_font_matrix(font_matrix[0], font_matrix[1], font_matrix[2], font_matrix[3], font_matrix[4], font_matrix[5]); - NR::Matrix new_text_matrix(text_matrix[0], text_matrix[1], + NR::Matrix new_text_matrix(text_matrix[0] * state->getHorizScaling(), + text_matrix[1] * state->getHorizScaling(), -text_matrix[2], -text_matrix[3], 0.0, 0.0); - if ( fabs( text_descrim - 1.0 ) > EPSILON ) { + + if ( fabs( max_scale - 1.0 ) > EPSILON ) { // Cancel out scaling by font size in text matrix - new_text_matrix *= NR::scale( 1.0 / text_descrim, 1.0 / text_descrim ); + for ( int i = 0 ; i < 4 ; i++ ) { + new_text_matrix[i] /= max_scale; + } } _text_matrix = nr_font_matrix * new_text_matrix; - + _font_scaling = max_scale; _current_font = font; _invalidated_style = true; } +/** + * \brief Shifts the current text position by the given amount (specified in text space) + */ +void SvgBuilder::updateTextShift(GfxState *state, double shift) { + double shift_value = -shift * 0.001 * fabs(state->getFontSize()); + if (state->getFont()->getWMode()) { + _text_position[1] += shift_value; + } else { + _text_position[0] += shift_value; + } +} + +/** + * \brief Updates current text position + */ +void SvgBuilder::updateTextPosition(double tx, double ty) { + NR::Point new_position(tx, ty); + _text_position = new_position; +} + /** * \brief Flushes the buffered characters */ @@ -909,7 +941,6 @@ void SvgBuilder::_flushText() { } Inkscape::XML::Node *text_node = _xml_doc->createElement("svg:text"); - text_node->setAttribute("inkscape:font-specification", _font_specification); // Set text matrix NR::Matrix text_transform(_text_matrix); text_transform[4] = first_glyph.position[0]; @@ -936,9 +967,9 @@ void SvgBuilder::_flushText() { } else if ( i != _glyphs.begin() ) { const SvgGlyph& prev_glyph = (*prev_iterator); if ( !( ( glyph.dy == 0.0 && prev_glyph.dy == 0.0 && - glyph.transformed_position[1] == prev_glyph.transformed_position[1] ) || + glyph.text_position[1] == prev_glyph.text_position[1] ) || ( glyph.dx == 0.0 && prev_glyph.dx == 0.0 && - glyph.transformed_position[0] == prev_glyph.transformed_position[0] ) ) ) { + glyph.text_position[0] == prev_glyph.text_position[0] ) ) ) { new_tspan = true; } } @@ -970,9 +1001,10 @@ void SvgBuilder::_flushText() { break; } else { tspan_node = _xml_doc->createElement("svg:tspan"); + tspan_node->setAttribute("inkscape:font-specification", glyph.font_specification); // Set style and unref SPCSSAttr if it won't be needed anymore sp_repr_css_change(tspan_node, glyph.style, "style"); - if ( glyph.style_changed && i != _glyphs.begin() ) { // Free previous style + if ( glyph.style_changed && i != _glyphs.begin() ) { // Free previous style sp_repr_css_attr_unref((*prev_iterator).style); } } @@ -983,7 +1015,10 @@ void SvgBuilder::_flushText() { y_coords.append(" "); } // Append the coordinates to their respective strings - NR::Point delta_pos( glyph.transformed_position - first_glyph.transformed_position ); + NR::Point delta_pos( glyph.text_position - first_glyph.text_position ); + delta_pos[1] += glyph.rise; + delta_pos[1] *= -1.0; // flip it + delta_pos *= _font_scaling; Inkscape::CSSOStringStream os_x; os_x << delta_pos[0]; x_coords.append(os_x.str()); @@ -1034,17 +1069,19 @@ void SvgBuilder::addChar(GfxState *state, double x, double y, // Allow only one space in a row if ( is_space && _glyphs[_glyphs.size() - 1].code_size == 1 && _glyphs[_glyphs.size() - 1].code[0] == 32 ) { + NR::Point delta(dx, dy); + _text_position += delta; return; } SvgGlyph new_glyph; new_glyph.is_space = is_space; new_glyph.position = NR::Point( x - originX, y - originY ); - new_glyph.transformed_position = new_glyph.position * _text_matrix; + new_glyph.text_position = _text_position; + new_glyph.dx = dx; + new_glyph.dy = dy; NR::Point delta(dx, dy); - delta *= _text_matrix; - new_glyph.dx = delta[0]; - new_glyph.dy = delta[1]; + _text_position += delta; // Convert the character to UTF-8 since that's our SVG document's encoding static UnicodeMap *u_map = NULL; @@ -1078,6 +1115,9 @@ void SvgBuilder::addChar(GfxState *state, double x, double y, new_glyph.style = prev_glyph.style; new_glyph.render_mode = prev_glyph.render_mode; } + new_glyph.font_specification = _font_specification; + new_glyph.rise = state->getRise(); + _glyphs.push_back(new_glyph); } diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h index 245ef4a7c..47a79a0f4 100644 --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -58,8 +58,9 @@ namespace Internal { */ struct SvgGlyph { NR::Point position; // Absolute glyph coords - NR::Point transformed_position; // Glyph coords transformed by text matrix + NR::Point text_position; // Absolute glyph coords in text space double dx, dy; // Advance values + double rise; // Text rise parameter char code[8]; // UTF-8 coded character int code_size; bool is_space; @@ -67,6 +68,7 @@ struct SvgGlyph { bool style_changed; // Set to true if style has to be reset SPCSSAttr *style; int render_mode; // Text render mode + char *font_specification; // Pointer to current font specification }; /** @@ -113,6 +115,8 @@ public: void restoreState(); void updateStyle(GfxState *state); void updateFont(GfxState *state); + void updateTextPosition(double tx, double ty); + void updateTextShift(GfxState *state, double shift); void updateTextMatrix(GfxState *state); // Clipping @@ -152,8 +156,10 @@ private: SPCSSAttr *_font_style; // Current font style GfxFont *_current_font; char *_font_specification; + double _font_scaling; bool _need_font_update; NR::Matrix _text_matrix; + NR::Point _text_position; std::vector _glyphs; // Added characters bool _in_text_object; // Whether we are inside a text object bool _invalidated_style; -- 2.30.2