Drop shadows in TCPDF - tcpdf

I believe there is no native method in TCPDF to create drop shadows. Any ideas how I could create such an effect with any of its other methods? I was first thinking of creating a small gradient next to each edge (for rectangles) but found no way to create gradients with different alpha channels.

Something like this:
class MYPDF extends TCPDF {
public function addShadow($x,$y,$h,$w){
for($i=5;$i>=1;$i-=0.5){
$this->SetAlpha(0.1-($i*0.02));
$this->SetFillColor(0, 0, 0);
$this->SetDrawColor(0, 0, 0);
$this->Rect($x+$i, $y+$i, $h, $w, 'DF');
}
$this->SetAlpha(1);
}
}

Related

Qt 5 drawing translate(), rotate(), font fill issues

I'm writing my first Qt 5 application... This uses a third-party map library (QGeoView).
I need to draw an object (something like a stylized airplane) over this map. Following the library coding guidelines, I derived from the base class QGVDrawItem my QGVAirplane.
The airplane class contains heading and position values: such values must be used to draw the airplane on the map (of course in the correct position and with correct heading). The library requires QGVDrawItem derivatives to override three base class methods:
QPainterPath projShape() const;
void projPaint(QPainter* painter);
void onProjection(QGVMap* geoMap)
The first method is used to achieve the area of the map that needs to be updated. The second is the method responsible to draw the object on the map. The third method is needed to reproject the point from the coordinate space on the map (it's not relevant for the solution of my problem).
My code looks like this:
void onProjection(QGVMap* geoMap)
{
QGVDrawItem::onProjection(geoMap);
mProjPoint = geoMap->getProjection()->geoToProj(mPoint);
}
QPainterPath projShape() const
{
QRectF _bounding = createGlyph().boundingRect();
double _size = fmax(_bounding.height(), _bounding.width());
QPainterPath _bounding_path;
_bounding_path.addRect(0,0,_size,_size);
_bounding_path.translate(mProjPoint.x(), mProjPoint.y());
return _bounding_path;
}
// This function creates the path containing the airplane glyph
// along with its label
QPainterPath createGlyph() const
{
QPainterPath _path;
QPolygon _glyph = QPolygon();
_glyph << QPoint(0,6) << QPoint(0,8) << QPoint(14,6) << QPoint(28,8) << QPoint(28,6) << QPoint(14,0);
_path.addPolygon(_glyph);
_path.setFillRule(Qt::FillRule::OddEvenFill);
_path.addText(OFF_X_TEXT, OFF_Y_TEXT, mFont , QString::number(mId));
QTransform _transform;
_transform.rotate(mHeading);
return _transform.map(_path);
}
// This function is the actual painting method
void drawGlyph(QPainter* painter)
{
painter->setRenderHints(QPainter::Antialiasing, true);
painter->setBrush(QBrush(mColor));
painter->setPen(QPen(QBrush(Qt::black), 1));
QPainterPath _path = createGlyph();
painter->translate(mProjPoint.x(), mProjPoint.y());
painter->drawPath(_path);
}
Of course:
mProjPoint is the position of the airplane,
mHeading is the heading (the direction where the airplane is pointing),
mId is a number identifying the airplane (will be displayed as a label under airplane glyph),
mColor is the color assigned to the airplane.
The problem here is the mix of rotation and translation. Transformation: since the object is rotated, projShape() methods return a bounding rectangle that's not fully overlapping the object drawn on the map...
I also suspect that the center of the object is not correctly pointed on mProjPoint. I tried many times trying to translate the bounding rectangle to center the object without luck.
Another minor issue is the fillup of the font... the label under the airplane glyph is not solid, but it is filled with the same color of the airplane.
How can I fix this?
Generically speaking, the general pattern for rotation is to scale about the origin first and then finish with your final translation.
The following is pseudocode, but it illustrates the need to shift your object's origin to (0, 0) prior to doing any rotation or scaling. After the rotate and scale are done, the object can be moved back from (0, 0) back to where it came from. From here, any post-translation step may be applied.
translate( -origin.x, -origin.y );
rotate( angle );
scale( scale.x, scale y);
translate( origin.x, origin.y );
translate( translation.x, translation.y )
I finally managed to achieve the result I meant....
QPainterPath projShape() const
{
QPainterPath _path;
QRectF _glyph_bounds = _path.boundingRect();
QPainterPath _textpath;
_textpath.addText(0, 0, mFont, QString::number(mId));
QRectF _text_bounds = _textpath.boundingRect();
_textpath.translate(_glyph_bounds.width()/2-_text_bounds.width()/2, _glyph_bounds.height()+_text_bounds.height());
_path.addPath(_textpath);
QTransform _transform;
_transform.translate(mProjPoint.x(),mProjPoint.y());
_transform.rotate(360-mHeading);
_transform.translate(-_path.boundingRect().width()/2, -_path.boundingRect().height()/2);
return _transform.map(_path);
}
void projPaint(QPainter* painter)
{
painter->setRenderHint(QPainter::Antialiasing, true);
painter->setRenderHint(QPainter::TextAntialiasing, true);
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
painter->setRenderHint(QPainter::HighQualityAntialiasing, true);
painter->setBrush(QBrush(mColor));
painter->setPen(QPen(QBrush(Qt::black), 1));
painter->setFont(mFont);
QPainterPath _path = projShape();
painter->drawPath(_path);
}
Unluckly I still suffer the minor issue with text fill mode:
I would like to have a solid black fill for the text instead of the mColor fill I use for the glyph/polygon.

How to get a color of a pixel in the image using p5.js and use it as a fill color?

I'm learning p5.js. I've tried the following code to draw a circle each time I move the mouse with fill color that changes according to color of an image.
let img;
function setup() {
createCanvas(400, 400);
loadImage('https://upload.wikimedia.org/wikipedia/commons/e/ef/Hayao_Miyazaki.jpg', img => {
image(img, 0, 0);
});
noStroke();
}
function draw() {
let c = get(mouseX, mouseY);
fill(c);
circle(mouseX, mouseY, 30);
}
But it seems to take the color from the canvas, not from an image. Because of that, if you don't move your mouse fast enough the color doesn't change at all, and even if you do, the amount of color is much more limited, in other words it's not what I intended.
I can get the colors right if I put the loadImage() part inside of a draw function, but then only one circle at a time is visible.
May be I should store every pixel of an image in the array and get the values from an array, without using get()? Is it possible?
I think I'm missing something simple, please help.
img.get(mouseX, mouseY) to get values from image, not a whole canvas
I too though that img.get(mouseX, mouseY); would work and #mevfy-y also said it so it might work?!

How to create a skin for fl.controls.Slider with custom height in actionscript only?

I created a skin called customSliderTrack in the graphical editor of Adobe Flash CS5.5. This Slider is now in the "library" of the FLA file.
I can apply this skin with the following code:
var cls:Class = getDefinitionByName("CustomSliderTrack") as Class;
var tmpTrack:Sprite = new cls();
slider.setStyle("sliderTrackSkin",tmpTrack);
However due to the binary nature of the FLA file and lack of compatibility of different Versions of Adobe Flash I need to implement it all in Actionscript.
I understand that cls is a MovieClip object but I cant get the same results with new MovieClip(). I think this might be related to the dashed Lines in the graphical editor(I modified the default SliderTrack_skin). I havn't found out yet what they mean and how to replace them with Actionscript code.
setStyle automatically sets the track.height and track.width. In case of the track.height the slider.height attribute does not seem to have any effect. To work around this problem simply set the track.height to the best value.
To access the track extend the Slider class and override the configUI Function:
public class CustomSlider extends Slider
{
override protected function configUI():void
{
// Call configUI of Slider
super.configUI();
// The sprite that will contain the track
var t:Sprite = new Sprite();
// Draw the content into the sprite
t.graphics.beginFill(0x000000, 0.1);
t.graphics.drawRect(0, -15, width, 30);
t.graphics.endFill();
// Set the Sprite to be the one used by the Slider
this.setStyle("sliderTrackSkin",t);
// Reset the height to the value that it should be
track.height = 30;
}
}
Depending on the complexity of your track asset, you could accomplish this with the drawing API: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html
A very simple example would be:
var track:Sprite = new Sprite();
track.graphics.lineStyle(2, 0xcccccc);
track.graphics.beginFill(0x000000, 1);
track.graphics.drawRect(0, 0, 400, 20);
track.graphics.endFill();
track.scale9Grid = new Rectangle(2, 2, 396, 16);
slider.setStyle("sliderTrackSkin",track);
This creates a track that is just a black rectangle, 400x20 pixels in size. You can set the scale9grid in code to control how the skin scales. In the example above the rectangle's border wont scale, but the black rectangle inside will. Experimenting with the methods in the drawing API could be all you need.
If you need a more complex asset, I'd recommend loading an image and then passing that in to slider.setStyle.

Do screen transitions when the user clicks on a bitmap

I am working on an eBook app where I need to transition the screens from left to right and right to left. I tried many samples that I've found, but I am not successful. How do I change the screen frequently when user clicks on the screen from left to right and right to left. What is the basic idea for transition of pages. I went through the Developer Support Forum thread "page-flip effect" looking for a solution, but I can't see it.
The following code is not logical. In which position do I have to implement flip effect for flipping pages in the screen and how to implement it?
public class TransitionScreen extends FullScreen implements Runnable{
private int angle = 0;
Bitmap fromBmp,toBmp;
public TransitionScreen(){
}
public TransitionScreen(AnimatableScreen from,AnimatableScreen to) {
fromBmp = new Bitmap(Display.getWidth(), Display.getHeight());
toBmp = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics fromGraphics = Graphics.create(fromBmp);
Graphics toGraphics = Graphics.create(toBmp);
Object eventLock = getApplication().getEventLock();
synchronized(eventLock) {
from.drawAnimationBitmap(fromGraphics);
to.drawAnimationBitmap(toGraphics);
// Interpolate myOffset to target
// Set animating = false if myOffset = target
invalidate();
}
try {
synchronized (Application.getEventLock()) {
Ui.getUiEngine().suspendPainting(true);
}
} catch (final Exception ex) {
}
}
protected void paint(Graphics g){
//control x,y positions of the bitmaps in the timer task and the paint will just paint where they go
g.drawBitmap(0,0, 360,
480, toBmp, 0, 0);
g.drawBitmap(0, 0, 360,
480, fromBmp, 0, 0);
// invalidate();
}
protected boolean touchEvent(TouchEvent event) {
if (!this.isFocus())
return true;
if (event.getEvent() == TouchEvent.CLICK) {
// invalidate();
}
return super.touchEvent(event);
}
}
Assuming you're working with version 5.0 or later of the OS, this page has a simple example:
http://docs.blackberry.com/en/developers/deliverables/11958/Screen_transitions_detailed_overview_806391_11.jsp
From where did you get the code sample posted in your question? That code does not appear to be close to working.
Update: you can actually animate transitions like this yourself fairly simply. Assuming you know how to use the Timer class, you basically have a class-level variable that stores the current x-position of your first Bitmap (the variable would have a value of 0 initially). In each timer tick, you subtract some amount from the x-position (however many pixels you want it to move each tick) and then call invalidate();.
In each call to the paint method, then, you just draw the first bitmap using the x-position variable for the call's x parameter, and draw the second bitmap using the x-position variable plus the width of the first bitmap. The resulting effect is to see the first bitmap slide off to the left while the second slides in from the right.
A caveat : Because this is java (which means the timer events are not real-time - they're not guaranteed to occur when you want them to), this animation will be kind of erratic and unsmooth. The best way to get smooth animation like this is to pre-render your animation cells (where each is a progressive combination of the two bitmaps you're transitioning between), so that in the paint method you're just drawing a single pre-rendered bitmap.

How can I fill an actionscript 3 polygon with a solid color?

I'm building a map editor for a project and need to draw a hexagon and fill it with a solid color. I have the shape correct but for the life of me can't figure out how to fill it. I suspect it may be due to whether the thing is a Shape, Sprite or UIComponent. Here is what I have for the polygon itself:
import com.Polygon;
import mx.core.UIComponent;
public class greenFillOne extends UIComponent {
public var hexWidth:Number = 64;
public var hexLength:Number = 73;
public function greenFillOne() {
var hexPoly:Polygon = new Polygon;
hexPoly.drawPolygon(40,6,27+(hexWidth*.25),37,0x499b0e,1,30);
addChild(hexPoly);
}
}
The Polygon class isn't a standard Adobe library, so I don't know the specifics. However, assuming that it uses the standard flash API, it should be no problem to add some code to extend the function. You just need to make sure you're doing a graphics.beginFill before the graphics.lineTo / graphics.moveTo functions. And then finish with graphics.endFill.
e.g.,
var g:Graphics = someShape.graphics;
g.beginFill(0xFF0000,.4); // red, .4 opacity
g.moveTo(x1,y1);
g.lineTo(x2,y2);
g.lineTo(x3,y3);
g.lineTo(x1,y1);
g.endFill();
This will draw a triangle filled with .4 red.
I'll put this here because answering it as a comment to Glenn goes past the character limit. My actionscript file extends UIComponent. When I created a variable hexPoly:Polygon = new Polygon; it would render the outline of the hex, but would not fill it no matter what I did. I examined polygon.as and duplicated the methods, but as a sprite and it worked. So, I need to figure out how to wrap the polygon as a sprite, or just leave it as is.
var hexPoly:Sprite = new Sprite;
hexPoly.graphics.beginFill(0x4ea50f,1);
hexPoly.graphics.moveTo(xCenter+(hexWidth*.25)+Math.sin(radians(330))*radius,offset+(radius-Math.cos(radians(330))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(30))*radius,offset+(radius-Math.cos(radians(30))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(90))*radius,offset+(radius-Math.cos(radians(90))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(150))*radius,offset+(radius-Math.cos(radians(150))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(210))*radius,offset+(radius-Math.cos(radians(210))*radius));
hexPoly.graphics.lineTo(xCenter+(hexWidth*.25)+Math.sin(radians(270))*radius,offset+(radius-Math.cos(radians(270))*radius));
hexPoly.graphics.endFill();
addChild(hexPoly);

Resources