/* * Copyright (c) 1987, 1988, 1989, 1990, 1991 Stanford University * Copyright (c) 1991 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Stanford and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Stanford and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL STANFORD OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ /* * X11-dependent bitmap code */ #include #include #include #include #include #include #include #include #include #include #include Bitmap::Bitmap() { rep_ = nil; } Bitmap* Bitmap::open(const char* filename) { Display* d = Session::instance()->default_display(); DisplayRep* r = d->rep(); unsigned int w, h; Pixmap p; int x0, y0; if ( XReadBitmapFile( r->display_, r->root_, filename, &w, &h, &p, &x0, &y0 ) != BitmapSuccess ) { return nil; } Bitmap* bm = new Bitmap; BitmapRep* b = new BitmapRep; bm->rep_ = b; b->display_ = d; b->pwidth_ = w; b->pheight_ = h; b->width_ = d->to_coord(w); b->height_ = d->to_coord(h); b->pixmap_ = p; if (x0 == -1 && y0 == -1) { b->left_ = 0; b->right_ = d->to_coord(w); b->bottom_ = 0; b->top_ = d->to_coord(h); } else { b->left_ = d->to_coord(-x0); b->right_ = d->to_coord(w - x0); b->bottom_ = d->to_coord(y0 - h); b->top_ = d->to_coord(y0); } return bm; } Bitmap::Bitmap( const void* data, unsigned int w, unsigned int h, int x0, int y0 ) { Display* d = Session::instance()->default_display(); DisplayRep* r = d->rep(); BitmapRep* b = new BitmapRep; rep_ = b; b->display_ = d; b->pwidth_ = w; b->pheight_ = h; b->width_ = d->to_coord(w); b->height_ = d->to_coord(h); if (x0 == -1 && y0 == -1) { b->left_ = 0; b->right_ = d->to_coord(w); b->bottom_ = 0; b->top_ = d->to_coord(h); } else { b->left_ = d->to_coord(-x0); b->right_ = d->to_coord(w - x0); b->bottom_ = d->to_coord(y0 - h); b->top_ = d->to_coord(y0); } if (data != nil) { b->pixmap_ = XCreateBitmapFromData( r->display_, r->root_, (char*)data, w, h ); } else { b->pixmap_ = XCreatePixmap(r->display_, r->root_, w, h, 1); GC gc = XCreateGC(r->display_, b->pixmap_, 0, nil); XSetForeground(r->display_, gc, 0); XFillRectangle(r->display_, b->pixmap_, gc, 0, 0, w, h); XFreeGC(r->display_, gc); } } Bitmap::Bitmap(const Font* f, long c, float scale) { Display* d = Session::instance()->default_display(); DisplayRep* r = d->rep(); XDisplay* dpy = r->display_; BitmapRep* b = new BitmapRep; rep_ = b; int w, h; int x, y; XFontStruct* info = f->rep(d)->font_; if ( c >= info->min_char_or_byte2 && c <= info->max_char_or_byte2 && info->per_char != nil ) { long i = c - info->min_char_or_byte2; w = info->per_char[i].rbearing - info->per_char[i].lbearing; h = info->per_char[i].ascent + info->per_char[i].descent; x = info->per_char[i].lbearing; y = info->per_char[i].ascent; } else { w = info->max_bounds.rbearing - info->min_bounds.lbearing; h = info->max_bounds.ascent + info->max_bounds.descent; x = info->min_bounds.lbearing; y = info->max_bounds.ascent; } int pw = Math::max(1, int(w * scale)); int ph = Math::max(1, int(h * scale)); w = Math::max(1, w); h = Math::max(1, h); Pixmap map = XCreatePixmap(dpy, r->root_, w, h, 1); GC gc = XCreateGC(dpy, map, 0, nil); XSetFont(dpy, gc, info->fid); XSetForeground(dpy, gc, 0); XFillRectangle(dpy, map, gc, 0, 0, pw, ph); XSetForeground(dpy, gc, 1); char ch = char(c); XDrawString(dpy, map, gc, -x, y, &ch, 1); if (scale != 1.0) { XImage* source = XGetImage(dpy, map, 0, 0, w, h, 0x01, ZPixmap); XFreePixmap(dpy, map); map = XCreatePixmap(dpy, r->root_, pw, ph, 1); XFillRectangle(dpy, map, gc, 0, 0, pw, ph); XImage* dest = XGetImage(dpy, map, 0, 0, pw, ph, 0x01, ZPixmap); for (int dy = 0; dy < ph; ++dy) { int sy = int(float(dy) / scale); for (int dx = 0; dx < pw; ++dx) { int sx = int(float(dx) / scale); XPutPixel( dest, dx, ph - 1 - dy, XGetPixel(source, sx, h - 1 - sy) ); } } XPutImage(dpy, map, gc, dest, 0, 0, 0, 0, pw, ph); XDestroyImage(source); XDestroyImage(dest); } XFreeGC(dpy, gc); b->display_ = d; b->pixmap_ = map; b->pwidth_ = pw; b->pheight_ = ph; b->width_ = d->to_coord(pw); b->height_ = d->to_coord(ph); b->left_ = d->to_coord(x) * scale; b->right_ = d->to_coord(x + w) * scale; b->top_ = d->to_coord(y) * scale; b->bottom_ = d->to_coord(y - h) * scale; } Bitmap::Bitmap(const Bitmap& bm) { rep_ = new BitmapRep(bm.rep_, BitmapRep::copy); flush(); } Bitmap::~Bitmap() { delete rep_; } Coord Bitmap::width() const { return rep()->width_; } Coord Bitmap::height() const { return rep()->height_; } unsigned int Bitmap::pwidth() const { return rep()->pwidth_; } unsigned int Bitmap::pheight() const { return rep()->pheight_; } Coord Bitmap::left_bearing() const { return -rep()->left_; } Coord Bitmap::right_bearing() const { return rep()->right_; } Coord Bitmap::ascent() const { return rep()->top_; } Coord Bitmap::descent() const { return -rep()->bottom_; } void Bitmap::poke(boolean set, int x, int y) { BitmapRep* b = rep(); b->fill(); unsigned long p = set ? 1 : 0; XPutPixel(rep()->image_, x, b->pheight_ - 1 - y, p); b->modified_ = true; } boolean Bitmap::peek(int x, int y) const { BitmapRep* b = rep(); b->fill(); unsigned long pixel = XGetPixel(b->image_, x, b->pheight_ - 1 - y); return pixel != 0; } void Bitmap::flush() const { rep()->flush(); } /* class BitmapRep */ BitmapRep::BitmapRep() { image_ = nil; modified_ = false; } /* * The second parameter requests a simple transformation, but * we don't support that anymore. It got broken somewhere along the line * and no one complained, so presumably no one will mind if it is ignored * completely. The only exception is inverse, which is straightforward. */ BitmapRep::BitmapRep(BitmapRep* b, unsigned int t) { display_ = b->display_; DisplayRep* r = display_->rep(); image_ = nil; modified_ = true; left_ = b->left_; right_ = b->right_; bottom_ = b->bottom_; top_ = b->top_; width_ = b->width_; height_ = b->height_; pwidth_ = b->pwidth_; pheight_ = b->pheight_; pixmap_ = XCreatePixmap(r->display_, r->root_, pwidth_, pheight_, 1); b->fill(); fill(); for (register int bx = 0; bx < pwidth_; bx++) { for (register int by = 0; by < pheight_; by++) { unsigned long pixel; if (bx >= 0 && bx < b->pwidth_ && by >= 0 && by < b->pheight_) { pixel = XGetPixel(b->image_, bx, b->pheight_ - by - 1); } else { pixel = 0; } if (t == inv) { pixel = !pixel; } XPutPixel(image_, bx, pheight_ - by - 1, pixel); } } } BitmapRep::~BitmapRep() { if (image_ != nil) { XDestroyImage(image_); } if (pixmap_ != nil) { XFreePixmap(display_->rep()->display_, pixmap_); } } void BitmapRep::fill() { if (image_ == nil) { image_ = XGetImage( display_->rep()->display_, pixmap_, 0, 0, pwidth_, pheight_, 0x01, ZPixmap ); } } void BitmapRep::flush() { if (modified_) { modified_ = false; XDisplay* dpy = display_->rep()->display_; GC gc = XCreateGC(dpy, pixmap_, 0, nil); XPutImage(dpy, pixmap_, gc, image_, 0, 0, 0, 0, pwidth_, pheight_); XFreeGC(dpy, gc); } }