/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
const SmNode * SmNode::GetLeftMost() const // returns leftmost node of current subtree. //! (this assumes the one with index 0 is always the leftmost subnode //! for the current node).
{ const SmNode *pNode = GetNumSubNodes() > 0 ?
GetSubNode(0) : nullptr;
case FontSizeType::PLUS:
aFntSize.AdjustHeight(nHeight ); break;
case FontSizeType::MINUS:
aFntSize.AdjustHeight( -nHeight ); break;
case FontSizeType::MULTIPLY:
aFntSize.setHeight( static_cast<tools::Long>(Fraction(aFntSize.Height()) * rSize) ); break;
case FontSizeType::DIVIDE: if (rSize != Fraction(0))
aFntSize.setHeight( static_cast<tools::Long>(Fraction(aFntSize.Height()) / rSize) ); break; default: break;
}
// check the requested size against maximum value constint nMaxVal = o3tl::convert(128, o3tl::Length::pt, SmO3tlLengthUnit()); if (aFntSize.Height() > nMaxVal)
aFntSize.setHeight( nMaxVal );
// quit immediately if 'rPoint' is inside the *should not // overlap with other rectangles* part. // This (partly) serves for getting the attributes in eg // "bar overstrike a". // ('nDist < 0' is used as *quick shot* to avoid evaluation of // the following expression, where the result is already determined) if (nDist < 0 && pFound->IsInsideRect(rPoint)) break;
}
}
}
}
void SmTableNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat) // arranges all subnodes in one column
{
SmNode *pNode;
size_t nSize = GetNumSubNodes();
// make distance depend on font size
tools::Long nDist = +(rFormat.GetDistance(DIS_VERTICAL)
* GetFont().GetFontSize().Height()) / 100;
if (nSize < 1) return;
// arrange subnodes and get maximum width of them
tools::Long nMaxWidth = 0,
nTmp; for (size_t i = 0; i < nSize; ++i)
{ if (nullptr != (pNode = GetSubNode(i)))
{ pNode->Arrange(rDev, rFormat); if ((nTmp = pNode->GetItalicWidth()) > nMaxWidth)
nMaxWidth = nTmp;
}
}
Point aPos;
SmRect::operator = (SmRect(nMaxWidth, 1)); for (size_t i = 0; i < nSize; ++i)
{ if (nullptr != (pNode = GetSubNode(i)))
{ const SmRect &rNodeRect = pNode->GetRect(); const SmNode *pCoNode = pNode->GetLeftMost();
RectHorAlign eHorAlign = pCoNode->GetRectHorAlign();
SmRect aRect(aTmpDev, &rFormat, u"a"_ustr, GetFont().GetBorderWidth());
mnFormulaBaseline = GetAlignM(); // move from middle position by constant - distance // between middle and baseline for single letter
mnFormulaBaseline += aRect.GetBaseline() - aRect.GetAlignM();
}
}
// Here we use the 'FNT_VARIABLE' font since it's ascent and descent in general fit better // to the rest of the formula compared to the 'FNT_MATH' font.
GetFont() = rFormat.GetFont(FNT_VARIABLE);
Flags() |= FontChangeMask::Face;
}
void SmLineNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat) // arranges all subnodes in one row with some extra space between
{
SmNode *pNode;
size_t nSize = GetNumSubNodes(); for (size_t i = 0; i < nSize; ++i)
{ if (nullptr != (pNode = GetSubNode(i)))
pNode->Arrange(rDev, rFormat);
}
if (nSize < 1)
{ // provide an empty rectangle with alignment parameters for the "current" // font (in order to make "a^1 {}_2^3 a_4" work correct, that is, have the // same sub-/supscript positions.) //! be sure to use a character that has explicitly defined HiAttribut //! line in rect.cxx such as 'a' in order to make 'vec a' look same to //! 'vec {a}'.
SmRect::operator = (SmRect(aTmpDev, &rFormat, u"a"_ustr,
GetFont().GetBorderWidth())); // make sure that the rectangle occupies (almost) no space
SetWidth(1);
SetItalicSpaces(0, 0); return;
}
// make distance depend on font size
tools::Long nDist = (rFormat.GetDistance(DIS_HORIZONTAL) * GetFont().GetFontSize().Height()) / 100; if (!IsUseExtraSpaces())
nDist = 0;
Point aPos; // copy the first node into LineNode and extend by the others if (nullptr != (pNode = GetSubNode(0)))
SmRect::operator = (pNode->GetRect());
for (size_t i = 1; i < nSize; ++i)
{ if (nullptr != (pNode = GetSubNode(i)))
{
aPos = pNode->AlignTo(*this, RectPos::Right, RectHorAlign::Center, RectVerAlign::Baseline);
// add horizontal space to the left for each but the first sub node
aPos.AdjustX(nDist );
// from this calculate topleft edge of 'rExtra'
aPos.AdjustX( -(rExtra.GetWidth() + rExtra.GetItalicRightSpace()) );
aPos.AdjustY( -(rExtra.GetHeight()) ); // if there's enough space move a bit less to the right // examples: "nroot i a", "nroot j a" // (it looks better if we don't use italic-spaces here)
tools::Long nX = rRootSymbol.GetLeft() + (rSymSize.Width() * 30) / 100; if (aPos.X() > nX)
aPos.setX( nX );
return aPos;
}
}
void SmRootNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
{ //! pExtra needs to have the smaller index than pRootSym in order to //! not to get the root symbol but the pExtra when clicking on it in the //! GraphicWindow. (That is because of the simplicity of the algorithm //! that finds the node corresponding to a mouseclick in the window.)
SmNode *pExtra = GetSubNode(0),
*pRootSym = GetSubNode(1),
*pBody = GetSubNode(2);
assert(pRootSym);
assert(pBody);
// font specialist advised to change the width first
pRootSym->AdaptToY(rDev, nHeight);
pRootSym->AdaptToX(rDev, pBody->GetItalicWidth());
pRootSym->Arrange(rDev, rFormat);
// Set the top and bottom of the root symbol to the top and bottom of its glyph bounding rect, // to get accurate position of the root symbol.
SmRect rRootSymRect = pRootSym->AsGlyphRect();
pRootSym->SetTop(rRootSymRect.GetTop());
pRootSym->SetBottom(rRootSymRect.GetBottom());
// font specialist advised to change the width first
pLine->AdaptToY(rDev, nThick);
pLine->AdaptToX(rDev, nWidth + 2 * nExtLen);
pLine->Arrange(rDev, rFormat);
// get horizontal alignment for numerator const SmNode *pLM = pNum->GetLeftMost();
RectHorAlign eHorAlign = pLM->GetRectHorAlign();
// move numerator to its position
Point aPos = pNum->AlignTo(*pLine, RectPos::Top, eHorAlign, RectVerAlign::Baseline);
aPos.AdjustY( -nNumDist );
pNum->MoveTo(aPos);
// get horizontal alignment for denominator
pLM = pDenom->GetLeftMost();
eHorAlign = pLM->GetRectHorAlign();
// move denominator to its position
aPos = pDenom->AlignTo(*pLine, RectPos::Bottom, eHorAlign, RectVerAlign::Baseline);
aPos.AdjustY(nDenomDist );
pDenom->MoveTo(aPos);
/// @return value of the determinant formed by the two points double Det(const Point &rHeading1, const Point &rHeading2)
{ return rHeading1.X() * rHeading2.Y() - rHeading1.Y() * rHeading2.X();
}
/// Is true iff the point 'rPoint1' belongs to the straight line through 'rPoint2' /// and has the direction vector 'rHeading2' bool IsPointInLine(const Point &rPoint1, const Point &rPoint2, const Point &rHeading2)
{
assert(rHeading2 != Point());
// are the direction vectors linearly dependent? double fDet = Det(rHeading1, rHeading2); if (fabs(fDet) < eps)
{
nRes = IsPointInLine(rPoint1, rPoint2, rHeading2) ? USHRT_MAX : 0;
rResult = nRes ? rPoint1 : Point();
} else
{ // here we do not pay attention to the computational accuracy // (that would be more complicated and is not really worth it in this case) double fLambda = ( (rPoint1.Y() - rPoint2.Y()) * rHeading2.X()
- (rPoint1.X() - rPoint2.X()) * rHeading2.Y())
/ fDet;
rResult = Point(rPoint1.X() + static_cast<tools::Long>(fLambda * rHeading1.X()),
rPoint1.Y() + static_cast<tools::Long>(fLambda * rHeading1.Y()));
}
return nRes;
}
}
/// @return position and size of the diagonal line /// premise: SmRect of the node defines the limitation(!) consequently it has to be known upfront void SmBinDiagonalNode::GetOperPosSize(Point &rPos, Size &rSize, const Point &rDiagPoint, double fAngleDeg) const
tools::Long nLeft, nRight, nTop, nBottom; // margins of the rectangle for the diagonal
Point aPoint; if (IsAscending())
{ // determine top right corner
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectTop), aRightHdg,
rDiagPoint, aDiagHdg); // is there a point of intersection with the top border? if (aPoint.X() <= nRectRight)
{
nRight = aPoint.X();
nTop = nRectTop;
} else
{ // there has to be a point of intersection with the right border!
GetLineIntersectionPoint(aPoint,
Point(nRectRight, nRectTop), aDownHdg,
rDiagPoint, aDiagHdg);
nRight = nRectRight;
nTop = aPoint.Y();
}
// determine bottom left corner
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectBottom), aRightHdg,
rDiagPoint, aDiagHdg); // is there a point of intersection with the bottom border? if (aPoint.X() >= nRectLeft)
{
nLeft = aPoint.X();
nBottom = nRectBottom;
} else
{ // there has to be a point of intersection with the left border!
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectTop), aDownHdg,
rDiagPoint, aDiagHdg);
nLeft = nRectLeft;
nBottom = aPoint.Y();
}
} else
{ // determine top left corner
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectTop), aRightHdg,
rDiagPoint, aDiagHdg); // is there a point of intersection with the top border? if (aPoint.X() >= nRectLeft)
{
nLeft = aPoint.X();
nTop = nRectTop;
} else
{ // there has to be a point of intersection with the left border!
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectTop), aDownHdg,
rDiagPoint, aDiagHdg);
nLeft = nRectLeft;
nTop = aPoint.Y();
}
// determine bottom right corner
GetLineIntersectionPoint(aPoint,
Point(nRectLeft, nRectBottom), aRightHdg,
rDiagPoint, aDiagHdg); // is there a point of intersection with the bottom border? if (aPoint.X() <= nRectRight)
{
nRight = aPoint.X();
nBottom = nRectBottom;
} else
{ // there has to be a point of intersection with the right border!
GetLineIntersectionPoint(aPoint,
Point(nRectRight, nRectTop), aDownHdg,
rDiagPoint, aDiagHdg);
void SmBinDiagonalNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
{ // Both arguments have to get into the SubNodes before the Operator so that clicking // within the GraphicWindow sets the FormulaCursor correctly (cf. SmRootNode)
SmNode *pLeft = GetSubNode(0),
*pRight = GetSubNode(1),
*pLine = GetSubNode(2);
assert(pLeft);
assert(pRight);
assert(pLine && pLine->GetType() == SmNodeType::PolyLine);
//! some routines being called extract some info from the OutputDevice's //! font (eg the space to be used for borders OR the font name(!!)). //! Thus the font should reflect the needs and has to be set!
SmTmpDevice aTmpDev (rDev, true);
aTmpDev.SetFont(GetFont());
// determine position and size of diagonal line
Size aTmpSize;
GetOperPosSize(aPos, aTmpSize, aLogCenter, IsAscending() ? 60.0 : -60.0);
// font specialist advised to change the width first
pOper->AdaptToY(aTmpDev, aTmpSize.Height());
pOper->AdaptToX(aTmpDev, aTmpSize.Width()); // and make it active
pOper->Arrange(aTmpDev, rFormat);
// line that separates sub- and supscript rectangles
tools::Long nDelimLine = SmFromTo(GetAlignB(), GetAlignT(), 0.4);
Point aPos;
tools::Long nDelta, nDist;
// iterate over all possible sub-/supscripts
SmRect aTmpRect (rBodyRect); for (int i = 0; i < SUBSUP_NUM_ENTRIES; i++)
{
SmSubSup eSubSup = static_cast<SmSubSup>(i);
SmNode *pSubSup = GetSubSup(eSubSup);
if (!pSubSup) continue;
// switch position of limits if we are in textmode if (rFormat.IsTextmode() && (GetToken().nGroup & TG::Limit)) switch (eSubSup)
{ case CSUB: eSubSup = RSUB; break; case CSUP: eSubSup = RSUP; break; default: break;
}
// prevent sub-/supscripts from diminishing in size // (as would be in "a_{1_{2_{3_4}}}") if (GetFont().GetFontSize().Height() > rFormat.GetBaseSize().Height() / 3)
{
sal_uInt16 nIndex = (eSubSup == CSUB || eSubSup == CSUP) ?
SIZ_LIMITS : SIZ_INDEX;
Fraction aFraction ( rFormat.GetRelSize(nIndex), 100 );
pSubSup->SetSize(aFraction);
}
// determine oversize in %
sal_uInt16 nPerc = 0; if (!bIsABS && bScale)
{ // in case of oversize braces...
sal_uInt16 nIndex = GetScaleMode() == SmScaleMode::Height ?
DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
nPerc = rFormat.GetDistance(nIndex);
}
// determine the height for the braces
tools::Long nBraceHeight; if (bScale)
{
nBraceHeight = pBody->GetType() == SmNodeType::Bracebody ? static_cast<SmBracebodyNode *>(pBody)->GetBodyHeight()
: pBody->GetHeight();
nBraceHeight += 2 * (nBraceHeight * nPerc / 100);
} else
nBraceHeight = nFaceHeight;
// distance to the argument
nPerc = bIsABS ? 0 : rFormat.GetDistance(DIS_BRACKETSPACE);
tools::Long nDist = nFaceHeight * nPerc / 100;
// if wanted, scale the braces to the wanted size if (bScale)
{
Size aTmpSize (pLeft->GetFont().GetFontSize());
OSL_ENSURE(pRight->GetFont().GetFontSize() == aTmpSize, "Sm : different font sizes");
aTmpSize.setWidth( std::min(nBraceHeight * 60 / 100,
rFormat.GetBaseSize().Height() * 3 / 2) ); // correction factor since change from StarMath to OpenSymbol font // because of the different font width in the FontMetric
aTmpSize.setWidth( aTmpSize.Width() * 182 );
aTmpSize.setWidth( aTmpSize.Width() / 267 );
// required in order to make "\(a\) - (a) - left ( a right )" look alright
RectVerAlign eVerAlign = bScale ? RectVerAlign::CenterY : RectVerAlign::Baseline;
// arrange arguments for (size_t i = 0; i < nNumSubNodes; i += 2)
GetSubNode(i)->Arrange(rDev, rFormat);
// build reference rectangle with necessary info for vertical alignment
SmRect aRefRect (*GetSubNode(0)); for (size_t i = 0; i < nNumSubNodes; i += 2)
{
SmRect aTmpRect (*GetSubNode(i));
Point aPos = aTmpRect.AlignTo(aRefRect, RectPos::Right, RectHorAlign::Center, RectVerAlign::Baseline);
aTmpRect.MoveTo(aPos);
aRefRect.ExtendBy(aTmpRect, RectCopyMBL::Xor);
}
mnBodyHeight = aRefRect.GetHeight();
// scale separators to required height and arrange them bool bScale = GetScaleMode() == SmScaleMode::Height || rFormat.IsScaleNormalBrackets();
tools::Long nHeight = bScale ? aRefRect.GetHeight() : GetFont().GetFontSize().Height();
sal_uInt16 nIndex = GetScaleMode() == SmScaleMode::Height ?
DIS_BRACKETSIZE : DIS_NORMALBRACKETSIZE;
sal_uInt16 nPerc = rFormat.GetDistance(nIndex); if (bScale)
nHeight += 2 * (nHeight * nPerc / 100); for (size_t i = 1; i < nNumSubNodes; i += 2)
{
SmNode *pNode = GetSubNode(i);
pNode->AdaptToY(rDev, nHeight);
pNode->Arrange(rDev, rFormat);
}
// horizontal distance between argument and brackets or separators
tools::Long nDist = GetFont().GetFontSize().Height()
* rFormat.GetDistance(DIS_BRACKETSPACE) / 100;
SmNode *pLeft = GetSubNode(0);
SmRect::operator = (*pLeft); for (size_t i = 1; i < nNumSubNodes; ++i)
{ bool bIsSeparator = i % 2 != 0;
RectVerAlign eVerAlign = bIsSeparator ? RectVerAlign::CenterY : RectVerAlign::Baseline;
// size is the same as for limits for this part
pScript->SetSize( Fraction( rFormat.GetRelSize(SIZ_LIMITS), 100 ) ); // braces are a bit taller than usually
pBrace ->SetSize( Fraction(3, 2) );
tools::Long nItalicWidth = pBody->GetItalicWidth(); if (nItalicWidth > 0)
pBrace->AdaptToX(aTmpDev, nItalicWidth);
tools::Long SmOperNode::CalcSymbolHeight(const SmNode &rSymbol, const SmFormat &rFormat) const // returns the font height to be used for operator-symbol
{
tools::Long nHeight = GetFont().GetFontSize().Height();
void SmAlignNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat) // set alignment within the entire subtree (including current node)
{
assert(GetNumSubNodes() == 1);
SmNode *pNode = GetSubNode(0);
assert(pNode);
RectHorAlign eHorAlign = RectHorAlign::Center; switch (GetToken().eType)
{ case TALIGNL: eHorAlign = RectHorAlign::Left; break; case TALIGNC: eHorAlign = RectHorAlign::Center; break; case TALIGNR: eHorAlign = RectHorAlign::Right; break; default: break;
}
SetRectHorAlign(eHorAlign);
void SmFontNode::Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell, int nDepth)
{ //! prepare subnodes first
SmNode::Prepare(rFormat, rDocShell, nDepth);
int nFnt = -1; switch (GetToken().eType)
{ case TFIXED: nFnt = FNT_FIXED; break; case TSANS: nFnt = FNT_SANS; break; case TSERIF: nFnt = FNT_SERIF; break; default: break;
} if (nFnt != -1)
{ GetFont() = rFormat.GetFont( sal::static_int_cast< sal_uInt16 >(nFnt) );
SetFont(GetFont());
}
//! prevent overwrites of this font by 'Arrange' or 'SetFont' calls of //! other font nodes (those with lower depth in the tree)
Flags() |= FontChangeMask::Face;
}
switch (GetToken().eType)
{ case TSIZE :
pNode->SetFontSize(maFontSize, meSizeType); break; case TSANS : case TSERIF : case TFIXED :
pNode->SetFont(GetFont()); break; case TUNKNOWN : break; // no assertion on "font <?> <?>"
case TPHANTOM : SetPhantom(true); break; case TBOLD : SetAttribute(FontAttribute::Bold); break; case TITALIC : SetAttribute(FontAttribute::Italic); break; case TNBOLD : ClearAttribute(FontAttribute::Bold); break; case TNITALIC : ClearAttribute(FontAttribute::Italic); break;
// Using HTML CSS Level 1 standard case TRGB : case TRGBA : case THTMLCOL : case TMATHMLCOL : case TDVIPSNAMESCOL: case TICONICCOL : case THEX :
nc = GetToken().cMathChar.toUInt32(16);
SetColor(Color(ColorTransparency, nc)); break;
void SmPolyLineNode::Arrange(OutputDevice &rDev, const SmFormat &rFormat)
{ //! some routines being called extract some info from the OutputDevice's //! font (eg the space to be used for borders OR the font name(!!)). //! Thus the font should reflect the needs and has to be set!
SmTmpDevice aTmpDev (rDev, true);
aTmpDev.SetFont(GetFont());
void SmRootSymbolNode::AdaptToY(OutputDevice &rDev, tools::Long nHeight)
{ // some additional length so that the horizontal // bar will be positioned above the argument
SmMathSymbolNode::AdaptToY(rDev, nHeight + nHeight / 10);
}
//! use this method in order to have 'SmRect::HasAlignInfo() == true' //! and thus having the attribute-fences updated in 'SmRect::ExtendBy'
SmRect::operator = (SmRect(nWidth, nHeight));
}
// default setting for horizontal alignment of nodes with TTEXT // content is as alignl (cannot be done in Arrange since it would // override the settings made by an SmAlignNode before) if (TTEXT == GetToken().eType)
SetRectHorAlign( RectHorAlign::Left );
if (IsItalic( GetFont() ))
Attributes() |= FontAttribute::Italic; if (IsBold( GetFont() ))
Attributes() |= FontAttribute::Bold;
// special handling for ':' where it is a token on its own and is likely // to be used for mathematical notations. (E.g. a:b = 2:3) // In that case it should not be displayed in italic. if (maText.getLength() == 1 && GetToken().aText[0] == ':')
Attributes() &= ~FontAttribute::Italic;
// Arabic text should not be italic, so we check for any character in Arabic script and // remove italic attribute. if (!maText.isEmpty())
{
sal_Int32 nIndex = 0; while (nIndex < maText.getLength())
{
sal_uInt32 cChar = maText.iterateCodePoints(&nIndex); if (u_getIntPropertyValue(cChar, UCHAR_SCRIPT) == USCRIPT_ARABIC)
{
Attributes() &= ~FontAttribute::Italic; break;
}
}
}
};
//For whatever unicode glyph that equation editor doesn't ship with that //we have a possible match we can munge it to. switch (nIn)
{ case 0x2223:
nIn = '|'; break; default: break;
}
aPos = aLineRect.AlignTo(*this, RectPos::Bottom, RectHorAlign::Center, RectVerAlign::Baseline); if (i > 0)
aPos.AdjustY(nVerDist );
// move 'aLineRect' and rectangles in that line to final position
Point aDelta(0, // since horizontal alignment is already done
aPos.Y() - aLineRect.GetTop());
aLineRect.Move(aDelta); for (size_t j = 0; j < mnNumCols; ++j)
{ if (nullptr != (pNode = GetSubNode(i * mnNumCols + j)))
pNode->Move(aDelta);
}
void SmMathSymbolNode::AdaptToX(OutputDevice &rDev, tools::Long nWidth)
{ // Since there is no function to do this, we try to approximate it:
Size aFntSize (GetFont().GetFontSize());
//! however the result is a bit better with 'nWidth' as initial font width
aFntSize.setWidth( nWidth );
GetFont().SetSize(aFntSize);
// Since we only want to scale the height, we might have // to determine the font width in order to keep it if (aFntSize.Width() == 0)
{
rDev.Push(vcl::PushFlags::FONT | vcl::PushFlags::MAPMODE);
rDev.SetFont(GetFont());
aFntSize.setWidth( rDev.GetFontMetric().GetFontSize().Width() );
rDev.Pop();
}
OSL_ENSURE(aFntSize.Width() != 0, "Sm: ");
//! however the result is a bit better with 'nHeight' as initial //! font height
aFntSize.setHeight( nHeight );
GetFont().SetSize(aFntSize);
GetFont() = rFormat.GetFont(GetFontDesc()); // use same font size as is used for variables
GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetFontSize() );
OSL_ENSURE(GetFont().GetCharSet() == RTL_TEXTENCODING_SYMBOL ||
GetFont().GetCharSet() == RTL_TEXTENCODING_UNICODE, "wrong charset for character from StarMath/OpenSymbol font");
OUString aSymbolSetName = SmLocalizedSymbolData::GetExportSymbolSetName(pSym->GetSymbolSetName()); if (aSymbolSetName == "Greek")
bIsGreekSymbol = true; elseif (aSymbolSetName == "Special")
bIsSpecialSymbol = true; elseif (aSymbolSetName == "Arabic")
bIsArabic = true;
} else
{
SetText( GetToken().aText );
GetFont() = rFormat.GetFont(FNT_VARIABLE);
} // use same font size as is used for variables
GetFont().SetSize( rFormat.GetFont( FNT_VARIABLE ).GetFontSize() );
// Actually only WEIGHT_NORMAL and WEIGHT_BOLD should occur... However, the sms-file also // contains e.g. 'WEIGHT_ULTRALIGHT'. Consequently, compare here with '>' instead of '!='. // (In the long term the necessity for 'PrepareAttribut' and thus also for this here should be dropped)
//! see also SmFontStyles::GetStyleName if (IsItalic( GetFont() ))
SetAttribute(FontAttribute::Italic); if (IsBold( GetFont() ))
SetAttribute(FontAttribute::Bold);
// Here it need/should not be the StarMath font, so that for the character // used in Arrange a normal (non-clipped) rectangle is generated
GetFont() = rFormat.GetFont(FNT_VARIABLE);
// make distance depend on the font height // (so that it increases when scaling (e.g. size *2 {a ~ b})
tools::Long nDist = GetFont().GetFontSize().Height() / 10,
nSpace = mnNum * nDist;
// get a SmRect with Baseline and all the bells and whistles
SmRect::operator = (SmRect(aTmpDev, &rFormat, OUString(' '),
GetFont().GetBorderWidth()));
// and resize it to the requested size
SetItalicSpaces(0, 0);
SetWidth(nSpace);
}
/**************************************************************************/ //Implementation of all accept methods for SmVisitor
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.