/* -*- 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 .
*/
// speed it up by removing all but 1.33x as many as the break pos.
sal_Int32 nEraseChars = std::max<sal_Int32>(4, rOrigStr.size() - (nIndex*4)/3); while(nEraseChars < static_cast<sal_Int32>(rOrigStr.size()) && GetTextWidth(aTmpStr.toString(), 0, aTmpStr.getLength()) > nMaxWidth)
{
aTmpStr = rOrigStr;
sal_Int32 i = (aTmpStr.getLength() - nEraseChars)/2;
aTmpStr.remove(i, nEraseChars++);
aTmpStr.insert(i, "...");
}
// We can have two cases: // 1) "packen" turns into "pak-ken" // 2) "Schiffahrt" turns into "Schiff-fahrt"
// In case 1 we need to replace a char // In case 2 we add a char
// Correct recognition is made harder by words such as // "Schiffahrtsbrennesseln", as the Hyphenator splits all // positions of the word and comes up with "Schifffahrtsbrennnesseln" // Thus, we cannot infer the aWord from the AlternativeWord's // index. // TODO: The whole junk will be made easier by a function in // the Hyphenator, as soon as AMA adds it.
sal_Int32 nAltStart = _nWordLen - 1;
sal_Int32 nTxtStart = nAltStart - (aAlt.getLength() - aWord.getLength());
sal_Int32 nTxtEnd = nTxtStart;
sal_Int32 nAltEnd = nAltStart;
// The area between nStart and nEnd is the difference // between AlternativeString and OriginalString while( nTxtEnd < aWord.getLength() && nAltEnd < aAlt.getLength() &&
aWord[nTxtEnd] != aAlt[nAltEnd] )
{
++nTxtEnd;
++nAltEnd;
}
// If a char was added, we notice it now: if( nAltEnd > nTxtEnd && nAltStart == nAltEnd &&
aWord[ nTxtEnd ] == aAlt[nAltEnd] )
{
++nAltEnd;
++nTxtStart;
++nTxtEnd;
}
MapMode aTargetMapMode( m_rTargetDevice.GetMapMode() );
SAL_WARN_IF(aTargetMapMode.GetOrigin() != Point(), "vcl", "uhm, the code below won't work here ...");
// normally, controls simulate "zoom" by "zooming" the font. This is responsible for (part of) the discrepancies // between text in Writer and text in controls in Writer, though both have the same font. // So, if we have a zoom set at the control, then we do not scale the font, but instead modify the map mode // to accommodate for the zoom.
aTargetMapMode.SetScaleX( aZoom ); // TODO: shouldn't this be "current_scale * zoom"?
aTargetMapMode.SetScaleY( aZoom );
// also, use a higher-resolution map unit than "pixels", which should save us some rounding errors when // translating coordinates between the reference device and the target device.
SAL_WARN_IF(aTargetMapMode.GetMapUnit() != MapUnit::MapPixel, "vcl", "this class is not expected to work with such target devices!"); // we *could* adjust all the code in this class to handle this case, but at the moment, it's not necessary const MapUnit eTargetMapUnit = m_rReferenceDevice.GetMapMode().GetMapUnit();
aTargetMapMode.SetMapUnit( eTargetMapUnit );
SAL_WARN_IF(aTargetMapMode.GetMapUnit() == MapUnit::MapPixel, "vcl", "a reference device which has map mode PIXEL?!");
m_rTargetDevice.SetMapMode( aTargetMapMode );
// now that the Zoom is part of the map mode, reset the target device's font to the "unzoomed" version
Font aDrawFont( aUnzoomedPointFont );
aDrawFont.SetFontSize( OutputDevice::LogicToLogic(aDrawFont.GetFontSize(), MapMode(MapUnit::MapPoint), MapMode(eTargetMapUnit)) );
_rTargetDevice.SetFont( aDrawFont );
// transfer font to the reference device
m_rReferenceDevice.Push( PushFlags::FONT | PushFlags::TEXTLAYOUTMODE );
Font aRefFont( aUnzoomedPointFont );
aRefFont.SetFontSize( OutputDevice::LogicToLogic(
aRefFont.GetFontSize(), MapMode(MapUnit::MapPoint), m_rReferenceDevice.GetMapMode()) );
m_rReferenceDevice.SetFont( aRefFont );
}
// determine text layout mode from the RTL-ness of the control whose text we render
text::ComplexTextLayoutFlags nTextLayoutMode = m_bRTLEnabled ? text::ComplexTextLayoutFlags::BiDiRtl : text::ComplexTextLayoutFlags::Default;
m_rReferenceDevice.SetLayoutMode( nTextLayoutMode );
m_rTargetDevice.SetLayoutMode( nTextLayoutMode | text::ComplexTextLayoutFlags::TextOriginLeft );
// ComplexTextLayoutFlags::TextOriginLeft is because when we do actually draw the text (in DrawText( Point, ... )), then // our caller gives us the left border of the draw position, regardless of script type, text layout, // and the like in our ctor, we set the map mode of the target device from pixel to twip, but our caller doesn't know this, // but passed pixel coordinates. So, adjust the rect.
tools::Rectangle aRect( m_rTargetDevice.PixelToLogic( _rRect ) ); if (i_pDeviceSize)
{ //if i_pDeviceSize is passed in here, it was the original pre logic-to-pixel size of _rRect
SAL_WARN_IF(std::abs(_rRect.GetSize().Width() - m_rTargetDevice.LogicToPixel(*i_pDeviceSize).Width()) > 1, "vcl", "DeviceSize width was expected to match Pixel width");
SAL_WARN_IF(std::abs(_rRect.GetSize().Height() - m_rTargetDevice.LogicToPixel(*i_pDeviceSize).Height()) > 1, "vcl", "DeviceSize height was expected to match Pixel height");
aRect.SetSize(*i_pDeviceSize);
}
if ( aTextRect.IsEmpty() && !aRect.IsEmpty() )
{ // this happens for instance if we're in a PaintToDevice call, where only a MetaFile is recorded, // but no actual painting happens, so our "DrawText( Point, ... )" is never called // In this case, calculate the rect from what OutputDevice::GetTextRect would give us. This has // the disadvantage of less accuracy, compared with the approach to calculate the rect from the // single "DrawText( Point, ... )" calls, since more intermediate arithmetic will translate // from ref- to target-units.
aTextRect = m_rTargetDevice.GetTextRect( aRect, _rText, _nStyle, nullptr, this );
}
// similar to above, the text rect now contains TWIPs (or whatever unit the ref device has), but the caller // expects pixel coordinates
aTextRect = m_rTargetDevice.LogicToPixel( aTextRect );
// convert the metric vector if ( _pVector )
{ for ( auto& rCharRect : *_pVector )
{
rCharRect = m_rTargetDevice.LogicToPixel( rCharRect );
}
}
// determine text layout mode from the RTL-ness of the control whose text we render
text::ComplexTextLayoutFlags nTextLayoutMode = m_bRTLEnabled ? text::ComplexTextLayoutFlags::BiDiRtl : text::ComplexTextLayoutFlags::Default;
m_rReferenceDevice.SetLayoutMode( nTextLayoutMode );
m_rTargetDevice.SetLayoutMode( nTextLayoutMode | text::ComplexTextLayoutFlags::TextOriginLeft );
// ComplexTextLayoutFlags::TextOriginLeft is because when we do actually draw the text (in DrawText( Point, ... )), then // our caller gives us the left border of the draw position, regardless of script type, text layout, // and the like in our ctor, we set the map mode of the target device from pixel to twip, but our caller doesn't know this, // but passed pixel coordinates. So, adjust the rect.
tools::Rectangle aRect( m_rTargetDevice.PixelToLogic( _rRect ) );
tools::Rectangle aTextRect = m_rTargetDevice.GetTextRect( aRect, _rText, _nStyle, nullptr, this );
//if o_pDeviceSize is available, stash the pre logic-to-pixel size in it if (o_pDeviceSize)
{
*o_pDeviceSize = aTextRect.GetSize();
}
// similar to above, the text rect now contains TWIPs (or whatever unit the ref device has), but the caller // expects pixel coordinates
aTextRect = m_rTargetDevice.LogicToPixel( aTextRect );
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.