LibreOffice Module oox (master)  1
vmltextbox.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <oox/vml/vmltextbox.hxx>
21 
22 #include <rtl/ustrbuf.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <com/sun/star/awt/FontWeight.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
27 #include <com/sun/star/drawing/XShape.hpp>
28 #include <com/sun/star/text/XTextAppend.hpp>
29 #include <com/sun/star/text/WritingMode.hpp>
30 #include <com/sun/star/style/ParagraphAdjust.hpp>
31 #include <comphelper/sequence.hxx>
33 
34 namespace oox::vml {
35 
36 using namespace com::sun::star;
37 
39 {
40 }
41 
42 TextPortionModel::TextPortionModel( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText ) :
43  maParagraph( rParagraph ),
44  maFont( rFont ),
45  maText( rText )
46 {
47 }
48 
50  : mrTypeModel(rTypeModel)
51  , borderDistanceSet( false )
52  , borderDistanceLeft(0)
53  , borderDistanceTop(0)
54  , borderDistanceRight(0)
55  , borderDistanceBottom(0)
56 {
57 }
58 
59 void TextBox::appendPortion( const TextParagraphModel& rParagraph, const TextFontModel& rFont, const OUString& rText )
60 {
61  maPortions.emplace_back( rParagraph, rFont, rText );
62 }
63 
65 {
66  return maPortions.empty() ? nullptr : &maPortions.front().maFont;
67 }
68 
69 OUString TextBox::getText() const
70 {
71  OUStringBuffer aBuffer;
72  for (auto const& portion : maPortions)
73  aBuffer.append( portion.maText );
74  return aBuffer.makeStringAndClear();
75 }
76 
77 void TextBox::convert(const uno::Reference<drawing::XShape>& xShape) const
78 {
79  uno::Reference<text::XTextAppend> xTextAppend(xShape, uno::UNO_QUERY);
80  OUString sParaStyle;
81  bool bAmbiguousStyle = true;
82 
83  for (auto const& portion : maPortions)
84  {
85  beans::PropertyValue aPropertyValue;
86  std::vector<beans::PropertyValue> aPropVec;
87  const TextParagraphModel& rParagraph = portion.maParagraph;
88  const TextFontModel& rFont = portion.maFont;
89  if (rFont.moName.has())
90  {
91  aPropertyValue.Name = "CharFontName";
92  aPropertyValue.Value <<= rFont.moName.get();
93  aPropVec.push_back(aPropertyValue);
94 
95  aPropertyValue.Name = "CharFontNameAsian";
96  aPropertyValue.Value <<= rFont.moNameAsian.get();
97  aPropVec.push_back(aPropertyValue);
98 
99  aPropertyValue.Name = "CharFontNameComplex";
100  aPropertyValue.Value <<= rFont.moNameComplex.get();
101  aPropVec.push_back(aPropertyValue);
102  }
103  if (rFont.mobBold.has())
104  {
105  aPropertyValue.Name = "CharWeight";
106  aPropertyValue.Value <<= rFont.mobBold.get() ? awt::FontWeight::BOLD : awt::FontWeight::NORMAL;
107  aPropVec.push_back(aPropertyValue);
108  }
109  if (rFont.monSize.has())
110  {
111  aPropertyValue.Name = "CharHeight";
112  aPropertyValue.Value <<= double(rFont.monSize.get()) / 2.;
113  aPropVec.push_back(aPropertyValue);
114  }
115  if (rFont.monSpacing.has())
116  {
117  aPropertyValue.Name = "CharKerning";
118  // Value is not converted to mm100: SvxKerningItem::PutValue() gets
119  // called with nMemberId = 0, so no mm100 -> twips conversion will
120  // be done there.
121  aPropertyValue.Value <<= sal_Int16(rFont.monSpacing.get());
122  aPropVec.push_back(aPropertyValue);
123  }
124  if (rParagraph.moParaAdjust.has())
125  {
126  style::ParagraphAdjust eAdjust = style::ParagraphAdjust_LEFT;
127  if (rParagraph.moParaAdjust.get() == "center")
128  eAdjust = style::ParagraphAdjust_CENTER;
129  else if (rParagraph.moParaAdjust.get() == "right")
130  eAdjust = style::ParagraphAdjust_RIGHT;
131 
132  aPropertyValue.Name = "ParaAdjust";
133  aPropertyValue.Value <<= eAdjust;
134  aPropVec.push_back(aPropertyValue);
135  }
136 
137  // All paragraphs should be either undefined (default) or the same style,
138  // because it will only be applied to the entire shape, and not per-paragraph.
139  if (sParaStyle.isEmpty() )
140  {
141  if ( rParagraph.moParaStyleName.has() )
142  sParaStyle = rParagraph.moParaStyleName.get();
143  if ( bAmbiguousStyle )
144  bAmbiguousStyle = false; // both empty parastyle and ambiguous can only be true at the first paragraph
145  else
146  bAmbiguousStyle = rParagraph.moParaStyleName.has(); // ambiguous if both default and specified style used.
147  }
148  else if ( !bAmbiguousStyle )
149  {
150  if ( !rParagraph.moParaStyleName.has() )
151  bAmbiguousStyle = true; // ambiguous if both specified and default style used.
152  else if ( rParagraph.moParaStyleName.get() != sParaStyle )
153  bAmbiguousStyle = true; // ambiguous if two different styles specified.
154  }
155  if (rFont.moColor.has())
156  {
157  aPropertyValue.Name = "CharColor";
158  aPropertyValue.Value <<= rFont.moColor.get().toUInt32(16);
159  aPropVec.push_back(aPropertyValue);
160  }
161  xTextAppend->appendTextPortion(portion.maText, comphelper::containerToSequence(aPropVec));
162  }
163 
164  try
165  {
166  // Track the style in a grabBag for use later when style details are known.
168  uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY_THROW);
169  aGrabBag.update( xPropertySet->getPropertyValue("CharInteropGrabBag") );
170  aGrabBag["mso-pStyle"] <<= sParaStyle;
171  xPropertySet->setPropertyValue("CharInteropGrabBag", uno::makeAny(aGrabBag.getAsConstPropertyValueList()));
172  }
173  catch (const uno::Exception&)
174  {
175  TOOLS_WARN_EXCEPTION( "oox.vml","convert() grabbag exception" );
176  }
177 
178  // Remove the last character of the shape text, if it would be a newline.
179  uno::Reference< text::XTextCursor > xCursor = xTextAppend->createTextCursor();
180  xCursor->gotoEnd(false);
181  xCursor->goLeft(1, true);
182  if (xCursor->getString() == "\n")
183  xCursor->setString("");
184 
185  if ( maLayoutFlow != "vertical" )
186  return;
187 
188  uno::Reference<beans::XPropertySet> xProperties(xShape, uno::UNO_QUERY);
189 
190  // VML has the text horizontally aligned to left (all the time),
191  // v-text-anchor for vertical alignment, and vertical mode to swap the
192  // two. drawinglayer supports both horizontal and vertical alignment,
193  // but no vertical mode: we use T->B, R->L instead.
194  // As a result, we need to set horizontal adjustment here to 'right',
195  // that will result in vertical 'top' after writing mode is applied,
196  // which matches the VML behavior.
197  xProperties->setPropertyValue("TextHorizontalAdjust", uno::makeAny(drawing::TextHorizontalAdjust_RIGHT));
198 
199  xProperties->setPropertyValue( "TextWritingMode", uno::makeAny( text::WritingMode_TB_RL ) );
200 }
201 
202 } // namespace oox::vml
203 
204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
The shape model structure contains all properties shared by all types of shapes.
Definition: vmlshape.hxx:60
OptValue< OUString > moParaAdjust
Paragraph adjust (left, center, right, etc.)
Definition: vmltextbox.hxx:44
A text paragraph in a textbox.
Definition: vmltextbox.hxx:42
void appendPortion(const TextParagraphModel &rParagraph, const TextFontModel &rFont, const OUString &rText)
Appends a new text portion to the textbox.
Definition: vmltextbox.cxx:59
OptValue< sal_Int32 > monSpacing
Definition: vmltextbox.hxx:61
const TextFontModel * getFirstFont() const
Returns the font settings of the first text portion.
Definition: vmltextbox.cxx:64
OptValue< OUString > moNameAsian
Asian font name.
Definition: vmltextbox.hxx:52
css::uno::Sequence< css::beans::PropertyValue > getAsConstPropertyValueList() const
Font settings for a text portion in a textbox.
Definition: vmltextbox.hxx:49
OptValue< bool > mobBold
Definition: vmltextbox.hxx:58
void convert(const css::uno::Reference< css::drawing::XShape > &xShape) const
Definition: vmltextbox.cxx:77
const Type & get() const
Definition: helper.hxx:185
TextPortionModel(const TextParagraphModel &rParagraph, const TextFontModel &rFont, const OUString &rText)
Definition: vmltextbox.cxx:42
void update(const SequenceAsHashMap &rSource)
#define TOOLS_WARN_EXCEPTION(area, stream)
OUString getText() const
Returns the entire text of all text portions.
Definition: vmltextbox.cxx:69
OptValue< OUString > moParaStyleName
Definition: vmltextbox.hxx:45
OUString maLayoutFlow
Definition: vmltextbox.hxx:99
std::unique_ptr< char[]> aBuffer
Text maText
OptValue< OUString > moColor
Font color, HTML encoded, sort of.
Definition: vmltextbox.hxx:54
OptValue< OUString > moName
Font name.
Definition: vmltextbox.hxx:51
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
OptValue< OUString > moNameComplex
Complex font name.
Definition: vmltextbox.hxx:53
OptValue< sal_Int32 > monSize
Font size in twips.
Definition: vmltextbox.hxx:55
bool has() const
Definition: helper.hxx:181
PortionVector maPortions
Definition: vmltextbox.hxx:105
TextBox(ShapeTypeModel &rTypeModel)
Definition: vmltextbox.cxx:49