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;
}
Пример #2
0
void QgsDecorationTitle::render( const QgsMapSettings &mapSettings, QgsRenderContext &context )
{
  Q_UNUSED( mapSettings )
  if ( !enabled() )
    return;

  context.painter()->save();
  context.painter()->setRenderHint( QPainter::Antialiasing, true );

  QString displayString = QgsExpression::replaceExpressionText( mLabelText, &context.expressionContext() );
  QStringList displayStringList = displayString.split( '\n' );

  QFontMetricsF fm( mTextFormat.scaledFont( context ) );
  QFontMetricsF textMetrics = QgsTextRenderer::fontMetrics( context, mTextFormat );
  double textDescent = textMetrics.descent();
  double textWidth = QgsTextRenderer::textWidth( context, mTextFormat, displayStringList, &fm );
  double textHeight = QgsTextRenderer::textHeight( context, mTextFormat, displayStringList, QgsTextRenderer::Point, &fm );

  QPaintDevice *device = context.painter()->device();
  int deviceHeight = device->height() / device->devicePixelRatioF();
  int deviceWidth = device->width() / device->devicePixelRatioF();

  float xOffset( 0 ), yOffset( 0 );

  // Set  margin according to selected units
  switch ( mMarginUnit )
  {
    case QgsUnitTypes::RenderMillimeters:
    {
      int pixelsInchX = context.painter()->device()->logicalDpiX();
Пример #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;
			}
		}
	}
}