LibreOffice Module sdext (master)  1
PresenterCanvasHelper.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
21 
23 #include <com/sun/star/rendering/CompositeOperation.hpp>
24 #include <osl/diagnose.h>
25 
26 using namespace ::com::sun::star;
27 using namespace ::com::sun::star::uno;
28 
29 namespace sdext::presenter {
30 
32  : maDefaultViewState(
33  geometry::AffineMatrix2D(1,0,0, 0,1,0),
34  nullptr),
35  maDefaultRenderState(
36  geometry::AffineMatrix2D(1,0,0, 0,1,0),
37  nullptr,
38  Sequence<double>(4),
39  rendering::CompositeOperation::SOURCE)
40 {
41 }
42 
44 {
45 }
46 
48  const SharedBitmapDescriptor& rpBitmap,
49  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
50  const css::awt::Rectangle& rRepaintBox,
51  const css::awt::Rectangle& rOuterBoundingBox,
52  const css::awt::Rectangle& rContentBoundingBox) const
53 {
54  PaintRectangle(rpBitmap,rxCanvas,rRepaintBox,rOuterBoundingBox,rContentBoundingBox,
56 }
57 
59  const SharedBitmapDescriptor& rpBitmap,
60  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
61  const css::awt::Rectangle& rRepaintBox,
62  const css::awt::Rectangle& rOuterBoundingBox,
63  const css::awt::Rectangle& rContentBoundingBox,
64  const css::rendering::ViewState& rDefaultViewState,
65  const css::rendering::RenderState& rDefaultRenderState)
66 {
67  if (rpBitmap.get() == nullptr)
68  return;
69 
70  if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is())
71  return;
72 
73  // Create a clip polypolygon that has the content box as hole.
74  ::std::vector<awt::Rectangle> aRectangles;
75  aRectangles.reserve(2);
76  aRectangles.push_back(
77  PresenterGeometryHelper::Intersection(rRepaintBox, rOuterBoundingBox));
78  if (rContentBoundingBox.Width > 0 && rContentBoundingBox.Height > 0)
79  aRectangles.push_back(
80  PresenterGeometryHelper::Intersection(rRepaintBox, rContentBoundingBox));
81  Reference<rendering::XPolyPolygon2D> xPolyPolygon (
83  aRectangles,
84  rxCanvas->getDevice()));
85  if ( ! xPolyPolygon.is())
86  return;
87  xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD);
88 
89  if (rpBitmap->GetNormalBitmap().is())
90  {
91  if (rpBitmap->meHorizontalTexturingMode == PresenterBitmapDescriptor::Repeat
92  || rpBitmap->meVerticalTexturingMode == PresenterBitmapDescriptor::Repeat)
93  {
95  rpBitmap->GetNormalBitmap(),
96  rxCanvas,
97  rRepaintBox,
98  xPolyPolygon,
99  rContentBoundingBox,
100  rDefaultViewState,
101  rDefaultRenderState);
102  }
103  else
104  {
105  PaintBitmap(
106  rpBitmap->GetNormalBitmap(),
107  awt::Point(rOuterBoundingBox.X, rOuterBoundingBox.Y),
108  rxCanvas,
109  rRepaintBox,
110  xPolyPolygon,
111  rDefaultViewState,
112  rDefaultRenderState);
113  }
114  }
115  else
116  {
117  PaintColor(
118  rpBitmap->maReplacementColor,
119  rxCanvas,
120  rRepaintBox,
121  xPolyPolygon,
122  rDefaultViewState,
123  rDefaultRenderState);
124  }
125 }
126 
128  const css::uno::Reference<css::rendering::XBitmap>& rxTexture,
129  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
130  const css::awt::Rectangle& rRepaintBox,
131  const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon,
132  const css::awt::Rectangle& rHole,
133  const css::rendering::ViewState& rDefaultViewState,
134  const css::rendering::RenderState& rDefaultRenderState)
135 {
136  if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is())
137  return;
138 
139  if ( ! rxTexture.is())
140  return;
141 
142  if ( ! rxPolygon.is())
143  return;
144 
145  rendering::ViewState aViewState (rDefaultViewState);
146  aViewState.Clip = rxPolygon;
147 
148  // Create a local render state at which the location of the bitmap is
149  // set.
150  rendering::RenderState aRenderState (rDefaultRenderState);
151 
152  // Tile the bitmap over the repaint box.
153  const geometry::IntegerSize2D aBitmapSize (rxTexture->getSize());
154  if( aBitmapSize.Width < 1 || aBitmapSize.Height < 1)
155  return;
156 
157  const sal_Int32 nLeft = (rRepaintBox.X / aBitmapSize.Width) * aBitmapSize.Width;
158  const sal_Int32 nTop = (rRepaintBox.Y / aBitmapSize.Height) * aBitmapSize.Height;
159  const sal_Int32 nRight = ((rRepaintBox.X + rRepaintBox.Width - 1 + aBitmapSize.Width - 1)
160  / aBitmapSize.Width) * aBitmapSize.Width;
161  const sal_Int32 nBottom = ((rRepaintBox.Y + rRepaintBox.Height - 1 + aBitmapSize.Height - 1)
162  / aBitmapSize.Height) * aBitmapSize.Height;
163 
164  for (sal_Int32 nY=nTop; nY<=nBottom; nY+=aBitmapSize.Height)
165  for (sal_Int32 nX=nLeft; nX<=nRight; nX+=aBitmapSize.Width)
166  {
168  awt::Rectangle(nX,nY,aBitmapSize.Width,aBitmapSize.Height),
169  rHole))
170  {
171  continue;
172  }
173  aRenderState.AffineTransform.m02 = nX;
174  aRenderState.AffineTransform.m12 = nY;
175  rxCanvas->drawBitmap(
176  rxTexture,
177  aViewState,
178  aRenderState);
179  }
180 }
181 
183  const css::uno::Reference<css::rendering::XBitmap>& rxBitmap,
184  const awt::Point& rLocation,
185  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
186  const css::awt::Rectangle& rRepaintBox,
187  const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon,
188  const css::rendering::ViewState& rDefaultViewState,
189  const css::rendering::RenderState& rDefaultRenderState)
190 {
191  if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is())
192  return;
193 
194  if ( ! rxBitmap.is())
195  return;
196 
197  if ( ! rxPolygon.is())
198  return;
199 
200  // Set the repaint box as clip rectangle at the view state.
201  rendering::ViewState aViewState (rDefaultViewState);
202  aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice());
203 
204  // Setup the rendering state so that the bitmap is painted top left in
205  // the polygon bounding box.
206  rendering::RenderState aRenderState (rDefaultRenderState);
207  aRenderState.AffineTransform = geometry::AffineMatrix2D(1,0, rLocation.X, 0,1,rLocation.Y);
208  aRenderState.Clip = rxPolygon;
209 
210  rxCanvas->drawBitmap(
211  rxBitmap,
212  aViewState,
213  aRenderState);
214 }
215 
217  const css::util::Color nColor,
218  const css::uno::Reference<css::rendering::XCanvas>& rxCanvas,
219  const css::awt::Rectangle& rRepaintBox,
220  const css::uno::Reference<css::rendering::XPolyPolygon2D>& rxPolygon,
221  const css::rendering::ViewState& rDefaultViewState,
222  const css::rendering::RenderState& rDefaultRenderState)
223 {
224  if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is())
225  return;
226 
227  if ( ! rxPolygon.is())
228  return;
229 
230  // Set the repaint box as clip rectangle at the view state.
231  rendering::ViewState aViewState (rDefaultViewState);
232  aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice());
233 
234  // Setup the rendering state to use the given color.
235  rendering::RenderState aRenderState (rDefaultRenderState);
236  SetDeviceColor(aRenderState, nColor);
237 
238  rxCanvas->fillPolyPolygon(
239  rxPolygon,
240  aViewState,
241  aRenderState);
242 }
243 
245  rendering::RenderState& rRenderState,
246  const util::Color aColor)
247 {
248  // Other component counts then 4 (RGBA) are not accepted (anymore).
249 
250  OSL_ASSERT(rRenderState.DeviceColor.getLength() == 4);
251  if (rRenderState.DeviceColor.getLength() == 4)
252  {
253  rRenderState.DeviceColor[0] = ((aColor >> 16) & 0x0ff) / 255.0;
254  rRenderState.DeviceColor[1] = ((aColor >> 8) & 0x0ff) / 255.0;
255  rRenderState.DeviceColor[2] = ((aColor >> 0) & 0x0ff) / 255.0;
256  rRenderState.DeviceColor[3] = 1.0 - ((aColor >> 24) & 0x0ff) / 255.0;
257  }
258 }
259 
260 css::geometry::RealRectangle2D PresenterCanvasHelper::GetTextBoundingBox (
261  const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
262  const OUString& rsText,
263  const sal_Int8 nTextDirection)
264 {
265  if (rxFont.is() && !rsText.isEmpty())
266  {
267  rendering::StringContext aContext (rsText, 0, rsText.getLength());
268  Reference<rendering::XTextLayout> xLayout (
269  rxFont->createTextLayout(aContext, nTextDirection, 0));
270  return xLayout->queryTextBounds();
271  }
272  else
273  {
274  return geometry::RealRectangle2D(0,0,0,0);
275  }
276 }
277 
278 css::geometry::RealSize2D PresenterCanvasHelper::GetTextSize (
279  const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
280  const OUString& rsText)
281 {
282  const geometry::RealRectangle2D aTextBBox (GetTextBoundingBox(rxFont, rsText));
283  return css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1);
284 }
285 
286 } // end of namespace sdext::presenter
287 
288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
signed char sal_Int8
static void PaintBitmap(const css::uno::Reference< css::rendering::XBitmap > &rxBitmap, const css::awt::Point &rLocation, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::uno::Reference< css::rendering::XPolyPolygon2D > &rxPolygon, const css::rendering::ViewState &rDefaultViewState, const css::rendering::RenderState &rDefaultRenderState)
void Paint(const SharedBitmapDescriptor &rpBitmap, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::awt::Rectangle &rBackgroundBoundingBox, const css::awt::Rectangle &rContentBoundingBox) const
std::shared_ptr< PresenterBitmapContainer::BitmapDescriptor > SharedBitmapDescriptor
const css::rendering::ViewState maDefaultViewState
static css::uno::Reference< css::rendering::XPolyPolygon2D > CreatePolygon(const css::awt::Rectangle &rBox, const css::uno::Reference< css::rendering::XGraphicDevice > &rxDevice)
static css::awt::Rectangle Intersection(const css::awt::Rectangle &rBox1, const css::awt::Rectangle &rBox2)
static void PaintRectangle(const SharedBitmapDescriptor &rpBitmap, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::awt::Rectangle &rBackgroundBoundingBox, const css::awt::Rectangle &rContentBoundingBox, const css::rendering::ViewState &rDefaultViewState, const css::rendering::RenderState &rDefaultRenderState)
static void SetDeviceColor(css::rendering::RenderState &rRenderState, const css::util::Color aColor)
static css::geometry::RealSize2D GetTextSize(const css::uno::Reference< css::rendering::XCanvasFont > &rxFont, const OUString &rsText)
static css::geometry::RealRectangle2D GetTextBoundingBox(const css::uno::Reference< css::rendering::XCanvasFont > &rxFont, const OUString &rsText, const sal_Int8=css::rendering::TextDirection::WEAK_LEFT_TO_RIGHT)
static bool IsInside(const css::geometry::RealRectangle2D &rBox, const css::geometry::RealPoint2D &rPoint)
static void PaintTiledBitmap(const css::uno::Reference< css::rendering::XBitmap > &rxTexture, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::uno::Reference< css::rendering::XPolyPolygon2D > &rxPolygon, const css::awt::Rectangle &rHole, const css::rendering::ViewState &rDefaultViewState, const css::rendering::RenderState &rDefaultRenderState)
static void PaintColor(const css::util::Color nColor, const css::uno::Reference< css::rendering::XCanvas > &rxCanvas, const css::awt::Rectangle &rRepaintBox, const css::uno::Reference< css::rendering::XPolyPolygon2D > &rxPolygon, const css::rendering::ViewState &rDefaultViewState, const css::rendering::RenderState &rDefaultRenderState)
const css::rendering::RenderState maDefaultRenderState