Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Run command in Docker and save artifact

on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:

jobs:
build-libreoffice:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Build libreoffice-core in container
run: |
docker compose -f compose.yml up --build
ls -lah ./build

- name: save libreoffice as artifact
uses: actions/upload-artifact@v4
with:
name: libreoffice-build
path: ./build
64 changes: 64 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
FROM ubuntu:24.04

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
git \
build-essential \
g++ \
python3 \
python3-pip \
python3-dev \
python3-setuptools \
openjdk-17-jdk \
autoconf \
automake \
libtool \
pkg-config \
libnss3-dev \
libnspr4-dev \
libxml2-utils \
gperf \
xsltproc \
uuid-runtime \
bison \
flex \
zip \
libxrender-dev \
libxt-dev \
libcups2-dev \
libxrandr-dev \
libglu1-mesa-dev \
libcairo2-dev \
libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev \
libpng-dev \
libjpeg-dev \
libtiff-dev \
libgif-dev \
libexpat1-dev \
libssl-dev \
libkrb5-dev \
libldap2-dev \
libdbus-1-dev \
libharfbuzz-dev \
libcurl4-openssl-dev \
libxslt1-dev \
ninja-build \
meson \
wget \
curl
RUN pip3 install --no-cache-dir setuptools lxml meson ninja --break-system-packages



#RUN dpkg-query -W -f='${Package}\t${Version}\n' \
# git build-essential g++ python3 python3-pip python3-dev python3-setuptools openjdk-17-jdk autoconf automake libtool pkg-config libnss3-dev libnspr4-dev libxml2-utils gperf xsltproc uuid-runtime bison flex zip libxrender-dev libxt-dev libcups2-dev libxrandr-dev libglu1-mesa-dev libcairo2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libpng-dev libjpeg-dev libtiff-dev libgif-dev libexpat1-dev libssl-dev libkrb5-dev libldap2-dev libdbus-1-dev libharfbuzz-dev libcurl4-openssl-dev libxslt1-dev ninja-build meson wget curl 2>/dev/null | column -t

COPY ./ /APP/libreoffice-core
WORKDIR /APP/libreoffice-core
RUN ./autogen.sh --disable-gtk3 --disable-gui --disable-dbus --disable-cairo-canvas --without-help --without-java --without-myspell-dicts --without-doxygen --without-junit --enable-release-build --disable-debug --prefix=/tmp/build/
RUN make -j8
RUN make install
RUN ls -laht /tmp/build/
RUN ls -laht /APP
ENTRYPOINT [ "mv", "/tmp/build/", "/build/" ]
#ENTRYPOINT [ "tail", "-f", "/dev/null" ]
11 changes: 11 additions & 0 deletions compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

services:
libreoffice-core:
build:
context: .
dockerfile: Dockerfile
container_name: libreoffice-core

# Uncomment and adjust the following lines as needed:
volumes:
- ./build:/build/
5 changes: 5 additions & 0 deletions filter/source/svg/svgfilter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ css::uno::Reference<css::frame::XController> SVGFilter::getSourceController() co

css::uno::Reference<css::frame::XController> SVGFilter::fillDrawImpressSelectedPages()
{
uno::Reference<frame::XDesktop2> xDesktop(frame::Desktop::create(mxContext));
if (xDesktop->getCurrentFrame() == nullptr) {
return {};
}

uno::Reference<frame::XController> xController = getSourceController();
uno::Reference<drawing::framework::XControllerManager> xManager(xController, uno::UNO_QUERY);
if (!xManager)
Expand Down
77 changes: 76 additions & 1 deletion filter/source/svg/svgwriter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
#include <com/sun/star/i18n/XBreakIterator.hpp>
#include <com/sun/star/style/NumberingType.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/style/LineSpacing.hpp>
#include <com/sun/star/style/LineSpacingMode.hpp>
#include <com/sun/star/text/XTextField.hpp>

#include <memory>
Expand Down Expand Up @@ -1107,7 +1110,9 @@ bool SVGTextWriter::nextParagraph()
Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_SET_THROW );
if( xEnumeration.is() && xEnumeration->hasMoreElements() )
{
mrTextPortionEnumeration.set( xEnumeration );
mrTextPortionEnumeration.set(xEnumeration);
Reference<XPropertySet> xPortionPropSet(mrTextPortionEnumeration->nextElement(), UNO_QUERY);
extractTextAlignmentAndLineHeight(xPortionPropSet);
}
#if OSL_DEBUG_LEVEL > 0
sInfo = "Paragraph";
Expand Down Expand Up @@ -1156,6 +1161,63 @@ bool SVGTextWriter::nextParagraph()
return true;
}

