LibreOffice Module vcl (master) 1
outdev/gradient.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
20#include <memory>
21#include <cassert>
22
23#include <tools/poly.hxx>
24#include <vcl/gdimtf.hxx>
25#include <vcl/gradient.hxx>
26#include <vcl/metaact.hxx>
27#include <vcl/settings.hxx>
28#include <vcl/outdev.hxx>
29#include <vcl/virdev.hxx>
30#include <vcl/window.hxx>
31
32#include <salgdi.hxx>
33
34#define GRADIENT_DEFAULT_STEPCOUNT 0
35
37 const Gradient& rGradient )
38{
40
41 // Convert rectangle to a tools::PolyPolygon by first converting to a Polygon
42 tools::Polygon aPolygon ( rRect );
43 tools::PolyPolygon aPolyPoly ( aPolygon );
44
45 DrawGradient ( aPolyPoly, rGradient );
46}
47
49 const Gradient& rGradient )
50{
52
55 // don't return on mbOutputClipped here, as we may need to draw the clipped metafile, even if the output is clipped
56
57 if ( rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() )
58 {
60 {
62
64 SetLineColor( aColor );
65 SetFillColor( aColor );
66 DrawPolyPolygon( rPolyPoly );
67 Pop();
68 return;
69 }
70
71 Gradient aGradient( rGradient );
72
74 aGradient.MakeGrayscale();
75
76 DrawGradientToMetafile( rPolyPoly, rGradient );
77
79 return;
80
81 // Clip and then draw the gradient
82 if( !tools::Rectangle( PixelToLogic( Point() ), GetOutputSize() ).IsEmpty() )
83 {
84 const tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
85
86 // convert rectangle to pixels
87 tools::Rectangle aRect( ImplLogicToDevicePixel( aBoundRect ) );
88 aRect.Normalize();
89
90 // do nothing if the rectangle is empty
91 if ( !aRect.IsEmpty() )
92 {
93 tools::PolyPolygon aClixPolyPoly( ImplLogicToDevicePixel( rPolyPoly ) );
94 bool bDrawn = false;
95
96 if( !mpGraphics && !AcquireGraphics() )
97 return;
98
99 // secure clip region
101 IntersectClipRegion( aBoundRect );
102
105
106 // try to draw gradient natively
107 if (!mbOutputClipped)
108 bDrawn = mpGraphics->DrawGradient( aClixPolyPoly, aGradient, *this );
109
110 if (!bDrawn && !mbOutputClipped)
111 {
112 // draw gradients without border
114 {
116 mbInitLineColor = true;
117 }
118
119 mbInitFillColor = true;
120
121 // calculate step count if necessary
122 if ( !aGradient.GetSteps() )
124
125 if ( rPolyPoly.IsRect() )
126 {
127 // because we draw with no border line, we have to expand gradient
128 // rect to avoid missing lines on the right and bottom edge
129 aRect.AdjustLeft( -1 );
130 aRect.AdjustTop( -1 );
131 aRect.AdjustRight( 1 );
132 aRect.AdjustBottom( 1 );
133 }
134
135 // if the clipping polypolygon is a rectangle, then it's the same size as the bounding of the
136 // polypolygon, so pass in a NULL for the clipping parameter
137 if( aGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial )
138 DrawLinearGradient( aRect, aGradient, aClixPolyPoly.IsRect() ? nullptr : &aClixPolyPoly );
139 else
140 DrawComplexGradient( aRect, aGradient, aClixPolyPoly.IsRect() ? nullptr : &aClixPolyPoly );
141 }
142
143 Pop();
144 }
145 }
146 }
147
148 if( mpAlphaVDev )
149 {
150 const Color aFillCol( mpAlphaVDev->GetFillColor() );
152 mpAlphaVDev->DrawPolyPolygon( rPolyPoly );
153 mpAlphaVDev->SetFillColor( aFillCol );
154 }
155}
156
158{
159 const tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
160 const bool bOldOutput = IsOutputEnabled();
161
162 EnableOutput( false );
165 DrawGradient( aBoundRect, rGradient );
168 DrawPolyPolygon( rPolyPoly );
170 DrawGradient( aBoundRect, rGradient );
171 Pop();
172 EnableOutput( bOldOutput );
173}
174
176 const Gradient& rGradient )
177{
178 assert(!is_double_buffered_window());
179
180 if ( !mpMetaFile )
181 return;
182
183 if ( !(rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize()) )
184 return;
185
186 const tools::Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
187
188 if (aBoundRect.IsEmpty())
189 return;
190
191 Gradient aGradient( rGradient );
192
194 aGradient.MakeGrayscale();
195
196 if ( rPolyPoly.IsRect() )
197 {
198 mpMetaFile->AddAction( new MetaGradientAction( aBoundRect, std::move(aGradient) ) );
199 }
200 else
201 {
202 mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_BEGIN" ) );
203 mpMetaFile->AddAction( new MetaGradientExAction( rPolyPoly, rGradient ) );
204
205 ClipAndDrawGradientMetafile ( rGradient, rPolyPoly );
206
207 mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_END" ) );
208 }
209}
210
211namespace
212{
214 {
215 if ( nValue < 0 )
216 return 0;
217 else if ( nValue > 0xFF )
218 return 0xFF;
219 else
220 return static_cast<sal_uInt8>(nValue);
221 }
222}
223
225 const Gradient& rGradient,
226 const tools::PolyPolygon* pClixPolyPoly )
227{
228 assert(!is_double_buffered_window());
229
230 // get BoundRect of rotated rectangle
231 tools::Rectangle aRect;
232 Point aCenter;
233 Degree10 nAngle = rGradient.GetAngle() % 3600_deg10;
234
235 rGradient.GetBoundRect( rRect, aRect, aCenter );
236
237 bool bLinear = (rGradient.GetStyle() == GradientStyle::Linear);
238 double fBorder = rGradient.GetBorder() * aRect.GetHeight() / 100.0;
239 if ( !bLinear )
240 {
241 fBorder /= 2.0;
242 }
243 tools::Rectangle aMirrorRect = aRect; // used in style axial
244 aMirrorRect.SetTop( ( aRect.Top() + aRect.Bottom() ) / 2 );
245 if ( !bLinear )
246 {
247 aRect.SetBottom( aMirrorRect.Top() );
248 }
249
250 // colour-intensities of start- and finish; change if needed
251 tools::Long nFactor;
252 Color aStartCol = rGradient.GetStartColor();
253 Color aEndCol = rGradient.GetEndColor();
254 tools::Long nStartRed = aStartCol.GetRed();
255 tools::Long nStartGreen = aStartCol.GetGreen();
256 tools::Long nStartBlue = aStartCol.GetBlue();
257 tools::Long nEndRed = aEndCol.GetRed();
258 tools::Long nEndGreen = aEndCol.GetGreen();
259 tools::Long nEndBlue = aEndCol.GetBlue();
260 nFactor = rGradient.GetStartIntensity();
261 nStartRed = (nStartRed * nFactor) / 100;
262 nStartGreen = (nStartGreen * nFactor) / 100;
263 nStartBlue = (nStartBlue * nFactor) / 100;
264 nFactor = rGradient.GetEndIntensity();
265 nEndRed = (nEndRed * nFactor) / 100;
266 nEndGreen = (nEndGreen * nFactor) / 100;
267 nEndBlue = (nEndBlue * nFactor) / 100;
268
269 // gradient style axial has exchanged start and end colors
270 if ( !bLinear)
271 {
272 std::swap( nStartRed, nEndRed );
273 std::swap( nStartGreen, nEndGreen );
274 std::swap( nStartBlue, nEndBlue );
275 }
276
277 sal_uInt8 nRed;
278 sal_uInt8 nGreen;
279 sal_uInt8 nBlue;
280
281 // Create border
282 tools::Rectangle aBorderRect = aRect;
283 tools::Polygon aPoly( 4 );
284 if (fBorder > 0.0)
285 {
286 nRed = static_cast<sal_uInt8>(nStartRed);
287 nGreen = static_cast<sal_uInt8>(nStartGreen);
288 nBlue = static_cast<sal_uInt8>(nStartBlue);
289
290 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
291
292 aBorderRect.SetBottom( static_cast<tools::Long>( aBorderRect.Top() + fBorder ) );
293 aRect.SetTop( aBorderRect.Bottom() );
294 aPoly[0] = aBorderRect.TopLeft();
295 aPoly[1] = aBorderRect.TopRight();
296 aPoly[2] = aBorderRect.BottomRight();
297 aPoly[3] = aBorderRect.BottomLeft();
298 aPoly.Rotate( aCenter, nAngle );
299
300 ImplDrawPolygon( aPoly, pClixPolyPoly );
301
302 if ( !bLinear)
303 {
304 aBorderRect = aMirrorRect;
305 aBorderRect.SetTop( static_cast<tools::Long>( aBorderRect.Bottom() - fBorder ) );
306 aMirrorRect.SetBottom( aBorderRect.Top() );
307 aPoly[0] = aBorderRect.TopLeft();
308 aPoly[1] = aBorderRect.TopRight();
309 aPoly[2] = aBorderRect.BottomRight();
310 aPoly[3] = aBorderRect.BottomLeft();
311 aPoly.Rotate( aCenter, nAngle );
312
313 ImplDrawPolygon( aPoly, pClixPolyPoly );
314 }
315 }
316
317 // calculate step count
318 tools::Long nStepCount = GetGradientSteps(rGradient, aRect);
319
320 // minimal three steps and maximal as max color steps
321 tools::Long nAbsRedSteps = std::abs( nEndRed - nStartRed );
322 tools::Long nAbsGreenSteps = std::abs( nEndGreen - nStartGreen );
323 tools::Long nAbsBlueSteps = std::abs( nEndBlue - nStartBlue );
324 tools::Long nMaxColorSteps = std::max( nAbsRedSteps , nAbsGreenSteps );
325 nMaxColorSteps = std::max( nMaxColorSteps, nAbsBlueSteps );
326 tools::Long nSteps = std::min( nStepCount, nMaxColorSteps );
327 if ( nSteps < 3)
328 {
329 nSteps = 3;
330 }
331
332 double fScanInc = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps);
333 double fGradientLine = static_cast<double>(aRect.Top());
334 double fMirrorGradientLine = static_cast<double>(aMirrorRect.Bottom());
335
336 const double fStepsMinus1 = static_cast<double>(nSteps) - 1.0;
337 if ( !bLinear)
338 {
339 nSteps -= 1; // draw middle polygons as one polygon after loop to avoid gap
340 }
341
342 for ( tools::Long i = 0; i < nSteps; i++ )
343 {
344 // linear interpolation of color
345 const double fAlpha = static_cast<double>(i) / fStepsMinus1;
346 double fTempColor = static_cast<double>(nStartRed) * (1.0-fAlpha) + static_cast<double>(nEndRed) * fAlpha;
347 nRed = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
348 fTempColor = static_cast<double>(nStartGreen) * (1.0-fAlpha) + static_cast<double>(nEndGreen) * fAlpha;
349 nGreen = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
350 fTempColor = static_cast<double>(nStartBlue) * (1.0-fAlpha) + static_cast<double>(nEndBlue) * fAlpha;
351 nBlue = GetGradientColorValue(static_cast<tools::Long>(fTempColor));
352
353 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
354
355 // Polygon for this color step
356 aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(i) * fScanInc ) );
357 aRect.SetBottom( static_cast<tools::Long>( fGradientLine + ( static_cast<double>(i) + 1.0 ) * fScanInc ) );
358 aPoly[0] = aRect.TopLeft();
359 aPoly[1] = aRect.TopRight();
360 aPoly[2] = aRect.BottomRight();
361 aPoly[3] = aRect.BottomLeft();
362 aPoly.Rotate( aCenter, nAngle );
363
364 ImplDrawPolygon( aPoly, pClixPolyPoly );
365
366 if ( !bLinear )
367 {
368 aMirrorRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(i) * fScanInc ) );
369 aMirrorRect.SetTop( static_cast<tools::Long>( fMirrorGradientLine - (static_cast<double>(i) + 1.0)* fScanInc ) );
370 aPoly[0] = aMirrorRect.TopLeft();
371 aPoly[1] = aMirrorRect.TopRight();
372 aPoly[2] = aMirrorRect.BottomRight();
373 aPoly[3] = aMirrorRect.BottomLeft();
374 aPoly.Rotate( aCenter, nAngle );
375
376 ImplDrawPolygon( aPoly, pClixPolyPoly );
377 }
378 }
379 if ( bLinear)
380 return;
381
382 // draw middle polygon with end color
383 nRed = GetGradientColorValue(nEndRed);
384 nGreen = GetGradientColorValue(nEndGreen);
385 nBlue = GetGradientColorValue(nEndBlue);
386
387 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
388
389 aRect.SetTop( static_cast<tools::Long>( fGradientLine + static_cast<double>(nSteps) * fScanInc ) );
390 aRect.SetBottom( static_cast<tools::Long>( fMirrorGradientLine - static_cast<double>(nSteps) * fScanInc ) );
391 aPoly[0] = aRect.TopLeft();
392 aPoly[1] = aRect.TopRight();
393 aPoly[2] = aRect.BottomRight();
394 aPoly[3] = aRect.BottomLeft();
395 aPoly.Rotate( aCenter, nAngle );
396
397 ImplDrawPolygon( aPoly, pClixPolyPoly );
398
399}
400
402{
403 auto pOwnerWindow = GetOwnerWindow();
404 return pOwnerWindow && pOwnerWindow->SupportsDoubleBuffering();
405}
406
408 const Gradient& rGradient,
409 const tools::PolyPolygon* pClixPolyPoly )
410{
411 assert(!is_double_buffered_window());
412
413 // Determine if we output via Polygon or PolyPolygon
414 // For all rasteroperations other than Overpaint always use PolyPolygon,
415 // as we will get wrong results if we output multiple times on top of each other.
416 // Also for printers always use PolyPolygon, as not all printers
417 // can print polygons on top of each other.
418
419 std::optional<tools::PolyPolygon> xPolyPoly;
420 tools::Rectangle aRect;
421 Point aCenter;
422 Color aStartCol( rGradient.GetStartColor() );
423 Color aEndCol( rGradient.GetEndColor() );
424 tools::Long nStartRed = ( static_cast<tools::Long>(aStartCol.GetRed()) * rGradient.GetStartIntensity() ) / 100;
425 tools::Long nStartGreen = ( static_cast<tools::Long>(aStartCol.GetGreen()) * rGradient.GetStartIntensity() ) / 100;
426 tools::Long nStartBlue = ( static_cast<tools::Long>(aStartCol.GetBlue()) * rGradient.GetStartIntensity() ) / 100;
427 tools::Long nEndRed = ( static_cast<tools::Long>(aEndCol.GetRed()) * rGradient.GetEndIntensity() ) / 100;
428 tools::Long nEndGreen = ( static_cast<tools::Long>(aEndCol.GetGreen()) * rGradient.GetEndIntensity() ) / 100;
429 tools::Long nEndBlue = ( static_cast<tools::Long>(aEndCol.GetBlue()) * rGradient.GetEndIntensity() ) / 100;
430 tools::Long nRedSteps = nEndRed - nStartRed;
431 tools::Long nGreenSteps = nEndGreen - nStartGreen;
432 tools::Long nBlueSteps = nEndBlue - nStartBlue;
433 Degree10 nAngle = rGradient.GetAngle() % 3600_deg10;
434
435 rGradient.GetBoundRect( rRect, aRect, aCenter );
436
438 xPolyPoly = tools::PolyPolygon( 2 );
439
440 tools::Long nStepCount = GetGradientSteps(rGradient, rRect);
441
442 // at least three steps and at most the number of colour differences
443 tools::Long nSteps = std::max( nStepCount, tools::Long(2) );
444 tools::Long nCalcSteps = std::abs( nRedSteps );
445 tools::Long nTempSteps = std::abs( nGreenSteps );
446 if ( nTempSteps > nCalcSteps )
447 nCalcSteps = nTempSteps;
448 nTempSteps = std::abs( nBlueSteps );
449 if ( nTempSteps > nCalcSteps )
450 nCalcSteps = nTempSteps;
451 if ( nCalcSteps < nSteps )
452 nSteps = nCalcSteps;
453 if ( !nSteps )
454 nSteps = 1;
455
456 // determine output limits and stepsizes for all directions
457 tools::Polygon aPoly;
458 double fScanLeft = aRect.Left();
459 double fScanTop = aRect.Top();
460 double fScanRight = aRect.Right();
461 double fScanBottom = aRect.Bottom();
462 double fScanIncX = static_cast<double>(aRect.GetWidth()) / static_cast<double>(nSteps) * 0.5;
463 double fScanIncY = static_cast<double>(aRect.GetHeight()) / static_cast<double>(nSteps) * 0.5;
464
465 // all gradients are rendered as nested rectangles which shrink
466 // equally in each dimension - except for 'square' gradients
467 // which shrink to a central vertex but are not per-se square.
468 if( rGradient.GetStyle() != GradientStyle::Square )
469 {
470 fScanIncY = std::min( fScanIncY, fScanIncX );
471 fScanIncX = fScanIncY;
472 }
473 sal_uInt8 nRed = static_cast<sal_uInt8>(nStartRed), nGreen = static_cast<sal_uInt8>(nStartGreen), nBlue = static_cast<sal_uInt8>(nStartBlue);
474 bool bPaintLastPolygon( false ); // #107349# Paint last polygon only if loop has generated any output
475
476 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
477
478 if( xPolyPoly )
479 {
480 aPoly = rRect;
481 xPolyPoly->Insert( aPoly );
482 xPolyPoly->Insert( aPoly );
483 }
484 else
485 {
486 // extend rect, to avoid missing bounding line
487 tools::Rectangle aExtRect( rRect );
488
489 aExtRect.AdjustLeft( -1 );
490 aExtRect.AdjustTop( -1 );
491 aExtRect.AdjustRight(1 );
492 aExtRect.AdjustBottom(1 );
493
494 aPoly = aExtRect;
495 ImplDrawPolygon( aPoly, pClixPolyPoly );
496 }
497
498 // loop to output Polygon/PolyPolygon sequentially
499 for( tools::Long i = 1; i < nSteps; i++ )
500 {
501 // calculate new Polygon
502 fScanLeft += fScanIncX;
503 aRect.SetLeft( static_cast<tools::Long>( fScanLeft ) );
504 fScanTop += fScanIncY;
505 aRect.SetTop( static_cast<tools::Long>( fScanTop ) );
506 fScanRight -= fScanIncX;
507 aRect.SetRight( static_cast<tools::Long>( fScanRight ) );
508 fScanBottom -= fScanIncY;
509 aRect.SetBottom( static_cast<tools::Long>( fScanBottom ) );
510
511 if( ( aRect.GetWidth() < 2 ) || ( aRect.GetHeight() < 2 ) )
512 break;
513
514 if( rGradient.GetStyle() == GradientStyle::Radial || rGradient.GetStyle() == GradientStyle::Elliptical )
515 aPoly = tools::Polygon( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
516 else
517 aPoly = tools::Polygon( aRect );
518
519 aPoly.Rotate( aCenter, nAngle );
520
521 // adapt colour accordingly
522 const tools::Long nStepIndex = ( xPolyPoly ? i : ( i + 1 ) );
523 nRed = GetGradientColorValue( nStartRed + ( ( nRedSteps * nStepIndex ) / nSteps ) );
524 nGreen = GetGradientColorValue( nStartGreen + ( ( nGreenSteps * nStepIndex ) / nSteps ) );
525 nBlue = GetGradientColorValue( nStartBlue + ( ( nBlueSteps * nStepIndex ) / nSteps ) );
526
527 // either slow tools::PolyPolygon output or fast Polygon-Painting
528 if( xPolyPoly )
529 {
530 bPaintLastPolygon = true; // #107349# Paint last polygon only if loop has generated any output
531
532 xPolyPoly->Replace( xPolyPoly->GetObject( 1 ), 0 );
533 xPolyPoly->Replace( aPoly, 1 );
534
535 ImplDrawPolyPolygon( *xPolyPoly, pClixPolyPoly );
536
537 // #107349# Set fill color _after_ geometry painting:
538 // xPolyPoly's geometry is the band from last iteration's
539 // aPoly to current iteration's aPoly. The window outdev
540 // path (see else below), on the other hand, paints the
541 // full aPoly. Thus, here, we're painting the band before
542 // the one painted in the window outdev path below. To get
543 // matching colors, have to delay color setting here.
544 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
545 }
546 else
547 {
548 // #107349# Set fill color _before_ geometry painting
549 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
550
551 ImplDrawPolygon( aPoly, pClixPolyPoly );
552 }
553 }
554
555 // we should draw last inner Polygon if we output PolyPolygon
556 if( !xPolyPoly )
557 return;
558
559 const tools::Polygon& rPoly = xPolyPoly->GetObject( 1 );
560
561 if( rPoly.GetBoundRect().IsEmpty() )
562 return;
563
564 // #107349# Paint last polygon with end color only if loop
565 // has generated output. Otherwise, the current
566 // (i.e. start) color is taken, to generate _any_ output.
567 if( bPaintLastPolygon )
568 {
569 nRed = GetGradientColorValue( nEndRed );
570 nGreen = GetGradientColorValue( nEndGreen );
571 nBlue = GetGradientColorValue( nEndBlue );
572 }
573
574 mpGraphics->SetFillColor( Color( nRed, nGreen, nBlue ) );
575 ImplDrawPolygon( rPoly, pClixPolyPoly );
576}
577
579{
580 tools::Long nInc = (nMinRect < 50) ? 2 : 4;
581
582 return nInc;
583}
584
586{
587 // calculate step count
588 tools::Long nStepCount = rGradient.GetSteps();
589
590 if (nStepCount)
591 return nStepCount;
592
593 tools::Long nMinRect = 0;
594
595 if (rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial)
596 nMinRect = rRect.GetHeight();
597 else
598 nMinRect = std::min(rRect.GetWidth(), rRect.GetHeight());
599
600 tools::Long nInc = GetGradientStepCount(nMinRect);
601
602 if (!nInc)
603 nInc = 1;
604
605 return nMinRect / nInc;
606}
607
609{
610 Color aColor;
611
612 // we should never call on this function if any of these aren't set!
614
616 aColor = COL_BLACK;
618 aColor = COL_WHITE;
621
622 return aColor;
623}
624
625/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const StyleSettings & GetStyleSettings() const
sal_uInt8 GetBlue() const
sal_uInt8 GetRed() const
sal_uInt8 GetGreen() const
void AddAction(const rtl::Reference< MetaAction > &pAction)
Definition: gdimtf.cxx:581
sal_uInt16 GetStartIntensity() const
GradientStyle GetStyle() const
Degree10 GetAngle() const
sal_uInt16 GetEndIntensity() const
sal_uInt16 GetBorder() const
const Color & GetEndColor() const
void MakeGrayscale()
const Color & GetStartColor() const
void SetSteps(sal_uInt16 nSteps)
sal_uInt16 GetSteps() const
void GetBoundRect(const tools::Rectangle &rRect, tools::Rectangle &rBoundRect, Point &rCenter) const
Size GetOutputSize() const
Definition: outdev.hxx:328
virtual void InitClipRegion()
SAL_DLLPRIVATE bool is_double_buffered_window() const
void EnableOutput(bool bEnable=true)
Definition: outdev.cxx:342
DrawModeFlags mnDrawMode
Definition: outdev.hxx:221
bool mbOutputClipped
Definition: outdev.hxx:246
SAL_DLLPRIVATE tools::Rectangle ImplLogicToDevicePixel(const tools::Rectangle &rLogicRect) const
Convert a logical rectangle to a rectangle in physical device pixel units.
Definition: map.cxx:391
SAL_DLLPRIVATE void DrawGradientToMetafile(const tools::PolyPolygon &rPolyPoly, const Gradient &rGradient)
SAL_DLLPRIVATE void DrawComplexGradient(const tools::Rectangle &rRect, const Gradient &rGradient, const tools::PolyPolygon *pClipPolyPoly)
SAL_DLLPRIVATE void ImplDrawPolygon(const tools::Polygon &rPoly, const tools::PolyPolygon *pClipPolyPoly=nullptr)
Definition: polygon.cxx:445
virtual bool AcquireGraphics() const =0
Acquire a graphics device that the output device uses to draw on.
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
Definition: map.cxx:1169
SAL_DLLPRIVATE bool ImplIsRecordLayout() const
Definition: outdev.cxx:709
GDIMetaFile * mpMetaFile
Definition: outdev.hxx:186
void SetLineColor()
Definition: line.cxx:37
bool mbInitLineColor
Definition: outdev.hxx:249
SalGraphics * mpGraphics
Graphics context to draw on.
Definition: outdev.hxx:183
SAL_DLLPRIVATE void ImplDrawPolyPolygon(const tools::PolyPolygon &rPolyPoly, const tools::PolyPolygon *pClipPolyPoly)
Definition: polygon.cxx:463
SAL_DLLPRIVATE tools::Long GetGradientSteps(Gradient const &rGradient, tools::Rectangle const &rRect)
virtual bool UsePolyPolygonForComplexGradient()=0
bool mbInitClipRegion
Definition: outdev.hxx:253
void SetFillColor()
Definition: fill.cxx:29
virtual void ClipAndDrawGradientMetafile(const Gradient &rGradient, const tools::PolyPolygon &rPolyPoly)
void SetRasterOp(RasterOp eRasterOp)
Definition: outdev.cxx:321
bool IsDeviceOutputNecessary() const
Definition: outdev.hxx:482
VclPtr< VirtualDevice > mpAlphaVDev
Definition: outdev.hxx:197
virtual tools::Long GetGradientStepCount(tools::Long nMinRect)
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
Definition: stack.cxx:33
void DrawGradient(const tools::Rectangle &rRect, const Gradient &rGradient)
void DrawPolyPolygon(const tools::PolyPolygon &rPolyPoly)
Render the given poly-polygon.
Definition: polygon.cxx:36
void Pop()
Definition: stack.cxx:92
bool IsOutputEnabled() const
Definition: outdev.hxx:481
const AllSettings & GetSettings() const
Definition: outdev.hxx:289
bool mbLineColor
Definition: outdev.hxx:247
void IntersectClipRegion(const tools::Rectangle &rRect)
SAL_DLLPRIVATE Color GetSingleColorGradientFill()
virtual vcl::Window * GetOwnerWindow() const
Get the vcl::Window that this OutputDevice belongs to, if any.
Definition: outdev.hxx:1900
SAL_DLLPRIVATE void DrawLinearGradient(const tools::Rectangle &rRect, const Gradient &rGradient, const tools::PolyPolygon *pClipPolyPoly)
bool mbInitFillColor
Definition: outdev.hxx:250
const Color & GetFillColor() const
Definition: outdev.hxx:516
virtual void SetLineColor()=0
virtual void SetFillColor()=0
bool DrawGradient(const tools::PolyPolygon &rPolyPoly, const Gradient &rGradient, const OutputDevice &rOutDev)
const Color & GetWindowColor() const
sal_uInt16 Count() const
bool IsRect() const
tools::Rectangle GetBoundRect() const
tools::Rectangle GetBoundRect() const
void Rotate(const Point &rCenter, double fSin, double fCos)
constexpr Point Center() const
constexpr tools::Long GetWidth() const
constexpr void SetLeft(tools::Long v)
constexpr void SetTop(tools::Long v)
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr void SetRight(tools::Long v)
constexpr tools::Long Right() const
tools::Long AdjustTop(tools::Long nVertMoveDelta)
tools::Long AdjustRight(tools::Long nHorzMoveDelta)
constexpr void SetBottom(tools::Long v)
constexpr Point BottomRight() const
constexpr Point TopRight() const
constexpr tools::Long GetHeight() const
tools::Long AdjustBottom(tools::Long nVertMoveDelta)
tools::Long AdjustLeft(tools::Long nHorzMoveDelta)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
constexpr Point BottomLeft() const
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
sal_Int16 nValue
static sal_uInt8 GetGradientColorValue(tools::Long nValue)
int i
long Long
#define GRADIENT_DEFAULT_STEPCOUNT
unsigned char sal_uInt8