Layout-TNG-Output.cpp revision 8eb2b6772a9db58582162899b9d525211efbc11c
/*
* Inkscape::Text::Layout - text layout engine output functions
*
* Authors:
* Richard Hughes <cyreve@users.sf.net>
*
* Copyright (C) 2005 Richard Hughes
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "Layout-TNG.h"
#include "display/nr-arena-glyphs.h"
#include "style.h"
#include "print.h"
#include "libnr/nr-matrix-fns.h"
#include "libnr/nr-scale-matrix-ops.h"
#include "libnr/nr-convert2geom.h"
#include "font-instance.h"
#include "svg/svg-length.h"
#include "extension/internal/cairo-render-context.h"
namespace Inkscape {
namespace Extension {
namespace Internal {
class CairoRenderContext;
class CairoGlyphInfo;
}
}
}
namespace Inkscape {
namespace Text {
void Layout::_clearOutputObjects()
{
_paragraphs.clear();
_characters.clear();
_path_fitted = NULL;
}
{
}
{
} else {
}
}
{
int glyph_index = 0;
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[_spans[span_index].in_input_stream_item]);
while (glyph_index < (int)_glyphs.size() && _characters[_glyphs[glyph_index].in_character].in_span == span_index) {
nr_arena_glyphs_group_add_component(nr_group, _spans[span_index].font, _glyphs[glyph_index].glyph, &glyph_matrix);
}
glyph_index++;
}
}
}
void Layout::getBoundingBox(NRRect *bounding_box, NR::Matrix const &transform, int start, int length) const
{
if (length != -1) {
if (start == -1)
start = 0;
}
// this could be faster
boost::optional<NR::Rect> glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph);
if (glyph_rect) {
tlp *= total_transform;
trp *= total_transform;
blp *= total_transform;
brp *= total_transform;
}
}
}
}
{
if (_input_stream.empty()) return;
// invisible glyphs
glyph_index++;
continue;
}
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[span.in_input_stream_item]);
if (text_to_path || _path_fitted) {
if (pv) {
}
glyph_index++;
} else {
NR::Point g_pos(0,0); // all strings are output at (0,0) because we do the translation using the matrix
glyph_matrix = NR::Matrix(NR::scale(1.0, -1.0) * NR::Matrix(NR::rotate(_glyphs[glyph_index].rotation)));
// since we're outputting character codes, not glyphs, we want the character x
glyph_matrix[5] = span.chunk(this).left_x + span.x_start + _characters[_glyphs[glyph_index].in_character].x;
} else {
glyph_matrix[4] = span.chunk(this).left_x + span.x_start + _characters[_glyphs[glyph_index].in_character].x;
}
char_index--;
span_iter++;
}
// try to output as many characters as possible in one go by detecting kerning and stopping when we encounter it
do {
span_string += *span_iter;
span_iter++;
glyph_index++;
}
&& _path_fitted == NULL
}
}
}
#ifdef HAVE_CAIRO_PDF
{
if (_input_stream.empty()) return;
bool clip_mode = false;//(ctx->getRenderMode() == CairoRenderContext::RENDER_MODE_CLIP);
// invisible glyphs
glyph_index++;
continue;
}
InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_input_stream[span.in_input_stream_item]);
if (clip_mode) {
if (pathv) {
}
glyph_index++;
continue;
}
if (_path_fitted == NULL) {
font_matrix[4] = 0;
font_matrix[5] = 0;
} else {
}
char_index--;
span_iter++;
}
// try to output as many characters as possible in one go
unsigned int first_index = glyph_index;
do {
span_string += *span_iter;
span_iter++;
if (glyph_index != first_index)
if (_path_fitted == NULL) {
} else {
info.x = 0;
info.y = 0;
}
glyph_index++;
}
&& _path_fitted == NULL
// remove vertical flip
if (_path_fitted) {
} else if (opacity != 1.0) {
}
if (glyph_index - first_index > 0)
if (_path_fitted)
else if (opacity != 1.0) {
}
}
}
#endif
// these functions are for dumpAsText() only. No need to translate
{
switch (d) {
}
return "???";
}
static char const *style_to_text(PangoStyle s)
{
switch (s) {
case PANGO_STYLE_NORMAL: return "upright";
case PANGO_STYLE_ITALIC: return "italic";
case PANGO_STYLE_OBLIQUE: return "oblique";
}
return "???";
}
static char const *weight_to_text(PangoWeight w)
{
switch (w) {
case PANGO_WEIGHT_ULTRALIGHT: return "ultralight";
case PANGO_WEIGHT_LIGHT : return "light";
case PANGO_WEIGHT_SEMIBOLD : return "semibold";
case PANGO_WEIGHT_NORMAL : return "normalweight";
case PANGO_WEIGHT_BOLD : return "bold";
case PANGO_WEIGHT_ULTRABOLD : return "ultrabold";
case PANGO_WEIGHT_HEAVY : return "heavy";
}
return "???";
}
{
char line[256];
snprintf(line, sizeof(line), " in para %d (direction=%s)\n", _lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph,
direction_to_text(_paragraphs[_lines[_chunks[_spans[span_index].in_chunk].in_line].in_paragraph].base_direction));
snprintf(line, sizeof(line), " in source %d (type=%d, cookie=%p)\n", _spans[span_index].in_input_stream_item,
snprintf(line, sizeof(line), " in line %d (baseline=%f, shape=%d)\n", _chunks[_spans[span_index].in_chunk].in_line,
snprintf(line, sizeof(line), " in chunk %d (x=%f, baselineshift=%f)\n", _spans[span_index].in_chunk, _chunks[_spans[span_index].in_chunk].left_x, _spans[span_index].baseline_shift);
snprintf(line, sizeof(line), " font '%s' %f %s %s\n", pango_font_description_get_family(_spans[span_index].font->descr), _spans[span_index].font_size, style_to_text(pango_font_description_get_style(_spans[span_index].font->descr)), weight_to_text(pango_font_description_get_weight(_spans[span_index].font->descr)));
}
snprintf(line, sizeof(line), " x_start = %f, x_end = %f\n", _spans[span_index].x_start, _spans[span_index].x_end);
snprintf(line, sizeof(line), " line height: ascent %f, descent %f leading %f\n", _spans[span_index].line_height.ascent, _spans[span_index].line_height.descent, _spans[span_index].line_height.leading);
snprintf(line, sizeof(line), " direction %s, block-progression %s\n", direction_to_text(_spans[span_index].direction), direction_to_text(_spans[span_index].block_progression));
result += " ** characters:\n";
// very inefficent code. what the hell, it's only debug stuff.
snprintf(line, sizeof(line), " %d: control x=%f flags=%03x glyph=%d\n", char_index, _characters[char_index].x, *(unsigned*)&_characters[char_index].char_attributes, _characters[char_index].in_glyph);
} else {
snprintf(line, sizeof(line), " %d: '%c' x=%f flags=%03x glyph=%d\n", char_index, *iter_char, _characters[char_index].x, *(unsigned*)&_characters[char_index].char_attributes, _characters[char_index].in_glyph);
iter_char++;
}
}
result += " ** glyphs:\n";
snprintf(line, sizeof(line), " %d: %d (%f,%f) rot=%f cx=%f char=%d\n", glyph_index, _glyphs[glyph_index].glyph, _glyphs[glyph_index].x, _glyphs[glyph_index].y, _glyphs[glyph_index].rotation, _glyphs[glyph_index].width, _glyphs[glyph_index].in_character);
}
result += "\n";
}
result += "EOT\n";
return result;
}
{
double offset = 0.0;
if (startOffset._set) {
else
}
case CENTER:
break;
case RIGHT:
offset -= _getChunkWidth(0);
break;
default:
break;
}
if (_characters.empty()) {
int unused = 0;
}
}
unsigned next_cluster_char_index;
double character_advance;
next_cluster_char_index < _characters.size() && !_characters[next_cluster_char_index].char_attributes.is_cursor_position;
} else {
character_advance = (_glyphs[next_cluster_glyph_index].x + _glyphs[next_cluster_glyph_index].chunk(this).left_x)
}
double cluster_width = 0.0;
for (int glyph_index = _characters[char_index].in_glyph ; glyph_index < next_cluster_glyph_index ; glyph_index++)
int unused = 0;
// as far as I know these functions are const, they're just not marked as such
Path::cut_position *midpoint_otp = const_cast<Path&>(path).CurvilignToPosition(1, &midpoint_offset, unused);
const_cast<Path&>(path).PointAndTangentAt(midpoint_otp[0].piece, midpoint_otp[0].t, midpoint, tangent);
Path::cut_position *start_otp = const_cast<Path&>(path).CurvilignToPosition(1, &start_offset, unused);
bool on_same_subpath = true;
on_same_subpath = false;
break;
}
}
if (on_same_subpath) {
// both points were on the same subpath (without this test the angle is very weird)
if (endpoint != startpoint) {
} else {
}
}
}
}
}
for (int glyph_index = _characters[char_index].in_glyph ; glyph_index < next_cluster_glyph_index ; glyph_index++) {
double tangent_shift = -cluster_width * 0.5 + _glyphs[glyph_index].x - (_characters[char_index].x + span.x_start);
_glyphs[glyph_index].x = midpoint[0] - span.chunk(this).left_x + tangent[0] * tangent_shift - tangent[1] * normal_shift;
_glyphs[glyph_index].y = midpoint[1] - _lines.front().baseline_y + tangent[1] * tangent_shift + tangent[0] * normal_shift;
}
} else { // outside the bounds of the path: hide the glyphs
}
}
}
_path_fitted = &path;
}
{
for (int glyph_index = from_glyph._glyph_index ; glyph_index < to_glyph._glyph_index ; glyph_index++) {
if (pathv) {
}
}
if ( cc ) {
} else {
}
while (cc) {
/* fixme: This is dangerous, as we are mixing art_alloc and g_new */
}
return curve;
}
{
// this is all massively oversimplified
// I can't actually think of anybody who'll want to use it at the moment, so it'll stay simple
}
}
}//namespace Text
}//namespace Inkscape
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :