| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sdext.hxx" |
| |
| #include "PresenterCanvasHelper.hxx" |
| |
| #include "PresenterController.hxx" |
| #include "PresenterGeometryHelper.hxx" |
| #include <com/sun/star/rendering/CompositeOperation.hpp> |
| #include <com/sun/star/rendering/TextDirection.hpp> |
| #include <com/sun/star/rendering/TexturingMode.hpp> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| |
| namespace sdext { namespace presenter { |
| |
| PresenterCanvasHelper::PresenterCanvasHelper (void) |
| : maDefaultViewState( |
| geometry::AffineMatrix2D(1,0,0, 0,1,0), |
| NULL), |
| maDefaultRenderState( |
| geometry::AffineMatrix2D(1,0,0, 0,1,0), |
| NULL, |
| Sequence<double>(4), |
| rendering::CompositeOperation::SOURCE) |
| { |
| } |
| |
| |
| |
| |
| PresenterCanvasHelper::~PresenterCanvasHelper (void) |
| { |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::Paint ( |
| const SharedBitmapDescriptor& rpBitmap, |
| const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, |
| const css::awt::Rectangle& rRepaintBox, |
| const css::awt::Rectangle& rOuterBoundingBox, |
| const css::awt::Rectangle& rContentBoundingBox) const |
| { |
| PaintRectangle(rpBitmap,rxCanvas,rRepaintBox,rOuterBoundingBox,rContentBoundingBox, |
| maDefaultViewState, maDefaultRenderState); |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::PaintRectangle ( |
| const SharedBitmapDescriptor& rpBitmap, |
| const css::uno::Reference<css::rendering::XCanvas>& rxCanvas, |
| const css::awt::Rectangle& rRepaintBox, |
| const css::awt::Rectangle& rOuterBoundingBox, |
| const css::awt::Rectangle& rContentBoundingBox, |
| const css::rendering::ViewState& rDefaultViewState, |
| const css::rendering::RenderState& rDefaultRenderState) |
| { |
| if (rpBitmap.get() == NULL) |
| return; |
| |
| if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) |
| return; |
| |
| // Create a clip polypolygon that has the content box as hole. |
| ::std::vector<awt::Rectangle> aRectangles; |
| aRectangles.reserve(2); |
| aRectangles.push_back( |
| PresenterGeometryHelper::Intersection(rRepaintBox, rOuterBoundingBox)); |
| if (rContentBoundingBox.Width > 0 && rContentBoundingBox.Height > 0) |
| aRectangles.push_back( |
| PresenterGeometryHelper::Intersection(rRepaintBox, rContentBoundingBox)); |
| Reference<rendering::XPolyPolygon2D> xPolyPolygon ( |
| PresenterGeometryHelper::CreatePolygon( |
| aRectangles, |
| rxCanvas->getDevice())); |
| if ( ! xPolyPolygon.is()) |
| return; |
| xPolyPolygon->setFillRule(rendering::FillRule_EVEN_ODD); |
| |
| if (rpBitmap->GetNormalBitmap().is()) |
| { |
| if (rpBitmap->meHorizontalTexturingMode == PresenterBitmapDescriptor::Repeat |
| || rpBitmap->meVerticalTexturingMode == PresenterBitmapDescriptor::Repeat) |
| { |
| PaintTiledBitmap( |
| Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), |
| rxCanvas, |
| rRepaintBox, |
| xPolyPolygon, |
| rContentBoundingBox, |
| rDefaultViewState, |
| rDefaultRenderState); |
| } |
| else |
| { |
| PaintBitmap( |
| Reference<rendering::XBitmap>(rpBitmap->GetNormalBitmap(), UNO_QUERY), |
| awt::Point(rOuterBoundingBox.X, rOuterBoundingBox.Y), |
| rxCanvas, |
| rRepaintBox, |
| xPolyPolygon, |
| rDefaultViewState, |
| rDefaultRenderState); |
| } |
| } |
| else |
| { |
| PaintColor( |
| rpBitmap->maReplacementColor, |
| rxCanvas, |
| rRepaintBox, |
| xPolyPolygon, |
| rDefaultViewState, |
| rDefaultRenderState); |
| } |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::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) |
| { |
| if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) |
| return; |
| |
| if ( ! rxTexture.is()) |
| return; |
| |
| if ( ! rxPolygon.is()) |
| return; |
| |
| rendering::ViewState aViewState (rDefaultViewState); |
| aViewState.Clip = rxPolygon; |
| |
| // Create a local render state at which the location of the bitmap is |
| // set. |
| rendering::RenderState aRenderState (rDefaultRenderState); |
| |
| |
| // Tile the bitmap over the repaint box. |
| const geometry::IntegerSize2D aBitmapSize (rxTexture->getSize()); |
| const sal_Int32 nLeft = (rRepaintBox.X / aBitmapSize.Width) * aBitmapSize.Width; |
| const sal_Int32 nTop = (rRepaintBox.Y / aBitmapSize.Height) * aBitmapSize.Height; |
| const sal_Int32 nRight = ((rRepaintBox.X + rRepaintBox.Width - 1 + aBitmapSize.Width - 1) |
| / aBitmapSize.Width) * aBitmapSize.Width; |
| const sal_Int32 nBottom = ((rRepaintBox.Y + rRepaintBox.Height - 1 + aBitmapSize.Height - 1) |
| / aBitmapSize.Height) * aBitmapSize.Height; |
| |
| for (sal_Int32 nY=nTop; nY<=nBottom; nY+=aBitmapSize.Height) |
| for (sal_Int32 nX=nLeft; nX<=nRight; nX+=aBitmapSize.Width) |
| { |
| if (PresenterGeometryHelper::IsInside( |
| awt::Rectangle(nX,nY,aBitmapSize.Width,aBitmapSize.Height), |
| rHole)) |
| { |
| continue; |
| } |
| aRenderState.AffineTransform.m02 = nX; |
| aRenderState.AffineTransform.m12 = nY; |
| rxCanvas->drawBitmap( |
| rxTexture, |
| aViewState, |
| aRenderState); |
| } |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::PaintBitmap ( |
| const css::uno::Reference<css::rendering::XBitmap>& rxBitmap, |
| const 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) |
| { |
| if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) |
| return; |
| |
| if ( ! rxBitmap.is()) |
| return; |
| |
| if ( ! rxPolygon.is()) |
| return; |
| |
| // Set the repaint box as clip rectangle at the view state. |
| rendering::ViewState aViewState (rDefaultViewState); |
| aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); |
| |
| |
| // Setup the rendering state so that the bitmap is painted top left in |
| // the polygon bounding box. |
| rendering::RenderState aRenderState (rDefaultRenderState); |
| aRenderState.AffineTransform = geometry::AffineMatrix2D(1,0, rLocation.X, 0,1,rLocation.Y); |
| aRenderState.Clip = rxPolygon; |
| |
| rxCanvas->drawBitmap( |
| rxBitmap, |
| aViewState, |
| aRenderState); |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::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) |
| { |
| if ( ! rxCanvas.is() || ! rxCanvas->getDevice().is()) |
| return; |
| |
| if ( ! rxPolygon.is()) |
| return; |
| |
| // Set the repaint box as clip rectangle at the view state. |
| rendering::ViewState aViewState (rDefaultViewState); |
| aViewState.Clip = PresenterGeometryHelper::CreatePolygon(rRepaintBox, rxCanvas->getDevice()); |
| |
| |
| // Setup the rendering state to use the given color. |
| rendering::RenderState aRenderState (rDefaultRenderState); |
| SetDeviceColor(aRenderState, nColor); |
| |
| rxCanvas->fillPolyPolygon( |
| rxPolygon, |
| aViewState, |
| aRenderState); |
| } |
| |
| |
| |
| |
| void PresenterCanvasHelper::SetDeviceColor( |
| rendering::RenderState& rRenderState, |
| const util::Color aColor) |
| { |
| // Other component counts then 4 (RGBA) are not accepted (anymore). |
| |
| OSL_ASSERT(rRenderState.DeviceColor.getLength() == 4); |
| if (rRenderState.DeviceColor.getLength() == 4) |
| { |
| rRenderState.DeviceColor[0] = ((aColor >> 16) & 0x0ff) / 255.0; |
| rRenderState.DeviceColor[1] = ((aColor >> 8) & 0x0ff) / 255.0; |
| rRenderState.DeviceColor[2] = ((aColor >> 0) & 0x0ff) / 255.0; |
| rRenderState.DeviceColor[3] = 1.0 - ((aColor >> 24) & 0x0ff) / 255.0; |
| } |
| } |
| |
| |
| |
| |
| css::geometry::RealRectangle2D PresenterCanvasHelper::GetTextBoundingBox ( |
| const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, |
| const ::rtl::OUString& rsText, |
| const sal_Int8 nTextDirection) |
| { |
| if (rxFont.is() && rsText.getLength() > 0) |
| { |
| rendering::StringContext aContext (rsText, 0, rsText.getLength()); |
| Reference<rendering::XTextLayout> xLayout ( |
| rxFont->createTextLayout(aContext, nTextDirection, 0)); |
| return xLayout->queryTextBounds(); |
| } |
| else |
| { |
| return geometry::RealRectangle2D(0,0,0,0); |
| } |
| } |
| |
| |
| |
| |
| css::geometry::RealSize2D PresenterCanvasHelper::GetTextSize ( |
| const css::uno::Reference<css::rendering::XCanvasFont>& rxFont, |
| const ::rtl::OUString& rsText, |
| const sal_Int8 nTextDirection) |
| { |
| const geometry::RealRectangle2D aTextBBox (GetTextBoundingBox(rxFont, rsText, nTextDirection)); |
| return css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1); |
| } |
| |
| |
| } } // end of namespace sdext::presenter |