예제 #1
0
void TBox::layout()
      {
      setPos(QPointF());      // !?
      bbox().setRect(0.0, 0.0, system()->width(), 0);
      _text->layout();

      qreal h = _text->height();
      if (_text->empty()) {
            QFontMetricsF fm = QFontMetricsF(_text->font(), MScore::paintDevice());
            h = fm.ascent();
            }
      else
            h = _text->height();
      qreal y = topMargin() * DPMM;
#if 0
      if (_text->align() & Align::BOTTOM)
            y += h;
      else if (_text->align() & Align::VCENTER)
            y +=  h * .5;
      else
            ; // y = 0;
#endif
      _text->setPos(leftMargin() * DPMM, y);
      h += topMargin() * DPMM + bottomMargin() * DPMM;
      bbox().setRect(0.0, 0.0, system()->width(), h);

      MeasureBase::layout();  // layout LayoutBreak's
      }
QSizeF AdjustColumnRowManipulator::textSize(const QString& text, const Style& style) const
{
    QSizeF size;
    DummyWidget dummyWiget;
    const QFontMetricsF fontMetrics(style.font(), &dummyWiget);

    // Set size to correct values according to
    // if the text is horizontal, vertical or rotated.
    if (!style.verticalText() && !style.angle()) {
        // Horizontal text.

        size = fontMetrics.size(0, text);
        double offsetFont = 0.0;
        if ((style.valign() == Style::Bottom) && style.underline())
            offsetFont = fontMetrics.underlinePos() + 1;

        size.setHeight((fontMetrics.ascent() + fontMetrics.descent() + offsetFont)
                       *(text.count('\n') + 1));
    } else if (style.angle() != 0) {
        // Rotated text.

        const double height = fontMetrics.ascent() + fontMetrics.descent();
        const double width  = fontMetrics.width(text);
        size.setHeight(height * ::cos(style.angle() * M_PI / 180)
                       + qAbs(width * ::sin(style.angle() * M_PI / 180)));
        size.setWidth(qAbs(height * ::sin(style.angle() * M_PI / 180))
                      + width * ::cos(style.angle() * M_PI / 180));
    } else {
        // Vertical text.

        qreal width = 0.0;
        for (int i = 0; i < text.length(); i++)
            width = qMax(width, fontMetrics.width(text.at(i)));

        size.setWidth(width);
        size.setHeight((fontMetrics.ascent() + fontMetrics.descent())
                       * text.length());
    }
    return size;
}
예제 #3
0
void TextObject::prepareLineInfos() const
{
	const TextSymbol* text_symbol = reinterpret_cast<const TextSymbol*>(symbol);
	
	double scaling = text_symbol->calculateInternalScaling();
	QFontMetricsF metrics = text_symbol->getFontMetrics();
	double line_spacing = text_symbol->getLineSpacing() * metrics.lineSpacing();
	double paragraph_spacing = scaling * text_symbol->getParagraphSpacing() + (text_symbol->hasLineBelow() ? (scaling * (text_symbol->getLineBelowDistance() + text_symbol->getLineBelowWidth())) : 0);
	double ascent = metrics.ascent();
	
	bool word_wrap = ! hasSingleAnchor();
	double box_width  = word_wrap ? (scaling * getBoxWidth())  : 0.0;
	double box_height = word_wrap ? (scaling * getBoxHeight()) : 0.0;
	
	int text_end = text.length();
	const QLatin1Char line_break('\n');
	const QLatin1Char part_break('\t');
	const QLatin1Char word_break(' ');
	
	line_infos.clear();
	
	// Initialize offsets
	
	double line_x = 0.0;
	if (h_align == TextObject::AlignLeft)
		line_x -= 0.5 * box_width;
	else if (h_align == TextObject::AlignRight)
		line_x += 0.5 * box_width;

	double line_y = 0.0;
	if (v_align == TextObject::AlignTop || v_align == TextObject::AlignBaseline)
		line_y += -0.5 * box_height;
	if (v_align != TextObject::AlignBaseline)
		line_y += ascent;
	
	// Determine lines and parts
	
	//double next_line_x_offset = 0; // to keep indentation after word wrap in a line with tabs
	int num_paragraphs = 0;
	int line_num = 0;
	int line_start = 0;
	while (line_start <= text_end) 
	{
		// Initialize input line
		double line_width = 0.0;
		int line_end = text.indexOf(line_break, line_start);
		if (line_end == -1)
			line_end = text_end;
		bool paragraph_end = true;
		
		std::vector<TextObjectPartInfo> part_infos;
		
		int part_start = line_start;
		double part_x = line_x;
		
		while (part_start <= line_end)
		{
			// Initialize part (sequence of letters terminated by tab or line break)
			int part_end = text.indexOf(part_break, part_start);
			if (part_end == -1)
				part_end = line_end;
			else if (part_end > line_end)
				part_end = line_end;
			
			if (part_start > 0 && text[part_start - 1] == part_break)
				part_x = line_x + text_symbol->getNextTab(part_x - line_x);
			
			QString part = text.mid(part_start, part_end - part_start);
			double part_width = metrics.boundingRect(part).width();
			
			if (word_wrap)
			{
				// shrink overflowing part to maximum possible size
				while (part_x + part_width - line_x > box_width)
				{
					// find latest possible break
					int new_part_end =  text.lastIndexOf(word_break, part_end - 1);
					if (new_part_end <= part_start)
					{
						// part won't fit
						if (part_start > line_start)
						{
							// don't put another part on this line
							part_end = part_start - 1;
							paragraph_end = false;
						}
						break;
					}
					
					paragraph_end = false;
					
					// Shrink the part and the line
					part_end = new_part_end;
					part = text.mid(part_start, part_end - part_start);
					part_width = metrics.width(part);
					line_end = part_end;
				}
			}
			if (part_end < part_start)
				break;
			
			// Add the current part
			part_infos.push_back( { part, part_start, part_end, part_x, metrics.width(part), metrics } );
			
			// Advance to next part position
			part_start = part_end + 1;
			part_x += part_width;
		}
		
		TextObjectPartInfo& last_part_info = part_infos.back();
		line_end   = last_part_info.end_index;
		line_width = last_part_info.part_x + last_part_info.width - line_x;
		
		// Jump over whitespace after the end of the line and check if it contains a newline character to determine if it is a paragraph end
		int next_line_start = line_end + 1;
		/*while (next_line_start < text.size() && (text[next_line_start] == line_break || text[next_line_start] == part_break || text[next_line_start] == word_break))
		{
			if (text[next_line_start - 1] == line_break)
			{
				paragraph_end = true;
				break;
			}
			++next_line_start;
		}*/
		
		line_infos.push_back( { line_start, line_end, paragraph_end, line_x, line_y, line_width, metrics.ascent(), metrics.descent(), part_infos } );
		
		// Advance to next line
		line_y += line_spacing;
		if (paragraph_end)
		{
			line_y += paragraph_spacing;
			num_paragraphs++;
		}
		line_num++;
		line_start = next_line_start;
	}
	
	// Update the line and part offset for every other alignment than top-left or baseline-left
	
	double delta_y = 0.0;
	if (v_align == TextObject::AlignBottom || v_align == TextObject::AlignVCenter)
	{
		int num_lines = getNumLines();
		double height = ascent + (num_lines - 1) * line_spacing + (num_paragraphs - 1) * paragraph_spacing;
		
		if (v_align == TextObject::AlignVCenter)
			delta_y = -0.5 * height;
		else if (v_align == TextObject::AlignBottom)
			delta_y = -height + 0.5 * box_height;
	}
	
	if (delta_y != 0.0 || h_align != TextObject::AlignLeft)
	{
		int num_lines = getNumLines();
		for (int i = 0; i < num_lines; i++)
		{
			TextObjectLineInfo* line_info = &line_infos[i];
			
			double delta_x = 0.0;
			if (h_align == TextObject::AlignHCenter)
				delta_x = -0.5 * line_info->width;
			else if (h_align == TextObject::AlignRight)
				delta_x -= line_info->width;
			
			line_info->line_x += delta_x;
			line_info->line_y += delta_y;
			
			int num_parts = line_info->part_infos.size();
			for (int j = 0; j < num_parts; j++)
			{
				line_info->part_infos.at(j).part_x += delta_x;
			}
		}
	}
}