summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/vcl/imaprect.hxx2
-rw-r--r--svtools/source/svhtml/htmlout.cxx4
-rw-r--r--sw/qa/extras/htmlexport/data/tdf160867_image_with_link.fodt25
-rw-r--r--sw/qa/extras/htmlexport/htmlexport.cxx21
-rw-r--r--sw/source/core/inc/noteurl.hxx34
-rw-r--r--sw/source/core/inc/swfont.hxx3
-rw-r--r--sw/source/core/layout/paintfrm.cxx1
-rw-r--r--sw/source/core/text/atrhndl.hxx2
-rw-r--r--sw/source/core/text/atrstck.cxx15
-rw-r--r--sw/source/core/text/inftxt.cxx21
-rw-r--r--sw/source/core/text/inftxt.hxx7
-rw-r--r--sw/source/core/text/itrform2.cxx2
-rw-r--r--sw/source/core/text/itrpaint.cxx3
-rw-r--r--sw/source/core/text/noteurl.cxx35
-rw-r--r--sw/source/core/text/pormulti.cxx3
-rw-r--r--sw/source/core/txtnode/swfont.cxx2
16 files changed, 176 insertions, 4 deletions
diff --git a/include/vcl/imaprect.hxx b/include/vcl/imaprect.hxx
index 89cb52d80bbe..8abe1ed39960 100644
--- a/include/vcl/imaprect.hxx
+++ b/include/vcl/imaprect.hxx
@@ -25,7 +25,7 @@
class Fraction;
-class UNLESS_MERGELIBS(VCL_DLLPUBLIC) IMapRectangleObject final : public IMapObject
+class VCL_DLLPUBLIC IMapRectangleObject final : public IMapObject
{
tools::Rectangle aRect;
diff --git a/svtools/source/svhtml/htmlout.cxx b/svtools/source/svhtml/htmlout.cxx
index 956546269708..d165a8922f02 100644
--- a/svtools/source/svhtml/htmlout.cxx
+++ b/svtools/source/svhtml/htmlout.cxx
@@ -702,7 +702,7 @@ SvStream& HTMLOutFuncs::Out_ImageMap( SvStream& rStream,
sOut.append(OString::Concat("<") + OOO_STRING_SVTOOLS_HTML_area
" " OOO_STRING_SVTOOLS_HTML_O_shape
- "=" + pShape + " "
+ "=\"" + pShape + "\" "
OOO_STRING_SVTOOLS_HTML_O_coords "=\"" +
aCoords + "\" ");
rStream.WriteOString( sOut );
@@ -756,7 +756,7 @@ SvStream& HTMLOutFuncs::Out_ImageMap( SvStream& rStream,
Out_Events( rStream, rMacroTab, pEventTable,
bOutStarBasic );
- rStream.WriteChar( '>' );
+ rStream.WriteOString("/>");
}
}
diff --git a/sw/qa/extras/htmlexport/data/tdf160867_image_with_link.fodt b/sw/qa/extras/htmlexport/data/tdf160867_image_with_link.fodt
new file mode 100644
index 000000000000..43c35cdff13e
--- /dev/null
+++ b/sw/qa/extras/htmlexport/data/tdf160867_image_with_link.fodt
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="as-char" svg:x="0" svg:y="0" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" fo:background-color="transparent" draw:fill="none" fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:wrap="none" style:vertical-pos="middle" style:vertical-rel="baseline" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" fo:padding="0" fo:border="none" loext:rel-width-rel="paragraph"/>
+ </style:style>
+ </office:styles>
+ <office:body>
+ <office:text>
+ <text:p><draw:a xlink:type="simple" xlink:href="foo/bar"><draw:frame draw:style-name="Frame" draw:name="image1" svg:width="17cm" svg:height="25mm" style:rel-height="scale"><draw:image draw:mime-type="image/png">
+ <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAMSURBVBhXY/jPwAAAAwEBAGMkVdMAAAAASUVORK5C</office:binary-data>
+ </draw:image>
+ </draw:frame></draw:a>image1 with a hyperlink, and this text with <text:a xlink:type="simple" xlink:href="baz" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">another hyperlink</text:a></text:p>
+ <text:p><draw:frame draw:style-name="Frame" draw:name="frame" svg:width="17cm">
+ <draw:text-box fo:min-height="1pt">
+ <text:p><draw:a xlink:type="simple" xlink:href="foo/bar"><draw:frame draw:style-name="Frame" draw:name="image2" svg:width="17cm" svg:height="25mm"><draw:image draw:mime-type="image/png">
+ <office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAMSURBVBhXY/jPwAAAAwEBAGMkVdMAAAAASUVORK5C</office:binary-data>
+ </draw:image>
+ </draw:frame></draw:a>image2 with a hyperlink, and this text with <text:a xlink:type="simple" xlink:href="baz" text:style-name="Internet_20_link" text:visited-style-name="Visited_20_Internet_20_Link">another hyperlink</text:a>, in a frame</text:p>
+ </draw:text-box>
+ </draw:frame></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index 6a23599184a5..329be9231bb9 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -3082,6 +3082,27 @@ CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_Tdf160390)
ExportToHTML();
}
+CPPUNIT_TEST_FIXTURE(SwHtmlDomExportTest, testHTML_160867)
+{
+ // Given a document with an image with hyperlink, and text with hyperlink, both in a frame:
+ createSwDoc("tdf160867_image_with_link.fodt");
+ // When exporting to HTML:
+ ExportToHTML();
+ // Parse it as XML (strict!)
+ xmlDocUniquePtr pDoc = parseXml(maTempFile);
+ CPPUNIT_ASSERT(pDoc);
+ assertXPath(pDoc, "/html/body/p"_ostr, 2);
+
+ // Test export of text hyperlink in the image map. TODO: implement export of image hyperlink.
+ // Without the fix, the test would fail with
+ // - Expected: 1
+ // - Actual : 0
+ // - In <>, XPath '/html/body/p[2]/map' number of nodes is incorrect
+ const OUString mapName = getXPath(pDoc, "/html/body/p[2]/map"_ostr, "name"_ostr);
+ assertXPath(pDoc, "/html/body/p[2]/map/area"_ostr, "shape"_ostr, u"rect"_ustr);
+ assertXPath(pDoc, "/html/body/p[2]/img"_ostr, "usemap"_ostr, "#" + mapName);
+}
+
} // end of anonymous namespace
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/inc/noteurl.hxx b/sw/source/core/inc/noteurl.hxx
index 1e5775d3c099..eeae15642a43 100644
--- a/sw/source/core/inc/noteurl.hxx
+++ b/sw/source/core/inc/noteurl.hxx
@@ -20,8 +20,42 @@
#ifndef INCLUDED_SW_SOURCE_CORE_INC_NOTEURL_HXX
#define INCLUDED_SW_SOURCE_CORE_INC_NOTEURL_HXX
+#include <swrect.hxx>
+
+#include <rtl/ustring.hxx>
+
+#include <vector>
+
+class ImageMap;
+class MapMode;
+
+class SwURLNote
+{
+ OUString aURL;
+ OUString aTarget;
+ SwRect aRect;
+
+public:
+ SwURLNote(const OUString& rURL, const OUString& rTarget, const SwRect& rRect)
+ : aURL(rURL)
+ , aTarget(rTarget)
+ , aRect(rRect)
+ {
+ }
+ const OUString& GetURL() const { return aURL; }
+ const OUString& GetTarget() const { return aTarget; }
+ const SwRect& GetRect() const { return aRect; }
+};
+
class SwNoteURL
{
+private:
+ std::vector<SwURLNote> m_List;
+
+public:
+ SwNoteURL() {}
+ void InsertURLNote(const OUString& rURL, const OUString& rTarget, const SwRect& rRect);
+ void FillImageMap(ImageMap* pMap, const Point& rPos, const MapMode& rMap);
};
// globale Variable, in NoteURL.Cxx angelegt
diff --git a/sw/source/core/inc/swfont.hxx b/sw/source/core/inc/swfont.hxx
index a8c3320d1cb8..25453744bd3f 100644
--- a/sw/source/core/inc/swfont.hxx
+++ b/sw/source/core/inc/swfont.hxx
@@ -174,6 +174,7 @@ class SwFont
bool m_bFontChg :1;
bool m_bOrgChg :1; // nOrgHeight/Ascent are invalid
bool m_bGreyWave :1; // for the extended TextInput: gray waveline
+ bool m_bURL : 1 = false;
public:
SwFont( const SwAttrSet* pSet, const IDocumentSettingAccess* pIDocumentSettingAccess );
@@ -264,6 +265,8 @@ public:
inline void SetGreyWave( const bool bNew );
bool IsGreyWave() const { return m_bGreyWave; }
bool IsPaintBlank() const { return m_bPaintBlank; }
+ void SetURL(const bool bURL) { m_bURL = bURL; }
+ bool IsURL() const { return m_bURL; }
// setting of the base class font for SwTextCharFormat
void SetDiffFnt( const SfxItemSet* pSet,
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 8aa4c3738934..1e8600d83094 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -8136,6 +8136,7 @@ Graphic SwFlyFrameFormat::MakeGraphic( ImageMap* pMap, const sal_uInt32 /*nMaxim
if( bNoteURL )
{
OSL_ENSURE( pNoteURL, "MakeGraphic: Good Bye, NoteURL." );
+ pNoteURL->FillImageMap(pMap, pFly->getFrameArea().Pos(), aMap);
delete pNoteURL;
pNoteURL = nullptr;
}
diff --git a/sw/source/core/text/atrhndl.hxx b/sw/source/core/text/atrhndl.hxx
index 851615325a06..efe1ae954958 100644
--- a/sw/source/core/text/atrhndl.hxx
+++ b/sw/source/core/text/atrhndl.hxx
@@ -46,6 +46,8 @@ private:
// a template, if we have to restart the attribute evaluation
std::optional<SwFont> m_oFnt;
+ int m_nINETFMT = 0; // for font's SetURL
+
bool m_bVertLayout;
bool m_bVertLayoutLRBT;
diff --git a/sw/source/core/text/atrstck.cxx b/sw/source/core/text/atrstck.cxx
index 0eb8d74e89c6..82a3da7fbf17 100644
--- a/sw/source/core/text/atrstck.cxx
+++ b/sw/source/core/text/atrstck.cxx
@@ -367,6 +367,13 @@ void SwAttrHandler::PushAndChg( const SwTextAttr& rAttr, SwFont& rFnt )
}
}
}
+
+ if (rAttr.Which() == RES_TXTATR_INETFMT)
+ {
+ if (m_nINETFMT == 0)
+ rFnt.SetURL(true);
+ ++m_nINETFMT;
+ }
}
// this is the usual case, we have a basic attribute, push it onto the
// stack and change the font
@@ -433,6 +440,14 @@ void SwAttrHandler::PopAndChg( const SwTextAttr& rAttr, SwFont& rFnt )
const SfxItemSet* pSet = CharFormat::GetItemSet( rAttr.GetAttr() );
if ( !pSet ) return;
+ if (rAttr.Which() == RES_TXTATR_INETFMT)
+ {
+ assert(m_nINETFMT > 0);
+ --m_nINETFMT;
+ if (m_nINETFMT == 0)
+ rFnt.SetURL(false);
+ }
+
for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
{
const SfxPoolItem* pItem;
diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx
index b293f18f824a..a1a3bb89a87b 100644
--- a/sw/source/core/text/inftxt.cxx
+++ b/sw/source/core/text/inftxt.cxx
@@ -21,7 +21,9 @@
#include <unotools/linguprops.hxx>
#include <unotools/lingucfg.hxx>
+#include <fmtinfmt.hxx>
#include <hintids.hxx>
+#include <txatbase.hxx>
#include <svl/ctloptions.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/printer.hxx>
@@ -1461,6 +1463,25 @@ void SwTextPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
DrawBackground( rPor, pColor );
}
+void SwTextPaintInfo::NotifyURL_(const SwLinePortion& rPor) const
+{
+ assert(pNoteURL);
+
+ SwRect aIntersect;
+ CalcRect(rPor, nullptr, &aIntersect);
+
+ if (aIntersect.HasArea())
+ {
+ SwTextNode* pNd = const_cast<SwTextNode*>(GetTextFrame()->GetTextNodeFirst());
+ SwTextAttr* const pAttr = pNd->GetTextAttrAt(sal_Int32(GetIdx()), RES_TXTATR_INETFMT);
+ if (pAttr)
+ {
+ const SwFormatINetFormat& rFormat = pAttr->GetINetFormat();
+ pNoteURL->InsertURLNote(rFormat.GetValue(), rFormat.GetTargetFrame(), aIntersect);
+ }
+ }
+}
+
static void lcl_InitHyphValues( PropertyValues &rVals,
sal_Int16 nMinLeading, sal_Int16 nMinTrailing,
bool bNoCapsHyphenation, bool bNoLastWordHyphenation,
diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx
index cb11d02b1e8d..9c4126a7a6e9 100644
--- a/sw/source/core/text/inftxt.hxx
+++ b/sw/source/core/text/inftxt.hxx
@@ -358,6 +358,7 @@ class SwTextPaintInfo : public SwTextSizeInfo
const bool bGrammarCheck = false );
SwTextPaintInfo &operator=(const SwTextPaintInfo&) = delete;
+ void NotifyURL_(const SwLinePortion& rPor) const;
protected:
SwTextPaintInfo()
@@ -418,6 +419,12 @@ public:
void DrawCSDFHighlighting(const SwLinePortion &rPor) const;
+ void NotifyURL(const SwLinePortion& rPor) const
+ {
+ if (URLNotify())
+ NotifyURL_(rPor);
+ }
+
/**
* Calculate the rectangular area where the portion takes place.
* @param[in] rPor portion for which the method specify the painting area
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 2d24e103957a..046aa6bde1ea 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1318,7 +1318,7 @@ SwTextPortion *SwTextFormatter::WhichTextPor( SwTextFormatInfo &rInf ) const
}
if( !pPor )
{
- if( !rInf.X() && !m_pCurr->GetNextPortion() && !m_pCurr->GetLen() )
+ if( !rInf.X() && !m_pCurr->GetNextPortion() && !m_pCurr->GetLen() && !GetFnt()->IsURL() )
pPor = m_pCurr;
else
pPor = new SwTextPortion;
diff --git a/sw/source/core/text/itrpaint.cxx b/sw/source/core/text/itrpaint.cxx
index 5b6bb1288d57..8fa9ca45f5fd 100644
--- a/sw/source/core/text/itrpaint.cxx
+++ b/sw/source/core/text/itrpaint.cxx
@@ -459,6 +459,9 @@ void SwTextPainter::DrawTextLine( const SwRect &rPaint, SwSaveClip &rClip,
// reset (for special vertical alignment)
GetInfo().Y( nOldY );
+ if (GetFnt()->IsURL() && pPor->InTextGrp())
+ GetInfo().NotifyURL(*pPor);
+
bFirst &= !pPor->GetLen();
if( pNext || !pPor->IsMarginPortion() )
pPor->Move( GetInfo() );
diff --git a/sw/source/core/text/noteurl.cxx b/sw/source/core/text/noteurl.cxx
index fa91ea252d5f..ae52e1c29a91 100644
--- a/sw/source/core/text/noteurl.cxx
+++ b/sw/source/core/text/noteurl.cxx
@@ -19,7 +19,42 @@
#include <noteurl.hxx>
+#include <vcl/imap.hxx>
+#include <vcl/imaprect.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/outdev.hxx>
+
// Global variable
SwNoteURL* pNoteURL = nullptr;
+void SwNoteURL::InsertURLNote(const OUString& rURL, const OUString& rTarget, const SwRect& rRect)
+{
+ const size_t nCount = m_List.size();
+ for (size_t i = 0; i < nCount; ++i)
+ if (rRect == m_List[i].GetRect())
+ return;
+
+ m_List.emplace_back(rURL, rTarget, rRect);
+}
+
+void SwNoteURL::FillImageMap(ImageMap* pMap, const Point& rPos, const MapMode& rMap)
+{
+ assert(pMap && "FillImageMap: No ImageMap, no cookies!");
+ const size_t nCount = m_List.size();
+ if (nCount)
+ {
+ MapMode aMap(MapUnit::Map100thMM);
+ for (size_t i = 0; i < nCount; ++i)
+ {
+ const SwURLNote& rNote = m_List[i];
+ SwRect aSwRect(rNote.GetRect());
+ aSwRect -= rPos;
+ tools::Rectangle aRect(OutputDevice::LogicToLogic(aSwRect.SVRect(), rMap, aMap));
+ IMapRectangleObject aObj(aRect, rNote.GetURL(), OUString(), OUString(),
+ rNote.GetTarget(), OUString(), true, false);
+ pMap->InsertIMapObject(aObj);
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx
index 9fb6011f0db5..aaf8339b37ef 100644
--- a/sw/source/core/text/pormulti.cxx
+++ b/sw/source/core/text/pormulti.cxx
@@ -1783,6 +1783,9 @@ void SwTextPainter::PaintMultiPortion( const SwRect &rPaint,
pPor->Paint( GetInfo() );
}
+ if (GetFnt()->IsURL() && pPor->InTextGrp())
+ GetInfo().NotifyURL(*pPor);
+
bFirst &= !pPor->GetLen();
if( pNext || !pPor->IsMarginPortion() )
pPor->Move( GetInfo() );
diff --git a/sw/source/core/txtnode/swfont.cxx b/sw/source/core/txtnode/swfont.cxx
index 98fec0f153e2..20b3062267f7 100644
--- a/sw/source/core/txtnode/swfont.cxx
+++ b/sw/source/core/txtnode/swfont.cxx
@@ -684,6 +684,7 @@ SwFont::SwFont( const SwFont &rFont )
m_bOrgChg = rFont.m_bOrgChg;
m_bPaintBlank = rFont.m_bPaintBlank;
m_bGreyWave = rFont.m_bGreyWave;
+ m_bURL = rFont.m_bURL;
}
SwFont::SwFont( const SwAttrSet* pAttrSet,
@@ -873,6 +874,7 @@ SwFont& SwFont::operator=( const SwFont &rFont )
m_bOrgChg = rFont.m_bOrgChg;
m_bPaintBlank = rFont.m_bPaintBlank;
m_bGreyWave = rFont.m_bGreyWave;
+ m_bURL = rFont.m_bURL;
}
return *this;
}