2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
13 #include <QFontDatabase>
15 #include <QPainterPath>
16 #include <QSvgRenderer>
19 #include "imageeffects.h"
20 #include "loader/context.h"
21 #include "loader/image.h"
25 //BEGIN Font-------------------------------------------------------------------
27 Font::Font(int id
, int size
)
29 , m_families(QFontDatabase::applicationFontFamilies(id
))
30 , m_font(m_families
.empty()?QString():m_families
[0], size
) {
31 //for(int i=0;i<m_families.size();i++)
32 //kDebug() << "Familiy[" << i << "] = " << m_families[i];
35 Font::Font(const QFont
& font
)
43 QFontDatabase::removeApplicationFont(m_id
);
46 FontPtr
Font::create(Context
* ctx
, const QString
& file
) {
48 if(FontPtr
*f
= ctx
->get
<FontPtr
>(file
))
51 int font_id
= QFontDatabase::addApplicationFont(file
);
53 retv
= FontPtr(new Font(font_id
) );
60 //END Font---------------------------------------------------------------------
63 //BEGIN FontGlyph--------------------------------------------------------------
69 bool m_inner_background_init
;
70 QImage m_inner_background
;
72 FontGlyph() : m_inner_background_init(false) {}
75 //END FontGlyph----------------------------------------------------------------
77 typedef boost::shared_ptr
<QSvgRenderer
> Svg
;
78 typedef boost::shared_ptr
<FontGlyph
> FontGlyphPtr
;
81 //BEGIN Image------------------------------------------------------------------
83 Image::Image(int width
,
85 : m_image(width
, height
, QImage::Format_ARGB32_Premultiplied
)
92 p
.fillRect(QRect(0,0,width
,height
), Qt::blue
);
96 Image::Image(Context
* ctx
,
100 , m_draw_over(true) {
102 if( QImage
*i
= ctx
->get
<QImage
>(file
) )
105 m_image
= QImage(file
);
106 if(use_cache
) ctx
->put(file
, m_image
);
111 void Image::init_painter(QPainter
* p
) {
112 p
->setMatrix(m_draw_matrix
);
113 p
->setOpacity(m_draw_opacity
);
114 p
->setRenderHint(QPainter::Antialiasing
);
115 p
->setRenderHint(QPainter::TextAntialiasing
);
116 p
->setRenderHint(QPainter::SmoothPixmapTransform
);
118 p
->setCompositionMode(QPainter::CompositionMode_SourceOver
);
120 p
->setCompositionMode(QPainter::CompositionMode_Source
);
124 void Image::clear(const QColor
& color
) {
125 QPainter
p(&m_image
);
126 p
.setCompositionMode(QPainter::CompositionMode_Source
);
127 p
.fillRect(0,0,width(),height(), color
);
131 void Image::fillRect(const QRectF
& rect
,
132 const QBrush
& brush
) {
133 QPainter
p(&m_image
);
136 p
.fillRect(rect
, brush
);
140 void Image::drawLine(const QPointF
& from
,
144 QPainter
p(&m_image
);
147 p
.setPen( QPen( col
, width
) );
148 p
.drawLine(from
, to
);
152 void Image::drawImage(const QRectF
& dest
,
153 const Image
& src_img
,
155 QPainter
p(&m_image
);
158 p
.drawImage(dest
, src_img
.m_image
, src
.isNull()
159 ? src_img
.m_image
.rect() : src
);
163 bool Image::drawImage(Context
* ctx
,
165 const QString
& src_img
,
168 Image
img(ctx
, src_img
, use_cache
);
169 if(img
.width()==0 || img
.height()==0)
171 QRectF s
= src
.isNull() ? QRectF(0,0,img
.width(),img
.height()) :
172 QRectF(src
.x()*img
.width(),src
.y()*img
.height(),
173 src
.width()*img
.width(),src
.height()*img
.height());
175 QPainter
p(&m_image
);
178 p
.drawImage(dest
, img
.m_image
, s
);
183 bool Image::drawSVG(Context
* ctx
,
185 const QString
& file
) {
188 if( Svg
*s
= ctx
->get
<Svg
>(file
) )
191 svg
= Svg(new QSvgRenderer(file
));
200 QPainter
p(&m_image
);
203 p
.setViewport(dest
.toRect());
209 bool Image::drawGlyph(Context
* ctx
,
212 unsigned int glyph_num
,
216 bool draw_inner_bg
) {
217 QChar
glyph(glyph_num
);
218 FontGlyphPtr font_glyph
;
220 QString k
= file
+ QString(":%04x").arg(glyph_num
);
221 if(FontGlyphPtr
*f
= ctx
->get
<FontGlyphPtr
>(k
))
224 /* get the font (from cache if possible) */
225 FontPtr font
= Font::create(ctx
, file
);
231 font_glyph
= FontGlyphPtr(new FontGlyph
);
234 /* get a few metrics */
235 QFontMetrics
fm(font
->m_font
);
237 if(!fm
.inFont(glyph
))
241 int w
= fm
.width(glyph
);
242 font_glyph
->m_height
= h
;
244 /* create the path from the char */
245 font_glyph
->m_path
.addText((h
-w
)/2, fm
.ascent(), font
->m_font
, glyph
);
248 ctx
->put(k
, font_glyph
);
251 /* create lazily the inner background region */
252 if(!font_glyph
->m_inner_background_init
&& draw_inner_bg
253 && (_bg
.style() != Qt::NoBrush
&& !(_bg
.style() <= 14 && _bg
.color().alpha()==0))) {
254 //14 is the last color-based brush
256 int h
= font_glyph
->m_height
;
257 QImage
bg_img(h
, h
, QImage::Format_ARGB32_Premultiplied
);
258 bg_img
.fill( QColor(Qt::black
).rgba() ); //fill all black
260 /* render the piece in blue */
263 p
.setBrush( Qt::blue
);
264 p
.setPen( Qt::NoPen
);
265 p
.setCompositionMode(QPainter::CompositionMode_Source
);
266 p
.setRenderHint(QPainter::Antialiasing
, true);
267 p
.drawPath(font_glyph
->m_path
);
270 /* flood fill the connected component where blue is <192 with a transparent color */
271 ImageEffects::floodFillBlueThreshold(bg_img
, QPoint(0,0), Qt::transparent
, 192, true);
273 /* And we've got our region */
274 font_glyph
->m_inner_background
= bg_img
.createAlphaMask();
275 font_glyph
->m_inner_background
.setColor(0, Qt::transparent
);
276 font_glyph
->m_inner_background_init
= true;
279 /* draw the glyph, at last :) */
280 int h
= font_glyph
->m_height
;
281 QPainter
p(&m_image
);
284 p
.translate(dest
.x(), dest
.y());
285 p
.scale(dest
.width()/h
, dest
.height()/h
);
287 //14 is the last color-based brush
288 if(_bg
.style() != Qt::NoBrush
&& !(_bg
.style() <= 14 && _bg
.color().alpha()==0)) {
290 QMatrix m
= bg
.matrix();
291 m
= m
* QMatrix().translate(-dest
.x(), -dest
.y());
292 m
= m
* QMatrix().scale(h
/dest
.width(), h
/dest
.height());
296 QMatrix m
= p
.matrix();
297 QRectF r
= m
.mapRect(QRectF(0,0,h
,h
));
298 QRect ir
= r
.toRect();
299 QImage
tmp(ir
.size(), QImage::Format_ARGB32_Premultiplied
);
303 ptmp
.setRenderHint(QPainter::Antialiasing
);
304 ptmp
.setRenderHint(QPainter::TextAntialiasing
);
305 ptmp
.setRenderHint(QPainter::SmoothPixmapTransform
);
306 ptmp
.translate(-ir
.x(), -ir
.y());
307 ptmp
.setMatrix(m
, true);
308 ptmp
.drawImage(QRect(0,0,h
,h
), font_glyph
->m_inner_background
);
309 if(border
> 0.0 || !_fg
.isOpaque() ) {
310 ptmp
.setBrush( _fg
.isOpaque() ? QBrush(Qt::NoBrush
) : QBrush(Qt::red
) );
311 ptmp
.setPen( (border
> 0.0)
312 ? QPen( Qt::green
, h
*border
/100.0, Qt::SolidLine
, Qt::RoundCap
, Qt::RoundJoin
)
314 ptmp
.drawPath(font_glyph
->m_path
);
316 ptmp
.setCompositionMode(QPainter::CompositionMode_SourceIn
);
317 ptmp
.fillRect(QRect(0,0,h
,h
), bg
);
320 p
.drawImage(ir
, tmp
);
323 else if(border
> 0.0 || !_fg
.isOpaque() ) {
324 p
.setBrush( _fg
.isOpaque() ? Qt::NoBrush
: bg
);
325 p
.setPen( (border
> 0.0)
326 ? QPen(bg
, h
*border
/100.0, Qt::SolidLine
, Qt::RoundCap
, Qt::RoundJoin
)
328 p
.drawPath(font_glyph
->m_path
);
331 if(_fg
.style() != Qt::NoBrush
) {
333 QMatrix m
= fg
.matrix();
334 m
= m
* QMatrix().translate(-dest
.x(), -dest
.y());
335 m
= m
* QMatrix().scale(h
/dest
.width(), h
/dest
.height());
339 p
.setPen( Qt::NoPen
);
340 p
.drawPath(font_glyph
->m_path
);
346 void Image::expBlur(double radius
) {
347 if(m_image
.format() != QImage::Format_RGB32
348 && m_image
.format() != QImage::Format_ARGB32
349 && m_image
.format() != QImage::Format_ARGB32_Premultiplied
)
350 m_image
= m_image
.convertToFormat(QImage::Format_ARGB32_Premultiplied
);
351 ImageEffects::expBlur(m_image
, int(radius
) );
355 Image
Image::createShadow(double radius
,
358 const QPointF
& offset
) {
359 Image
retv(width()+grow
.x(), height()+grow
.y());
360 int px
= int(grow
.x()*0.5+offset
.x());
361 int py
= int(grow
.y()*0.5+offset
.y());
364 retv
.m_image
.fill(0);
366 p
.begin(&retv
.m_image
);
367 p
.setCompositionMode(QPainter::CompositionMode_Source
);
368 p
.fillRect( QRect(px
, py
, width(), height()), color
);
369 p
.setCompositionMode(QPainter::CompositionMode_DestinationAtop
);
370 p
.drawImage( QPoint(px
, py
), m_image
);
373 ImageEffects::expBlur(retv
.m_image
, int(radius
) );
377 //END Image--------------------------------------------------------------------
379 //BEGIN Glyph------------------------------------------------------------------
381 Glyph::Glyph(const QString
& c
, int d
)
382 : m_font_valid(false)
386 Glyph::Glyph(Context
* ctx
, const QString
& file
, const QChar
& c
, int d
)
387 : m_font_valid(false)
391 if(FontPtr ff
= Font::create(ctx
, file
)) {
398 Glyph::Glyph(const QChar
& c
)
399 : m_font_valid(false)
405 //END Glyph--------------------------------------------------------------------
407 } //end namespace Loader