Kaydet (Commit) da163512 authored tarafından Khaled Hosny's avatar Khaled Hosny

Simplify PDFWriterImpl::drawLayout

Call SalLayout::GetNextGlyphs with one glyph at a time while collecting
glyphs to draw, which allows us to simplify the code a bit and helps
simplify my next patch.

Change-Id: I5c9ddb7469301d8fbc6a15695c01af7b0879685a
Reviewed-on: https://gerrit.libreoffice.org/53384Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarKhaled Hosny <khaledhosny@eglug.org>
üst e0201bbb
...@@ -6237,67 +6237,46 @@ sal_Int32 PDFWriterImpl::getSystemFont( const vcl::Font& i_rFont ) ...@@ -6237,67 +6237,46 @@ sal_Int32 PDFWriterImpl::getSystemFont( const vcl::Font& i_rFont )
return nFontID; return nFontID;
} }
void PDFWriterImpl::registerGlyphs( int nGlyphs, void PDFWriterImpl::registerGlyph(const GlyphItem* pGlyph,
const GlyphItem** pGlyphs, const PhysicalFontFace* pFont,
sal_Int32* pGlyphWidths, const std::vector<sal_Ucs>& rCodeUnits,
sal_Ucs* pCodeUnits, sal_uInt8& nMappedGlyph,
sal_Int32 const * pCodeUnitsPerGlyph, sal_Int32& nMappedFontObject)
sal_uInt8* pMappedGlyphs,
sal_Int32* pMappedFontObjects,
const PhysicalFontFace* pFallbackFonts[] )
{ {
SalGraphics *pGraphics = m_pReferenceDevice->GetGraphics(); const int nFontGlyphId = pGlyph->maGlyphId;
FontSubset& rSubset = m_aSubsets[ pFont ];
if (!pGraphics) // search for font specific glyphID
return; FontMapping::iterator it = rSubset.m_aMapping.find( nFontGlyphId );
if( it != rSubset.m_aMapping.end() )
const PhysicalFontFace* pDevFont = m_pReferenceDevice->mpFontInstance->maFontSelData.mpFontData;
sal_Ucs* pCurUnicode = pCodeUnits;
for( int i = 0; i < nGlyphs; pCurUnicode += pCodeUnitsPerGlyph[i] , i++ )
{ {
const int nFontGlyphId = pGlyphs[i]->maGlyphId; nMappedFontObject = it->second.m_nFontID;
const PhysicalFontFace* pCurrentFont = pFallbackFonts[i] ? pFallbackFonts[i] : pDevFont; nMappedGlyph = it->second.m_nSubsetGlyphID;
}
FontSubset& rSubset = m_aSubsets[ pCurrentFont ]; else
// search for font specific glyphID {
FontMapping::iterator it = rSubset.m_aMapping.find( nFontGlyphId ); // create new subset if necessary
if( it != rSubset.m_aMapping.end() ) if( rSubset.m_aSubsets.empty()
|| (rSubset.m_aSubsets.back().m_aMapping.size() > 254) )
{ {
pMappedFontObjects[i] = it->second.m_nFontID; rSubset.m_aSubsets.emplace_back( m_nNextFID++ );
pMappedGlyphs[i] = it->second.m_nSubsetGlyphID;
} }
else
{
// create new subset if necessary
if( rSubset.m_aSubsets.empty()
|| (rSubset.m_aSubsets.back().m_aMapping.size() > 254) )
{
rSubset.m_aSubsets.emplace_back( m_nNextFID++ );
}
// copy font id // copy font id
pMappedFontObjects[i] = rSubset.m_aSubsets.back().m_nFontID; nMappedFontObject = rSubset.m_aSubsets.back().m_nFontID;
// create new glyph in subset // create new glyph in subset
sal_uInt8 nNewId = sal::static_int_cast<sal_uInt8>(rSubset.m_aSubsets.back().m_aMapping.size()+1); sal_uInt8 nNewId = sal::static_int_cast<sal_uInt8>(rSubset.m_aSubsets.back().m_aMapping.size()+1);
pMappedGlyphs[i] = nNewId; nMappedGlyph = nNewId;
// add new glyph to emitted font subset // add new glyph to emitted font subset
GlyphEmit& rNewGlyphEmit = rSubset.m_aSubsets.back().m_aMapping[ nFontGlyphId ]; GlyphEmit& rNewGlyphEmit = rSubset.m_aSubsets.back().m_aMapping[ nFontGlyphId ];
rNewGlyphEmit.setGlyphId( nNewId ); rNewGlyphEmit.setGlyphId( nNewId );
for( sal_Int32 n = 0; n < pCodeUnitsPerGlyph[i]; n++ ) for (const auto nCode : rCodeUnits)
rNewGlyphEmit.addCode( pCurUnicode[n] ); rNewGlyphEmit.addCode(nCode);
// add new glyph to font mapping // add new glyph to font mapping
Glyph& rNewGlyph = rSubset.m_aMapping[ nFontGlyphId ]; Glyph& rNewGlyph = rSubset.m_aMapping[ nFontGlyphId ];
rNewGlyph.m_nFontID = pMappedFontObjects[i]; rNewGlyph.m_nFontID = nMappedFontObject;
rNewGlyph.m_nSubsetGlyphID = nNewId; rNewGlyph.m_nSubsetGlyphID = nNewId;
}
if (!getReferenceDevice()->AcquireGraphics())
return;
pGlyphWidths[i] = m_aFontCache.getGlyphWidth( pCurrentFont,
nFontGlyphId,
pGlyphs[i]->IsVertical(),
pGraphics );
} }
} }
...@@ -6566,17 +6545,10 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool ...@@ -6566,17 +6545,10 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
const int nMaxGlyphs = 256; const int nMaxGlyphs = 256;
const GlyphItem* pGlyphs[nMaxGlyphs] = { nullptr }; const GlyphItem* pGlyph = nullptr;
const PhysicalFontFace* pFallbackFonts[nMaxGlyphs] = { nullptr }; const PhysicalFontFace* pFallbackFont = nullptr;
sal_Int32 pGlyphWidths[nMaxGlyphs];
sal_uInt8 pMappedGlyphs[nMaxGlyphs];
sal_Int32 pMappedFontObjects[nMaxGlyphs];
std::vector<sal_Ucs> aCodeUnits; std::vector<sal_Ucs> aCodeUnits;
aCodeUnits.reserve(nMaxGlyphs);
std::vector<sal_Int32> aCodeUnitsPerGlyph;
aCodeUnits.reserve(nMaxGlyphs);
bool bVertical = m_aCurrentPDFState.m_aFont.IsVertical(); bool bVertical = m_aCurrentPDFState.m_aFont.IsVertical();
int nGlyphs;
int nIndex = 0; int nIndex = 0;
double fXScale = 1.0; double fXScale = 1.0;
double fSkew = 0.0; double fSkew = 0.0;
...@@ -6694,50 +6666,49 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool ...@@ -6694,50 +6666,49 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
} }
FontMetric aRefDevFontMetric = m_pReferenceDevice->GetFontMetric(); FontMetric aRefDevFontMetric = m_pReferenceDevice->GetFontMetric();
const PhysicalFontFace* pDevFont = m_pReferenceDevice->mpFontInstance->maFontSelData.mpFontData;
// collect the glyphs into a single array // collect the glyphs into a single array
std::vector< PDFGlyph > aGlyphs; std::vector< PDFGlyph > aGlyphs;
aGlyphs.reserve( nMaxGlyphs ); aGlyphs.reserve( nMaxGlyphs );
// first get all the glyphs and register them; coordinates still in Pixel // first get all the glyphs and register them; coordinates still in Pixel
Point aGNGlyphPos; Point aPos;
while ((nGlyphs = rLayout.GetNextGlyphs(nMaxGlyphs, pGlyphs, aGNGlyphPos, nIndex, pFallbackFonts)) != 0) while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nIndex, &pFallbackFont))
{ {
const auto* pFont = pFallbackFont ? pFallbackFont : pDevFont;
aCodeUnits.clear(); aCodeUnits.clear();
aCodeUnitsPerGlyph.clear();
for( int i = 0; i < nGlyphs; i++ )
{
// try to handle ligatures and such
int nStart = pGlyphs[i]->mnCharPos;
int nChars = pGlyphs[i]->mnCharCount;
if (nChars < 0)
nChars = 0;
aCodeUnitsPerGlyph.push_back(nChars); // try to handle ligatures and such
for( int n = 0; n < nChars; n++ ) int nStart = pGlyph->mnCharPos;
aCodeUnits.push_back( rText[ nStart + n ] ); int nChars = pGlyph->mnCharCount;
} if (nChars < 0)
nChars = 0;
for (int n = 0; n < nChars; n++)
aCodeUnits.push_back(rText[nStart + n]);
registerGlyphs( nGlyphs, pGlyphs, pGlyphWidths, aCodeUnits.data(), aCodeUnitsPerGlyph.data(), pMappedGlyphs, pMappedFontObjects, pFallbackFonts ); sal_uInt8 nMappedGlyph;
sal_Int32 nMappedFontObject;
registerGlyph(pGlyph, pFont, aCodeUnits, nMappedGlyph, nMappedFontObject);
for( int i = 0; i < nGlyphs; i++ ) sal_Int32 nGlyphWidth = 0;
if (m_pReferenceDevice->AcquireGraphics())
{ {
// tdf#113428: calculate the position of the next glyphs the same SalGraphics *pGraphics = m_pReferenceDevice->GetGraphics();
// way GetNextGlyphs() would do if we asked for a single glyph at if (pGraphics)
// time. nGlyphWidth = m_aFontCache.getGlyphWidth(pFont,
if (i > 0) pGlyph->maGlyphId,
{ pGlyph->IsVertical(),
Point aPos = pGlyphs[i]->maLinearPos; pGraphics);
aPos.setX( aPos.X() / ( rLayout.GetUnitsPerPixel()) );
aPos.setY( aPos.Y() / ( rLayout.GetUnitsPerPixel()) );
aGNGlyphPos = rLayout.GetDrawPosition(aPos);
}
aGlyphs.emplace_back( aGNGlyphPos,
pGlyphWidths[i],
pGlyphs[i]->maGlyphId,
pMappedFontObjects[i],
pMappedGlyphs[i],
pGlyphs[i]->IsVertical() );
} }
aGlyphs.emplace_back(aPos,
nGlyphWidth,
pGlyph->maGlyphId,
nMappedFontObject,
nMappedGlyph,
pGlyph->IsVertical());
} }
// Avoid fill color when map mode is in pixels, the below code assumes // Avoid fill color when map mode is in pixels, the below code assumes
...@@ -6817,11 +6788,10 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool ...@@ -6817,11 +6788,10 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
bool bUnderlineAbove = OutputDevice::ImplIsUnderlineAbove( m_aCurrentPDFState.m_aFont ); bool bUnderlineAbove = OutputDevice::ImplIsUnderlineAbove( m_aCurrentPDFState.m_aFont );
if( m_aCurrentPDFState.m_aFont.IsWordLineMode() ) if( m_aCurrentPDFState.m_aFont.IsWordLineMode() )
{ {
Point aPos, aStartPt; Point aStartPt;
sal_Int32 nWidth = 0; sal_Int32 nWidth = 0;
const GlyphItem* pGlyph; nIndex = 0;
int nStart = 0; while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nIndex))
while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nStart))
{ {
if (!pGlyph->IsSpacing()) if (!pGlyph->IsSpacing())
{ {
...@@ -6915,10 +6885,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool ...@@ -6915,10 +6885,8 @@ void PDFWriterImpl::drawLayout( SalLayout& rLayout, const OUString& rText, bool
else if ( eAlign == ALIGN_TOP ) else if ( eAlign == ALIGN_TOP )
aOffset.AdjustY(m_pReferenceDevice->mpFontInstance->mxFontMetric->GetAscent() ); aOffset.AdjustY(m_pReferenceDevice->mpFontInstance->mxFontMetric->GetAscent() );
Point aPos; nIndex = 0;
const GlyphItem* pGlyph; while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nIndex))
int nStart = 0;
while (rLayout.GetNextGlyphs(1, &pGlyph, aPos, nStart))
{ {
if (pGlyph->IsSpacing()) if (pGlyph->IsSpacing())
{ {
......
...@@ -810,7 +810,7 @@ i12626 ...@@ -810,7 +810,7 @@ i12626
void appendLiteralStringEncrypt( OStringBuffer const & rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer ); void appendLiteralStringEncrypt( OStringBuffer const & rInString, const sal_Int32 nInObjectNumber, OStringBuffer& rOutBuffer );
/* creates fonts and subsets that will be emitted later */ /* creates fonts and subsets that will be emitted later */
void registerGlyphs(int nGlyphs, const GlyphItem** pGlyphs, sal_Int32* pGlpyhWidths, sal_Ucs* pCodeUnits, sal_Int32 const * pCodeUnitsPerGlyph, sal_uInt8* pMappedGlyphs, sal_Int32* pMappedFontObjects, const PhysicalFontFace* pFallbackFonts[]); void registerGlyph(const GlyphItem* pGlyph, const PhysicalFontFace* pFont, const std::vector<sal_Ucs>& rCodeUnits, sal_uInt8& nMappedGlyph, sal_Int32& nMappedFontObject);
/* emits a text object according to the passed layout */ /* emits a text object according to the passed layout */
/* TODO: remove rText as soon as SalLayout will change so that rText is not necessary anymore */ /* TODO: remove rText as soon as SalLayout will change so that rText is not necessary anymore */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment