diff options
author | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
---|---|---|
committer | jcid <devnull@localhost> | 2008-09-24 18:44:40 +0200 |
commit | c377e06400f138325a9a9d43d91a9272691867a1 (patch) | |
tree | 49f3ca1c46af11a058a68714899d4137ec717618 /dw/fltkimgbuf.cc | |
parent | 642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff) |
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'dw/fltkimgbuf.cc')
-rw-r--r-- | dw/fltkimgbuf.cc | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc new file mode 100644 index 00000000..b8beb1cb --- /dev/null +++ b/dw/fltkimgbuf.cc @@ -0,0 +1,347 @@ +/* + * Dillo Widget + * + * Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + + +#include "fltkcore.hh" +#include "../lout/misc.hh" + +#include <fltk/draw.h> +#include <fltk/Color.h> + +using namespace fltk; + +namespace dw { +namespace fltk { + +using namespace container::typed; + +FltkImgbuf::FltkImgbuf (Type type, int width, int height) +{ + //printf("FltkImgbuf: new root %p\n", this); + init (type, width, height, NULL); +} + +FltkImgbuf::FltkImgbuf (Type type, int width, int height, FltkImgbuf *root) +{ + //printf("FltkImgbuf: new scaled %p, root is %p\n", this, root); + init (type, width, height, root); +} + +void FltkImgbuf::init (Type type, int width, int height, FltkImgbuf *root) +{ + this->root = root; + this->type = type; + this->width = width; + this->height = height; + + // TODO: Maybe this is only for root buffers + switch (type) { + case RGBA: bpp = 4; break; + case RGB: bpp = 3; break; + default: bpp = 1; break; + } + //fprintf(stderr,"FltkImgbuf::init width=%d height=%d bpp=%d\n", + // width, height, bpp); + rawdata = new uchar[bpp * width * height]; + // Set light-gray as interim background color. + memset(rawdata, 222, width*height*bpp); + + refCount = 1; + deleteOnUnref = true; + copiedRows = new misc::BitSet (height); + + // The list is only used for root buffers. + if (isRoot()) + scaledBuffers = new container::typed::List <FltkImgbuf> (true); + else + scaledBuffers = NULL; + + if (!isRoot()) { + // Scaling + for (int row = 0; row < root->height; row++) { + if (root->copiedRows->get (row)) + scaleRow (row, root->rawdata + row*root->width*root->bpp); + } + } +} + +FltkImgbuf::~FltkImgbuf () +{ + //printf ("FltkImgbuf::~FltkImgbuf (%s)\n", isRoot() ? "root" : "scaled"); + + //if (root) + // printf("FltkImgbuf[scaled %p, root is %p]: deleted\n", this, root); + //else + // printf("FltkImgbuf[root %p]: deleted\n", this); + + if (!isRoot()) + root->detachScaledBuf (this); + + delete[] rawdata; + delete copiedRows; + + if (scaledBuffers) + delete scaledBuffers; +} + +/** + * \brief This method is called for the root buffer, when a scaled buffer + * removed. + */ +void FltkImgbuf::detachScaledBuf (FltkImgbuf *scaledBuf) +{ + scaledBuffers->detachRef (scaledBuf); + + //printf("FltkImgbuf[root %p]: scaled buffer %p is detached, %d left\n", + // this, scaledBuf, scaledBuffers->size ()); + + if (refCount == 0 && scaledBuffers->isEmpty () && deleteOnUnref) + // If the root buffer is not used anymore, but this is the last scaled + // buffer. + // See also: FltkImgbuf::unref(). + delete this; +} + +void FltkImgbuf::setCMap (int *colors, int num_colors) +{ +} + +inline void FltkImgbuf::scaleRow (int row, const core::byte *data) +{ + int sr1 = scaledY (row); + int sr2 = scaledY (row + 1); + + for(int sr = sr1; sr < sr2; sr++) { + // Avoid multiple passes. + if (copiedRows->get(sr)) continue; + + copiedRows->set (sr, true); + if (sr == sr1) { + for(int px = 0; px < root->width; px++) { + int px1 = px * width / root->width; + int px2 = (px+1) * width / root->width; + for(int sp = px1; sp < px2; sp++) { + memcpy(rawdata + (sr*width + sp)*bpp, data + px*bpp, bpp); + } + } + } else { + memcpy(rawdata + sr*width*bpp, rawdata + sr1*width*bpp, width*bpp); + } + } +} + +void FltkImgbuf::copyRow (int row, const core::byte *data) +{ + assert (isRoot()); + + // Flag the row done and copy its data. + copiedRows->set (row, true); + memcpy(rawdata + row * width * bpp, data, width * bpp); + + // Update all the scaled buffers of this root image. + for (Iterator <FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext(); ) { + FltkImgbuf *sb = it.getNext (); + sb->scaleRow(row, data); + } +} + +void FltkImgbuf::newScan () +{ + if (isRoot()) { + for (Iterator<FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext();){ + FltkImgbuf *sb = it.getNext (); + sb->copiedRows->clear(); + } + } +} + +core::Imgbuf* FltkImgbuf::getScaledBuf (int width, int height) +{ + if (root) + return root->getScaledBuf (width, height); + + if (width == this->width && height == this->height) { + ref (); + return this; + } + + for (Iterator <FltkImgbuf> it = scaledBuffers->iterator(); it.hasNext(); ) { + FltkImgbuf *sb = it.getNext (); + if (sb->width == width && sb->height == height) { + sb->ref (); + return sb; + } + } + + /* This size is not yet used, so a new buffer has to be created. */ + FltkImgbuf *sb = new FltkImgbuf (type, width, height, this); + scaledBuffers->append (sb); + return sb; +} + +void FltkImgbuf::getRowArea (int row, dw::core::Rectangle *area) +{ + // TODO: May have to be adjusted. + + if (isRoot()) { + /* root buffer */ + area->x = 0; + area->y = row; + area->width = width; + area->height = 1; + //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n", + // area->x, area->y, area->width, area->height); + } else { + // scaled buffer + int sr1 = scaledY (row); + int sr2 = scaledY (row + 1); + + area->x = 0; + area->y = sr1; + area->width = width; + area->height = sr2 - sr1; + //fprintf(stderr,"::getRowArea: area x=%d y=%d width=%d height=%d\n", + // area->x, area->y, area->width, area->height); + } +} + +int FltkImgbuf::getRootWidth () +{ + return root ? root->width : width; +} + +int FltkImgbuf::getRootHeight () +{ + return root ? root->height : height; +} + +void FltkImgbuf::ref () +{ + refCount++; + + //if (root) + // printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", + // this, root, refCount); + //else + // printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount); +} + +void FltkImgbuf::unref () +{ + //if (root) + // printf("FltkImgbuf[scaled %p, root is %p]: ref() => %d\n", + // this, root, refCount - 1); + //else + // printf("FltkImgbuf[root %p]: ref() => %d\n", this, refCount - 1); + + if (--refCount == 0) { + if (isRoot ()) { + // Root buffer, it must be ensured that no scaled buffers are left. + // See also FltkImgbuf::detachScaledBuf(). + if (scaledBuffers->isEmpty () && deleteOnUnref) + delete this; + else + printf("FltkImgbuf[root %p]: not deleted\n", this); + } else + // Scaled buffer buffer, simply delete it. + delete this; + } +} + +bool FltkImgbuf::lastReference () +{ + return refCount == 1 && + (scaledBuffers == NULL || scaledBuffers->isEmpty ()); +} + +void FltkImgbuf::setDeleteOnUnref (bool deleteOnUnref) +{ + assert (isRoot ()); + this->deleteOnUnref = deleteOnUnref; +} + +bool FltkImgbuf::isReferred () +{ + return refCount != 0 || + (scaledBuffers != NULL && !scaledBuffers->isEmpty ()); +} + + +int FltkImgbuf::scaledY(int ySrc) +{ + // TODO: May have to be adjusted. + assert (root != NULL); + return ySrc * height / root->height; +} + +void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot, + int x, int y, int width, int height) +{ + // TODO (i): Implementation. + // TODO (ii): Clarify the question, whether "target" is the current widget + // (and so has not to be passed at all). + +/* + setcolor (0); + + for (int row = y; row < y + height; row++) { + if (copiedRows->get (row)) { + ::fltk::Rectangle rect (x + xRoot, row + yRoot, width, 1); + fillrect (rect); + } + } +*/ + + //fprintf(stderr,"::draw: xRoot=%d x=%d yRoot=%d y=%d width=%d height=%d\n" + // " this->width=%d this->height=%d\n", + // xRoot, x, yRoot, y, width, height, this->width, this->height); + +//{ +#if 1 + if (x > this->width || y > this->height) { + return; + } + + if (x + width > this->width) { + width = this->width - x; + } + + if (y + height > this->height) { + height = this->height - y; + } + + // almost OK for rows. For some unknown reason it trims the bottom and + // rightmost parts when scrolling. + ::fltk::Rectangle rect (xRoot + x, yRoot + y, width, height); + PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; + drawimage(rawdata+bpp*(y*this->width + x),ptype,rect,bpp*this->width); + +#else + // OK for full image. + ::fltk::Rectangle rect (xRoot, yRoot, this->width, this->height); + PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; + drawimage(rawdata,ptype,rect); +#endif +//} +} + +} // namespace dw +} // namespace fltk |