// global variables declared in fntcache.hxx // FontCache is created in txtinit.cxx TextInit_ and deleted in TextFinit
SwFntCache *pFntCache = nullptr; // last Font set by ChgFntCache
SwFntObj *pLastFont = nullptr;
// Computes the start and end position of an underline. This function is called // from the DrawText-method (for underlining misspelled words or smarttag terms). staticvoid lcl_calcLinePos( const CalcLinePosData &rData,
Point &rStart, Point &rEnd, TextFrameIndex const nStart, TextFrameIndex const nWrLen)
{
tools::Long nBlank = 0; const TextFrameIndex nEnd = nStart + nWrLen; const tools::Long nTmpSpaceAdd = rData.rInf.GetSpace() / SPACING_PRECISION_FACTOR;
// tdf#151968 // if start < end, OutputDevice::DrawWaveLine() will think it is a rotated // line, so we swap nStart and nEnd to avoid this. if ( rData.bBidiPor )
std::swap(rStart, rEnd);
if ( rData.bSwitchL2R )
{
rData.rInf.GetFrame()->SwitchLTRtoRTL( rStart );
rData.rInf.GetFrame()->SwitchLTRtoRTL( rEnd );
// tdf#151968 // We need to do this here as well for LTR text in a RTL paragraph.
std::swap(rStart, rEnd);
}
if ( rData.bSwitchH2V )
{
rData.rInf.GetFrame()->SwitchHorizontalToVertical( rStart );
rData.rInf.GetFrame()->SwitchHorizontalToVertical( rEnd );
}
}
// Returns the Ascent of the Font on the given output device; // it may be necessary to create the screen font first.
sal_uInt16 SwFntObj::GetFontAscent( const SwViewShell *pSh, const OutputDevice& rOut )
{
sal_uInt16 nRet = 0; const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
#if !defined(MACOSX) // #i89844# extleading is below the line for Mac // TODO: move extleading below the line for all platforms too
nRet += GetFontLeading( pSh, rRefDev ); #endif
// Returns the height of the Font on the given output device; // it may be necessary to create the screen font first.
sal_uInt16 SwFntObj::GetFontHeight( const SwViewShell* pSh, const OutputDevice& rOut )
{
sal_uInt16 nRet = 0; const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
#if OSL_DEBUG_LEVEL > 0 // Check if vcl did not change the meaning of GetTextHeight const FontMetric aOutMet( rRefDev.GetFontMetric() );
tools::Long nTmpPrtHeight = o3tl::narrowing<sal_uInt16>(aOutMet.GetAscent()) + aOutMet.GetDescent(); // #i106098#: do not compare with == here due to rounding error
OSL_ENSURE( std::abs(nTmpPrtHeight - m_nPrtHeight) < 3, "GetTextHeight != Ascent + Descent" ); #endif
// tdf#139418: MSO never applies ext leading to vertical text, even if the // NoLeading compatibility flag is unset. constbool bDisableExtLeading
= rIDSA.get(DocumentSettingId::MS_WORD_COMP_GRID_METRICS) && GetFont().IsVertical();
// pOut is the output device, not the reference device void SwFntObj::CreateScrFont( const SwViewShell& rSh, const OutputDevice& rOut )
{ if ( m_pScrFont ) return;
// any changes to the output device are reset at the end of the function
OutputDevice* pOut = const_cast<OutputDevice*>(&rOut);
// Save old font
vcl::Font aOldOutFont( pOut->GetFont() );
m_nScrHeight = USHRT_MAX;
// Condition for output font / refdev font adjustment
OutputDevice* pPrt = &rSh.GetRefDev();
if( !rSh.GetWin() ||
!rSh.GetViewOptions()->getBrowseMode() ||
rSh.GetViewOptions()->IsPrtFormat() )
{ // After CreatePrtFont m_pPrtFont is the font which is actually used // by the reference device
CreatePrtFont( *pPrt );
m_pPrinter = pPrt;
// save old reference device font
vcl::Font aOldPrtFnt( pPrt->GetFont() );
// set the font used at the reference device at the reference device // and the output device
pPrt->SetFont( *m_pPrtFont );
pOut->SetFont( *m_pPrtFont );
// This should be the default for pScrFont.
m_pScrFont = m_pPrtFont;
FontMetric aMet = pPrt->GetFontMetric( ); // Don't lose "faked" properties of the logical font that don't truly // exist in the physical font metrics which vcl which fake up for us
aMet.SetWeight(m_pScrFont->GetWeightMaybeAskConfig());
aMet.SetItalic(m_pScrFont->GetItalicMaybeAskConfig());
// reset original output device font
pOut->SetFont( aOldOutFont );
}
void SwFntObj::GuessLeading( const SwViewShell& #ifdefined(_WIN32)
rSh #endif
, const FontMetric& rMet )
{ // If leading >= 5, this seems to be enough leading. // Nothing has to be done. if ( rMet.GetInternalLeading() >= 5 )
{
m_nGuessedLeading = 0; return;
}
#ifdefined(_WIN32)
OutputDevice *pWin = rSh.GetWin() ?
rSh.GetWin()->GetOutDev() :
Application::GetDefaultDevice(); if ( pWin )
{
MapMode aTmpMap( MapUnit::MapTwip );
MapMode aOldMap = pWin->GetMapMode( );
pWin->SetMapMode( aTmpMap ); const vcl::Font aOldFnt( pWin->GetFont() );
pWin->SetFont( *m_pPrtFont ); const FontMetric aWinMet( pWin->GetFontMetric() ); const sal_uInt16 nWinHeight = sal_uInt16( aWinMet.GetFontSize().Height() ); if( m_pPrtFont->GetFamilyName().indexOf( aWinMet.GetFamilyName() ) != -1 )
{ // If the Leading on the Window is also 0, then it has to stay // that way (see also StarMath).
sal_Int32 nTmpLeading = aWinMet.GetInternalLeading(); if( nTmpLeading <= 0 )
{
pWin->SetFont( rMet );
nTmpLeading = pWin->GetFontMetric().GetInternalLeading(); if( nTmpLeading < 0 )
m_nGuessedLeading = 0; else
m_nGuessedLeading = sal_uInt16(nTmpLeading);
} else
{
m_nGuessedLeading = sal_uInt16(nTmpLeading); // Manta-Hack #50153#: // Wer beim Leading luegt, luegt moeglicherweise auch beim // Ascent/Descent, deshalb wird hier ggf. der Font ein wenig // tiefergelegt, ohne dabei seine Hoehe zu aendern. // (above original comment preserved for cultural reasons) // Those who lie about their Leading, may lie about their // Ascent/Descent as well, hence the Font will be lowered a // little without changing its height.
sal_Int32 nDiff = std::min( rMet.GetDescent() - aWinMet.GetDescent(),
aWinMet.GetAscent() - rMet.GetAscent() - nTmpLeading ); if( nDiff > 0 )
{
OSL_ENSURE( m_nPrtAscent < USHRT_MAX, "GuessLeading: PrtAscent-Fault" ); if ( m_nPrtAscent < USHRT_MAX )
m_nPrtAscent = m_nPrtAscent + o3tl::narrowing<sal_uInt16>(( 2 * nDiff ) / 5);
}
}
} else
{ // If all else fails, take 15% of the height, as empirically // determined by CL
m_nGuessedLeading = (nWinHeight * 15) / 100;
}
pWin->SetFont( aOldFnt );
pWin->SetMapMode( aOldMap );
} else
m_nGuessedLeading = 0; #else
m_nGuessedLeading = 0; #endif
}
// Set the font at the given output device; for screens it may be // necessary to do some adjustment first. void SwFntObj::SetDevFont( const SwViewShell *pSh, OutputDevice& rOut )
{ const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
// Here, we actually do not need the leading values, but by calling // GetFontLeading() we assure that the values are calculated for later use.
GetFontLeading( pSh, rRefDev );
}
// Draw wavy lines for spell and grammar errors only if font is large enough. // Lines for smart tags will always be drawn. if (pWList != rInf.GetSmartTags() && WRONG_SHOW_MIN >= nHght)
{ return;
}
SwForbidden::iterator pIter = rForbidden.begin(); if (rInf.GetOut().GetConnectMetaFile())
rInf.GetOut().Push();
const Color aCol( rInf.GetOut().GetLineColor() );
// iterate over all ranges stored in the respective SwWrongList do
{
nStart -= rInf.GetIdx();
if (stMetrics.aBounds.has_value())
{ if (nMaxAscent)
{
*nMaxAscent = static_cast<SwTwips>(std::ceil(-stMetrics.aBounds->Top()));
}
if (nMaxDescent)
{
*nMaxDescent = static_cast<SwTwips>(std::ceil(stMetrics.aBounds->Bottom()));
}
}
// tdf#88908: Adjust qualifying spaces to half of an ideographic space. // For compatibility, this must be done before all other kinds of justification. if (auto pSh = rExtraInf.GetShell(); pSh)
{ const IDocumentSettingAccess& rIDSA = pSh->getIDocumentSettingAccess(); if (rIDSA.get(DocumentSettingId::BALANCE_SPACES_AND_IDEOGRAPHIC_SPACES))
{ constauto* pFont = rExtraInf.GetFont(); bool bScriptIsCJK = (SwFontScript::CJK == pFont->GetActual());
// true if pOut is the printer and the printer has been used for formatting constbool bPrt = OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() &&
OUTDEV_PRINTER == rRefDev.GetOutDevType(); constbool bBrowse = ( pWin &&
rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
!rInf.GetShell()->GetViewOptions()->IsPrtFormat() &&
!rInf.GetBullet() &&
( rInf.GetSpace() || !rInf.GetKern() ) &&
!rInf.GetWrong() &&
!rInf.GetGrammarCheck() &&
!rInf.GetSmartTags() &&
!rInf.GetGreyWave() );
// bDirectPrint indicates that we can enter the branch which calls // the DrawText functions instead of calling the DrawTextArray functions constbool bDirectPrint = bPrt || bBrowse;
// Condition for output font / refdev font adjustment constbool bUseScrFont =
lcl_IsFontAdjustNecessary( rInf.GetOut(), rRefDev );
// robust: better use the printer font instead of using no font at all
OSL_ENSURE( pTmpFont, "No screen or printer font?" ); if ( ! pTmpFont )
pTmpFont = m_pPrtFont;
// HACK: LINESTYLE_WAVE must not be abused any more, hence the grey wave // line of the ExtendedAttributeSets will appear in the font color first
// be sure to have the correct layout mode at the printer if ( m_pPrinter )
{
m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
}
if ( bSwitchL2R )
rInf.GetFrame()->SwitchLTRtoRTL( aTextOriginPos );
if ( bSwitchH2V )
rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
// In the good old days we used to have a simple DrawText if the // output device is the printer. Now we need a DrawTextArray if // 1. KanaCompression is enabled // 2. Justified alignment // Simple kerning is handled by DrawStretchText if( rInf.GetSpace() || rInf.GetKanaComp() )
{
KernArray aKernArray;
GetTextArray(rInf.GetOut(), rInf, aKernArray);
std::vector<sal_Bool> aKashidaArray;
if ( LANGUAGE_THAI == aLang )
{ // Use rInf.GetSpace() because it has more precision than // nSpaceAdd:
SwScriptInfo::ThaiJustify( rInf.GetText(), &aKernArray,
rInf.GetIdx(), rInf.GetLen(),
rInf.GetNumberOfBlanks(),
rInf.GetSpace() );
// adding space to blanks is already done
bSpecialJust = true;
nSpaceAdd = 0;
}
}
}
double nKernSum = rInf.GetKern();
if ( bStretch || m_bPaintBlank || rInf.GetKern() || bSpecialJust )
{ for (sal_Int32 i = 0; i < sal_Int32(rInf.GetLen()); i++,
nKernSum += rInf.GetKern() )
{ if (CH_BLANK == rInf.GetText()[sal_Int32(rInf.GetIdx()) + i])
nKernSum += nSpaceAdd;
aKernArray[i] += nKernSum;
}
// In case of underlined/strike-through justified text // a blank at the end requires special handling: if( m_bPaintBlank && rInf.GetLen() && ( CH_BLANK ==
rInf.GetText()[sal_Int32(rInf.GetIdx() + rInf.GetLen())-1]))
{ // If it is a single underlined space, output 2 spaces: if (TextFrameIndex(1) == rInf.GetLen())
{
aKernArray[0] = rInf.GetWidth() + nSpaceAdd;
rInf.GetOut().DrawTextArray( aTextOriginPos, rInf.GetText(),
aKernArray, aKashidaArray, sal_Int32(rInf.GetIdx()), 1 );
} else
{
sal_Int32 nIndex(sal_Int32(rInf.GetLen()) - 2);
aKernArray[nIndex] += nSpaceAdd;
DrawTextArray(rInf.GetOut(), aTextOriginPos, rInf.GetText(), aKernArray,
aKashidaArray, sal_Int32{ rInf.GetIdx() },
sal_Int32{ rInf.GetLen() }, rInf.GetLayoutContext());
}
} else {
DrawTextArray(rInf.GetOut(), aTextOriginPos, rInf.GetText(), aKernArray,
aKashidaArray, sal_Int32{ rInf.GetIdx() },
sal_Int32{ rInf.GetLen() }, rInf.GetLayoutContext());
}
} else
{
Point aTmpPos( aTextOriginPos );
sal_Int32 j = 0;
sal_Int32 i; for( i = 0; i < sal_Int32(rInf.GetLen()); i++ )
{ if (CH_BLANK == rInf.GetText()[sal_Int32(rInf.GetIdx()) + i])
{
nKernSum += nSpaceAdd; if( j < i )
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
sal_Int32(rInf.GetIdx()) + j, i - j);
j = i + 1;
SwTwips nAdd = aKernArray[ i ] + nKernSum; if ( ( vcl::text::ComplexTextLayoutFlags::BiDiStrong | vcl::text::ComplexTextLayoutFlags::BiDiRtl ) == nMode )
nAdd *= -1;
aTmpPos.setX( aTextOriginPos.X() + nAdd );
}
} if( j < i )
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
sal_Int32(rInf.GetIdx()) + j, i - j);
}
} elseif( bStretch )
{
tools::Long nTmpWidth = rInf.GetWidth(); if( rInf.GetKern() && rInf.GetLen() && nTmpWidth > rInf.GetKern() )
nTmpWidth -= rInf.GetKern();
rInf.GetOut().DrawStretchText( aTextOriginPos, nTmpWidth,
rInf.GetText(),
sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()));
} elseif( rInf.GetKern() )
{ const tools::Long nTmpWidth = GetTextSize( rInf ).Width();
// OLE: no printer available // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" ) if ( m_pPrinter )
{ // pTmpFont has already been set as current font for rInf.GetOut() if ( m_pPrinter.get() != rInf.GetpOut() || pTmpFont != m_pPrtFont )
{ if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) )
m_pPrinter->SetFont( *m_pPrtFont );
}
xFormattingDevice = m_pPrinter;
} else
{
xFormattingDevice = &rInf.GetOut();
}
//tdf#152094 see if we can retain a subpixel factor int nSubPixels = 1;
MapMode aMapMode(xFormattingDevice->GetMapMode()); if (aMapMode.IsSimple() && aMapMode.GetMapUnit() == MapUnit::MapTwip)
{ if (xFormattingDevice->GetDPIX() == xFormattingDevice->GetDPIY())
{ int nRatio = xFormattingDevice->GetDPIX() / 1440; if (nRatio * 1440 == xFormattingDevice->GetDPIX())
nSubPixels = nRatio;
}
}
KernArray aKernArray(nSubPixels);
GetTextArray(*xFormattingDevice, rInf, aKernArray);
std::vector<sal_Bool> aKashidaArray;
// Modify Printer and ScreenArrays for special justifications
// adding space to blanks is already done
nSpaceAdd = 0;
}
}
}
if( bBullet )
{ // Copy the substring that will be painted, and replace spaces with // bullets, and everything else with space.
sal_Int32 nCopyStart = sal_Int32(rInf.GetIdx());
sal_Int32 nCopyLen = sal_Int32(rInf.GetLen());
// In case of a single underlined space in justified text, // have to output 2 spaces: if ((nCnt == TextFrameIndex(1)) && rInf.GetSpace() && (cChPrev == CH_BLANK))
{
aKernArray[0] = rInf.GetWidth() +
rInf.GetKern() +
(rInf.GetSpace() / SPACING_PRECISION_FACTOR);
if ( bSwitchL2R )
rInf.GetFrame()->SwitchLTRtoRTL( aTextOriginPos );
if ( bSwitchH2V )
rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
SwForbidden aForbidden; // draw line for smart tag data
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetSmartTags(), aCalcLinePosData, Size() ); // draw wave line for spell check errors // draw them BEFORE the grammar check lines to 'override' the latter in case of conflict. // reason: some grammar errors can only be found if spelling errors are fixed, // therefore we don't want the user to miss a spelling error.
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetWrong(), aCalcLinePosData, m_pPrtFont->GetFontSize() ); // draw wave line for grammar check errors
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetGrammarCheck(), aCalcLinePosData, m_pPrtFont->GetFontSize() );
}
}
sal_Int32 nLen = sal_Int32(rInf.GetLen());
if( nLen > 0 )
{
if ( bSwitchL2R )
rInf.GetFrame()->SwitchLTRtoRTL( aTextOriginPos );
if ( bSwitchH2V )
rInf.GetFrame()->SwitchHorizontalToVertical( aTextOriginPos );
sal_Int32 nIdx = sal_Int32(rInf.GetIdx());
DrawTextArray(rInf.GetOut(), aTextOriginPos, rInf.GetText(), aKernArray,
aKashidaArray, nIdx, nLen, rInf.GetLayoutContext()); if (bBullet)
{
rInf.GetOut().Push();
Color aPreviousColor = pTmpFont->GetColor();
// If the measure length is different from the length, then we are // measuring substring width for caret positioning, see SetMeasureLength() // use in TextCursor::GetCharRect_(). bool bCaret(nMsrLn != nLn);
// be sure to have the correct layout mode at the printer if ( m_pPrinter )
{
m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
}
// This is the part used e.g., for cursor travelling // See condition for DrawText or DrawTextArray (bDirectPrint)
KernArray aKernArray; if ( m_pPrinter && m_pPrinter.get() != rInf.GetpOut() )
{ if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) )
m_pPrinter->SetFont(*m_pPrtFont);
aTextSize.setHeight( m_pPrinter->GetTextHeight() );
if (nMsrLn)
{
aTextSize.setWidth(aKernArray[sal_Int32(nMsrLn) - 1]);
// Note that we can't simply use sal_Int(nMsrLn) - 1 as nSpaceCount // because a glyph may be made up of more than one characters.
sal_Int32 nSpaceCount = 0;
tools::Long nOldValue = aKernArray[0];
for(sal_Int32 i = 1; i < sal_Int32(nMsrLn); ++i)
{ if (nOldValue != aKernArray[i])
{
++nSpaceCount;
nOldValue = aKernArray[i];
}
}
if (rInf.GetKern())
aTextSize.AdjustWidth(nSpaceCount * rInf.GetKern());
}
// be sure to have the correct layout mode at the printer if ( m_pPrinter )
{
m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
GetTextArray(*m_pPrinter, rInf, aKernArray);
} else
{
GetTextArray(rInf.GetOut(), rInf, aKernArray);
}
// Kashida Justification if ( SwFontScript::CTL == nActual && rInf.GetSpace() )
{ if (SwScriptInfo::IsKashidaScriptText(rInf.GetText(), rInf.GetIdx(), rInf.GetLen()))
{ if (pSI && pSI->ParagraphContainsKashidaScript()
&& sw::Justify::KashidaJustify(pSI->GetKashidaPositions(), aKernArray, nullptr, static_cast<sal_Int32>(rInf.GetIdx()), static_cast<sal_Int32>(rInf.GetLen()),
nSpaceAdd))
{ // Intentionally do not clear nSpaceAdd for kashida justification. // The rest of the space will be handled below.
}
}
}
// step back if position is before the middle of the character // or if we do not want to go to the next character if ( nIdx > rInf.GetIdx() &&
( rInf.IsPosMatchesBounds() ||
( ( nRight > tools::Long( rInf.GetOffset() ) ) &&
( nRight - rInf.GetOffset() > rInf.GetOffset() - nLeft ) ) ) )
nCnt = nLastIdx - rInf.GetIdx(); // first half else
nCnt = nIdx - rInf.GetIdx(); // second half
if ( pSI )
rInf.SetCursorBidiLevel( pSI->DirType( nLastIdx ) );
return nCnt;
}
SwFntAccess::SwFntAccess( constvoid* & rnFontCacheId,
sal_uInt16 &rIndex, constvoid *pOwn, SwViewShell const *pSh, bool bCheck ) :
SwCacheAccess( *pFntCache, rnFontCacheId, rIndex ),
m_pShell( pSh )
{ // the used ctor of SwCacheAccess searches for rnFontCacheId+rIndex in the cache if ( m_pObj )
{ // fast case: known Font (rnFontCacheId), no need to check printer and zoom if ( !bCheck ) return;
// Font is known, but has to be checked
} else
{ // Font not known, must be searched
bCheck = false;
}
{
OutputDevice* pOut = nullptr;
sal_uInt16 nZoom = USHRT_MAX;
// Get the reference device if ( pSh )
{
pOut = &pSh->GetRefDev();
nZoom = pSh->GetViewOptions()->GetZoom();
}
SwFntObj *pFntObj; if ( bCheck )
{
pFntObj = Get(); if ( ( pFntObj->GetZoom( ) == nZoom ) &&
( pFntObj->m_pPrinter == pOut ) &&
pFntObj->GetPropWidth() == static_cast<SwSubFont const *>(pOwn)->GetPropWidth() )
{ return; // result of Check: Drucker+Zoom okay.
}
pFntObj->Unlock(); // forget this object, printer/zoom differs
m_pObj = nullptr;
}
// Search by font comparison, quite expensive! // Look for same font and same printer
pFntObj = pFntCache->First(); while ( pFntObj && !( pFntObj->m_aFont == *static_cast<vcl::Font const *>(pOwn) &&
pFntObj->GetZoom() == nZoom &&
pFntObj->GetPropWidth() == static_cast<SwSubFont const *>(pOwn)->GetPropWidth() &&
( !pFntObj->m_pPrinter || pFntObj->m_pPrinter == pOut ) ) )
pFntObj = SwFntCache::Next( pFntObj );
if( pFntObj && pFntObj->m_pPrinter.get() != pOut )
{ // found one without printer, let's see if there is one with // the same printer as well
SwFntObj *pTmpObj = pFntObj; while( pTmpObj && !( pTmpObj->m_aFont == *static_cast<vcl::Font const *>(pOwn) &&
pTmpObj->GetZoom()==nZoom && pTmpObj->m_pPrinter==pOut &&
pTmpObj->GetPropWidth() == static_cast<SwSubFont const *>(pOwn)->GetPropWidth() ) )
pTmpObj = SwFntCache::Next( pTmpObj ); if( pTmpObj )
pFntObj = pTmpObj;
}
if ( !pFntObj ) // Font has not been found, create one
{ // Have to create new Object, hence Owner must be a SwFont, later // the Owner will be the "MagicNumber"
SwCacheAccess::m_pOwner = pOwn;
pFntObj = Get(); // will create via NewObj() and lock
assert(pFntObj && "No Font, no Fun.");
} else// Font has been found, so we lock it.
{
pFntObj->Lock(); if (pFntObj->m_pPrinter.get() != pOut) // if no printer is known by now
{
OSL_ENSURE( !pFntObj->m_pPrinter, "SwFntAccess: Printer Changed" );
assert(pOut);
pFntObj->CreatePrtFont( *pOut );
pFntObj->m_pPrinter = pOut;
pFntObj->m_pScrFont = nullptr;
pFntObj->m_nGuessedLeading = USHRT_MAX;
pFntObj->m_nExtLeading = USHRT_MAX;
pFntObj->m_nPrtAscent = USHRT_MAX;
pFntObj->m_nPrtHeight = USHRT_MAX;
}
m_pObj = pFntObj;
}
// no matter if new or found, now the Owner of the Object is a // MagicNumber, and will be given to the SwFont, as well as the Index // for later direct access
rnFontCacheId = reinterpret_cast<void*>(reinterpret_cast<sal_IntPtr>(pFntObj->GetOwner()));
SwCacheAccess::m_pOwner = pFntObj->GetOwner();
rIndex = pFntObj->GetCachePos();
}
}
SwCacheObj *SwFntAccess::NewObj( )
{ // "MagicNumber" used to identify Fonts static std::uintptr_t fontCacheIdCounter = 0; // a new Font, a new "MagicNumber". returnnew SwFntObj( *static_cast<SwSubFont const *>(m_pOwner), ++fontCacheIdCounter, m_pShell );
}
// Uaaaaahhhh!!! In title case mode, we would get wrong results if ( bTitle && nLn )
{ // check if rInf.GetIdx() is begin of word if ( !g_pBreakIt->GetBreakIter()->isBeginWord(
rInf.GetText(), sal_Int32(rInf.GetIdx()),
g_pBreakIt->GetLocale( m_aSub[m_nActual].GetLanguage() ),
i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
{ // In this case, the beginning of aTmpText is wrong.
OUString aSnippetTmp(aSnippet.copy(0, 1));
aSnippetTmp = m_aSub[m_nActual].CalcCaseMap( aSnippetTmp );
aTmpText = aTmpText.replaceAt( 0, aSnippetTmp.getLength(), rtl::OUStringChar(aSnippet[0]) );
}
}
// tdf112290 tdf136588 Break the line correctly only if there is an image inline, // and the image wider than the line... if (GetCaseMap() == SvxCaseMap::SmallCaps && TextFrameIndex(COMPLETE_STRING) == nTextBreak2 &&
! bCompress && nTextWidth == 0) // If nTextWidth == 0 means the line is full, we have to break it
nTextBreak2 = TextFrameIndex(1);
if (pVSh && !bOutputToWindow && pVSh->GetViewOptions()->IsBlackFont())
{ if ( COL_BLACK != rFnt.GetColor() )
bChgFntColor = true;
if ( (COL_BLACK != GetOut().GetLineColor()) ||
(COL_BLACK != GetOut().GetOverlineColor()) )
bChgLineColor = true;
} else
{ // FontColor has to be changed if: // 1. FontColor = AUTO or 2. IsAlwaysAutoColor is set // LineColor has to be changed if: // 1. IsAlwaysAutoColor is set
if ( bChgFntColor )
{ // check if current background has a user defined setting
std::optional<Color> pCol; if (GetFont())
pCol = GetFont()->GetBackColor(); if( ! pCol || COL_TRANSPARENT == *pCol )
{ const SvxBrushItem* pItem;
SwRect aOrigBackRect;
drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
/// OD 21.08.2002 /// consider, that [GetBackgroundBrush(...)] can set <pCol> /// - see implementation in /core/layout/paintfrm.cxx /// OD 21.08.2002 #99657# /// There is a user defined setting for the background, if there /// is a background brush and its color is *not* "no fill"/"auto fill". if( GetFrame()->GetBackgroundBrush( aFillAttributes, pItem, pCol, aOrigBackRect, false, /*bConsiderTextBox=*/true ) )
{ if (aFillAttributes && aFillAttributes->isUsed())
{ // First see if fill attributes provide a color.
pCol = Color(aFillAttributes->getAverageColor(aGlobalRetoucheColor.getBColor()));
}
// If not, then fall back to the old brush item. if ( !pCol )
{
pCol = pItem->GetColor();
}
/// OD 30.08.2002 #99657# /// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it. if ( *pCol == COL_TRANSPARENT)
pCol.reset();
} else
pCol.reset();
}
// no user defined color at paragraph or font background if ( ! pCol )
pCol = aGlobalRetoucheColor;
if (pVSh && bOutputToWindow)
{ // here we determine the preferred window text color for painting const SwViewOption* pViewOption = pVSh->GetViewOptions(); if(pViewOption->IsPagePreview() &&
!officecfg::Office::Common::Accessibility::IsForPagePreviews::get())
nNewColor = COL_BLACK; else // we take the font color from the appearance page
nNewColor = pViewOption->GetFontColor();
}
// change painting color depending of dark/bright background if ((pVSh && !pVSh->GetWin()) || // ie. IsPrinting, see SwViewShell::GetWin()
svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR, false).nColor == COL_AUTO) // GetFontColor() uses the smart flag
{ if ( pCol->IsDark() )
nNewColor = COL_WHITE; else
nNewColor = COL_BLACK;
}
}
}
if ( bChgFntColor || bChgLineColor )
{
Color aNewColor( nNewColor );
if ( bChgFntColor )
{ if ( pFont && aNewColor != pFont->GetColor() )
{ // only set the new color at the font passed as argument
pFont->SetColor( aNewColor );
} elseif ( aNewColor != GetOut().GetFont().GetColor() )
{ // set new font with new color at output device
vcl::Font aFont( rFnt );
aFont.SetColor( aNewColor );
GetOut().SetFont( aFont );
}
}
// the underline and overline colors have to be set separately if ( bChgLineColor )
{ // get current font color or color set at output device
aNewColor = pFont ? pFont->GetColor() : GetOut().GetFont().GetColor(); if ( aNewColor != GetOut().GetLineColor() )
GetOut().SetLineColor( aNewColor ); if ( aNewColor != GetOut().GetOverlineColor() )
GetOut().SetOverlineColor( aNewColor );
}
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.