void SVGTextWriter::extractTextAlignmentAndLineHeight(const Reference<XPropertySet>& xPortionPropSet)
{
Reference<XPropertySetInfo> xPortionPropInfo(xPortionPropSet->getPropertySetInfo());
if (xPortionPropInfo->hasPropertyByName(u"ParaAdjust"_ustr))
{
sal_uInt16 nTextAdjust = sal_uInt16(ParagraphAdjust_LEFT);
if (xPortionPropSet->getPropertyValue(u"ParaAdjust"_ustr) >>= nTextAdjust)
{
switch (static_cast<ParagraphAdjust>(nTextAdjust))
{
case ParagraphAdjust_LEFT:
msTextAlignment = "left";
break;
case ParagraphAdjust_CENTER:
msTextAlignment = "center";
break;
case ParagraphAdjust_RIGHT:
msTextAlignment = "right";
break;
case ParagraphAdjust_BLOCK:
msTextAlignment = "block";
break;
default:
msTextAlignment.clear();
break;
}
}
}

if (xPortionPropInfo->hasPropertyByName(u"ParaLineSpacing"_ustr))
{
css::style::LineSpacing aLineSpacing;
if (xPortionPropSet->getPropertyValue(u"ParaLineSpacing"_ustr) >>= aLineSpacing)
{
switch (aLineSpacing.Mode)
{
case css::style::LineSpacingMode::PROP:
{
double fLineHeight = aLineSpacing.Height / 100.0;
msLineHeight = OUString::number(fLineHeight);
}
break;

case css::style::LineSpacingMode::FIX:
{
double fPoints = aLineSpacing.Height / 35.0;
msLineHeight = OUString::number(static_cast<int>(fPoints)) + u"pt";
}
break;

default:
msLineHeight = OUString::number(aLineSpacing.Height);
break;
}
}
}
}

bool SVGTextWriter::nextTextPortion()
{
Expand Down Expand Up @@ -1388,6 +1450,12 @@ void SVGTextWriter::startTextParagraph()
else
{
mrExport.AddAttribute(u"class"_ustr, u"TextParagraph"_ustr);
if (!msTextAlignment.isEmpty()) {
mrExport.AddAttribute(u"ooo:text-alignment"_ustr, msTextAlignment);
}
if (!msLineHeight.isEmpty()) {
mrExport.AddAttribute(u"ooo:line-height"_ustr, msLineHeight);
}
}
maParentFont = vcl::Font();
mpTextParagraphElem.reset(new SvXMLElementExport(mrExport, aXMLElemTspan, mbIWS, mbIWS));
Expand Down Expand Up @@ -1420,6 +1488,13 @@ void SVGTextWriter::startTextPosition( bool bExportX, bool bExportY )
if( bExportY )
mrExport.AddAttribute(aXMLAttrY, OUString::number(maTextPos.Y()));

if (!msTextAlignment.isEmpty()) {
mrExport.AddAttribute(u"ooo:text-alignment"_ustr, msTextAlignment);
}
if (!msLineHeight.isEmpty()) {
mrExport.AddAttribute(u"ooo:line-height"_ustr, msLineHeight);
}

mpTextPositionElem.reset(new SvXMLElementExport(mrExport, aXMLElemTspan, mbIWS, mbIWS));
}

Expand Down
3 changes: 3 additions & 0 deletions filter/source/svg/svgwriter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ class SVGTextWriter final
OUString msPageCount;
OUString msDateTimeType;
OUString msTextFieldType;
OUString msTextAlignment;
OUString msLineHeight;
bool mbIsPlaceholderShape;
static const bool mbIWS = false;
vcl::Font maCurrentFont;
Expand Down Expand Up @@ -291,6 +293,7 @@ class SVGTextWriter final

void implRegisterInterface( const Reference< XInterface >& rxIf );
const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
void extractTextAlignmentAndLineHeight(const Reference<com::sun::star::beans::XPropertySet>& xPortionPropSet);
};


Expand Down
1 change: 1 addition & 0 deletions include/vcl/outdev.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,7 @@ public:

FontMetric GetFontMetricFromCollection( int nDevFontIndex ) const;
int GetFontFaceCollectionCount() const;
OUString FindBestMatchingFont(const OUString& fontFamily) const;

bool IsFontAvailable( std::u16string_view rFontName ) const;

Expand Down
12 changes: 12 additions & 0 deletions oox/source/drawingml/textfont.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <oox/helper/attributelist.hxx>
#include <oox/token/tokens.hxx>
#include <docmodel/theme/Theme.hxx>
#include <vcl/svapp.hxx>
#include <vcl/outdev.hxx>

using ::oox::core::XmlFilterBase;

Expand Down Expand Up @@ -56,15 +58,25 @@ TextFont::TextFont() :

void TextFont::setAttributes( const AttributeList& rAttribs )
{
auto device = Application::GetDefaultDevice();
maTypeface = rAttribs.getStringDefaulted( XML_typeface);
if (!device->IsFontAvailable(maTypeface)) {
// If the font is not available, try to find the best match
maTypeface = device->FindBestMatchingFont(maTypeface);
}
maPanose = rAttribs.getStringDefaulted( XML_panose);
mnPitchFamily = rAttribs.getInteger( XML_pitchFamily, 0 );
mnCharset = rAttribs.getInteger( XML_charset, WINDOWS_CHARSET_DEFAULT );
}

void TextFont::setAttributes( const OUString& sFontName )
{
auto device = Application::GetDefaultDevice();
maTypeface = sFontName;
if (!device->IsFontAvailable(maTypeface)) {
// If the font is not available, try to find the best match
maTypeface = device->FindBestMatchingFont(maTypeface);
}
maPanose.clear();
mnPitchFamily = 0;
mnCharset = WINDOWS_CHARSET_DEFAULT;
Expand Down
57 changes: 57 additions & 0 deletions vcl/source/outdev/font.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,63 @@ int OutputDevice::GetFontFaceCollectionCount() const
return mpFontFaceCollection->Count();
}

namespace {
rtl::OUString StripWeightSuffix(const rtl::OUString& name)
{
static const char* const suffixes[] = {
" thin", " ultralight", " light", " semilight",
" normal", " medium", " semibold", " bold",
" ultrabold", " black"
};

rtl::OUString lower = name.toAsciiLowerCase();

for (const char* suffix : suffixes)
{
rtl::OUString pattern = rtl::OUString::createFromAscii(suffix);
sal_Int32 pos = lower.lastIndexOf(pattern);
if (pos >= 0 && (pos + pattern.getLength() == lower.getLength()))
{
return name.copy(0, pos);
}
}

return name;
}
}


OUString OutputDevice::FindBestMatchingFont(const OUString& fontFamily) const
{
if(!mpFontFaceCollection)
{
if (!mxFontCollection)
{
return fontFamily;
}

mpFontFaceCollection = mxFontCollection->GetFontFaceCollection();

if (!mpFontFaceCollection->Count())
{
mpFontFaceCollection.reset();
return fontFamily;
}
}
OUString fontName = StripWeightSuffix(fontFamily);
if (fontName != fontFamily) {
int size = mpFontFaceCollection->Count();
for (int i = 0; i < size; ++i) {
auto fontFace = mpFontFaceCollection->Get(i);
if (fontFace->GetFamilyName() == fontName) {
// We might want to check fontFace->GetWeight() as well
return fontName;
}
}
}
return fontFamily;
}

bool OutputDevice::IsFontAvailable( std::u16string_view rFontName ) const
{
ImplInitFontList();
Expand Down