From c243fa897f37dabeade187ac74ea5cd175e80a22 Mon Sep 17 00:00:00 2001 From: simonb Date: Tue, 4 Apr 2006 12:16:26 +0000 Subject: rotated XFonts (and minor ext tab alignment fixes) --- ChangeLog | 5 ++ src/Container.cc | 8 +-- src/FbTk/Text.hh | 10 +-- src/FbTk/XFontImp.cc | 180 +++++++++++++++++++++------------------------------ src/FbTk/XFontImp.hh | 41 ++++++------ src/FbWinFrame.cc | 15 ++++- 6 files changed, 119 insertions(+), 140 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4288513..c6f6a94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ (Format: Year/Month/Day) Changes for 0.9.16: +*06/04/04: + * Rotated X Fonts again, plus minor external tab alignment fixes (Simon) + - Still need to do XmbFonts. Most people probably load those + instead of XFont these days. Will need yet another approach... + FbTk/XFontImp.hh/cc FbTk/Text.hh FbWinFrame.cc Container.cc *06/04/02: * size_t fixes. (Thanks Semushin Slava aka php-coder) *06/03/27: diff --git a/src/Container.cc b/src/Container.cc index 6f811ef..db3e401 100644 --- a/src/Container.cc +++ b/src/Container.cc @@ -382,6 +382,7 @@ void Container::repositionItems() { unsigned int total_width; unsigned int cur_width; unsigned int height; + // unrotate if (m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) { total_width = cur_width = width(); @@ -438,11 +439,6 @@ void Container::repositionItems() { next_x = total_width - max_width_per_client - borderW; } - // when rot270, our borderwidth adjustment actually needs to be at the - // other end (i.e. top), so this puts it there - if (m_orientation == FbTk::ROT270) - next_x += 2*borderW; - int tmpx, tmpy; unsigned int tmpw, tmph; for (; it != it_end; ++it, next_x += direction*(max_width_per_client + borderW + extra)) { @@ -460,7 +456,7 @@ void Container::repositionItems() { tmph = height; FbTk::translateCoords(m_orientation, tmpx, tmpy, total_width, height); - FbTk::translatePosition(m_orientation, tmpx, tmpy, tmpw, tmph); + FbTk::translatePosition(m_orientation, tmpx, tmpy, tmpw, tmph, borderW); FbTk::translateSize(m_orientation, tmpw, tmph); // resize each clients including border in size diff --git a/src/FbTk/Text.hh b/src/FbTk/Text.hh index f04642d..ceb0f19 100644 --- a/src/FbTk/Text.hh +++ b/src/FbTk/Text.hh @@ -77,7 +77,7 @@ inline void translateCoords(Orientation orient, int &x, int &y, unsigned int w, // When positioning an X11 box inside another area, we need to // relocate the x,y coordinates -inline void translatePosition(Orientation orient, int &x, int &y, unsigned int w, unsigned int h) { +inline void translatePosition(Orientation orient, int &x, int &y, unsigned int w, unsigned int h, unsigned int bw) { int orig_x = x; int orig_y = y; @@ -86,14 +86,14 @@ inline void translatePosition(Orientation orient, int &x, int &y, unsigned int w case ROT0: break; case ROT90: - x -= h; + x -= h + 2*bw; break; case ROT180: - x -= w; - y -= h; + x -= w + 2*bw; + y -= h + 2*bw; break; case ROT270: - y -= w; + y -= w + 2*bw; break; } diff --git a/src/FbTk/XFontImp.cc b/src/FbTk/XFontImp.cc index eeb0830..1bf54a7 100644 --- a/src/FbTk/XFontImp.cc +++ b/src/FbTk/XFontImp.cc @@ -40,8 +40,10 @@ using namespace std; namespace FbTk { -XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0), - m_angle(0), m_rotate(true) { +XFontImp::XFontImp(const char *fontname):m_fontstruct(0) { + for (int i = ROT0; i <= ROT270; ++i) + m_rotfonts[i] = 0; + if (fontname != 0) load(fontname); } @@ -49,20 +51,21 @@ XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0), XFontImp::~XFontImp() { if (m_fontstruct != 0) XFreeFont(App::instance()->display(), m_fontstruct); - if (m_rotfont != 0) - freeRotFont(); + + for (int i = ROT0; i <= ROT270; ++i) + if (m_rotfonts[i] != 0) + freeRotFont(m_rotfonts[i]); } int XFontImp::ascent() const { if (m_fontstruct == 0) return 0; - if (m_rotfont != 0) - return m_rotfont->max_ascent; return m_fontstruct->ascent; } bool XFontImp::load(const std::string &fontname) { + XFontStruct *font = XLoadQueryFont(App::instance()->display(), fontname.c_str()); if (font == 0) return false; @@ -71,10 +74,9 @@ bool XFontImp::load(const std::string &fontname) { m_fontstruct = font; //set new font - if (m_rotfont != 0) { - freeRotFont(); // free old rotated font - rotate(m_angle); // allocate new rotated font and rotate it to old angle - } + for (int i = ROT0; i <= ROT270; ++i) + if (m_rotfonts[i] != 0) + freeRotFont(m_rotfonts[i]); return true; } @@ -84,8 +86,8 @@ void XFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text return; // use roated font functions? - if (m_rotfont != 0 && m_rotate) { - drawRotText(w.drawable(), screen, gc, text, len, x, y); + if (orient != ROT0 && m_rotfonts[orient] != 0) { + drawRotText(w.drawable(), screen, gc, text, len, x, y, orient); return; } @@ -97,10 +99,6 @@ unsigned int XFontImp::textWidth(const char * const text, unsigned int size) con if (text == 0 || m_fontstruct == 0) return 0; - // check rotated font? - if (m_rotfont != 0) - return rotTextWidth(text, size); - return XTextWidth(m_fontstruct, text, size); } @@ -111,28 +109,13 @@ unsigned int XFontImp::height() const { return m_fontstruct->ascent + m_fontstruct->descent; } -void XFontImp::rotate(int angle) { +void XFontImp::rotate(FbTk::Orientation orient) { //we must have a font loaded before we rotate - if (m_fontstruct == 0 || m_fontstruct->per_char == 0) + if (m_fontstruct == 0 || m_fontstruct->per_char == 0 || orient == ROT0) return; - if (m_rotfont != 0) - freeRotFont(); - - // no need for rotating, use regular font - if (angle == 0) { - m_angle = 0; - return; - } - _FB_USES_NLS; - //get positive angle - while (angle < 0) - angle += 360; - - m_angle = angle; - // X system default vars Display *dpy = App::instance()->display(); Window rootwin = DefaultRootWindow(dpy); @@ -145,12 +128,6 @@ void XFontImp::rotate(int angle) { unsigned char *vertdata, *bitdata; int ascent, descent, lbearing, rbearing; - // get nearest vertical or horizontal direction - int dir = (int)((angle+45.0)/90.0)%4; - - if (dir == 0) // no rotation - return; - // create the depth 1 canvas bitmap FbTk::FbPixmap canvas(rootwin, boxlen, boxlen, 1); @@ -160,9 +137,10 @@ void XFontImp::rotate(int angle) { font_gc.setFont(m_fontstruct->fid); // allocate space for rotated font - m_rotfont = new(nothrow) XRotFontStruct; + m_rotfonts[orient] = new(nothrow) XRotFontStruct; + XRotFontStruct *rotfont = m_rotfonts[orient]; - if (m_rotfont == 0) { + if (rotfont == 0) { cerr<<"RotFont: "<<_FBTKTEXT(Error, OutOfMemory, "Out of memory", "Something couldn't allocate memory")<dir = dir; - m_rotfont->min_char = min_char; - m_rotfont->max_char = max_char; - m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent; - m_rotfont->max_descent = m_fontstruct->max_bounds.descent; - m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent; + rotfont->min_char = min_char; + rotfont->max_char = max_char; + rotfont->max_ascent = m_fontstruct->max_bounds.ascent; + rotfont->max_descent = m_fontstruct->max_bounds.descent; + rotfont->height = rotfont->max_ascent + rotfont->max_descent; // font needs rotation // loop through each character @@ -191,17 +168,17 @@ void XFontImp::rotate(int angle) { index = ichar - m_fontstruct->min_char_or_byte2; // per char dimensions ... - ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent; - descent = m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent; - lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing; - rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing; - m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width; + ascent = rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent; + descent = rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent; + lbearing = rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing; + rbearing = rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing; + rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width; // some space chars have zero body, but a bitmap can't have if (!ascent && !descent) - ascent = m_rotfont->per_char[ichar-32].ascent = 1; + ascent = rotfont->per_char[ichar-32].ascent = 1; if (!lbearing && !rbearing) - rbearing = m_rotfont->per_char[ichar-32].rbearing = 1; + rbearing = rotfont->per_char[ichar-32].rbearing = 1; // glyph width and height when vertical vert_w = rbearing - lbearing; @@ -235,8 +212,8 @@ void XFontImp::rotate(int angle) { "XCreateImage failed for some reason") << "." << endl; free(vertdata); - delete m_rotfont; - m_rotfont = 0; + delete rotfont; + m_rotfonts[orient] = 0; return; } @@ -250,7 +227,7 @@ void XFontImp::rotate(int angle) { I1->format = XYBitmap; // width, height of rotated character - if (dir == 2) { + if (orient == ROT180) { bit_w = vert_w; bit_h = vert_h; } else { @@ -261,8 +238,8 @@ void XFontImp::rotate(int angle) { // width in bytes bit_len = (bit_w-1)/8 + 1; - m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w; - m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h; + rotfont->per_char[ichar-32].glyph.bit_w = bit_w; + rotfont->per_char[ichar-32].glyph.bit_h = bit_h; // reserve memory for the rotated image bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1); @@ -277,8 +254,8 @@ void XFontImp::rotate(int angle) { "XCreateImage failed for some reason") << "." << endl; free(bitdata); - delete m_rotfont; - m_rotfont = 0; + delete rotfont; + m_rotfonts[orient] = 0; return; } @@ -288,10 +265,10 @@ void XFontImp::rotate(int angle) { for (j = 0; j < bit_h; j++) { for (i = 0; i < bit_w; i++) { char val = 0; - if (dir == 1) { + if (orient == ROT270) { val = vertdata[i*vert_len + (vert_w-j-1)/8] & (128>>((vert_w-j-1)%8)); - } else if (dir == 2) { + } else if (orient == ROT180) { val = vertdata[(vert_h-j-1)*vert_len + (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8)); } else { @@ -306,11 +283,11 @@ void XFontImp::rotate(int angle) { } // create this character's bitmap - m_rotfont->per_char[ichar-32].glyph.bm = + rotfont->per_char[ichar-32].glyph.bm = XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1); // put the image into the bitmap - XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm, + XPutImage(dpy, rotfont->per_char[ichar-32].glyph.bm, font_gc.gc(), I2, 0, 0, 0, 0, bit_w, bit_h); // free the image and data @@ -320,29 +297,28 @@ void XFontImp::rotate(int angle) { } -void XFontImp::freeRotFont() { - if (m_rotfont == 0) - return; +void XFontImp::freeRotFont(XRotFontStruct *rotfont) { // loop through each character and free its pixmap - for (int ichar = m_rotfont->min_char - 32; - ichar <= m_rotfont->max_char - 32; ++ichar) { - XFreePixmap(App::instance()->display(), m_rotfont->per_char[ichar].glyph.bm); + for (int ichar = rotfont->min_char - 32; + ichar <= rotfont->max_char - 32; ++ichar) { + XFreePixmap(App::instance()->display(), rotfont->per_char[ichar].glyph.bm); } - delete m_rotfont; - m_rotfont = 0; + delete rotfont; + rotfont = 0; } -void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const { +void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const { Display *dpy = App::instance()->display(); static GC my_gc = 0; - int xp, yp, dir, ichar; + int xp, yp, ichar; + + XRotFontStruct *rotfont = m_rotfonts[orient]; if (text == NULL || len<1) return; - dir = m_rotfont->dir; if (my_gc == 0) my_gc = XCreateGC(dpy, w, 0, 0); @@ -359,52 +335,44 @@ void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size // make sure it's a printing character if (ichar >= 0 && ichar<95) { // suitable offset - if (dir == 1) { - xp = x-m_rotfont->per_char[ichar].ascent; - yp = y-m_rotfont->per_char[ichar].rbearing; - } else if (dir == 2) { - xp = x-m_rotfont->per_char[ichar].rbearing; - yp = y-m_rotfont->per_char[ichar].descent+1; - } else { - xp = x-m_rotfont->per_char[ichar].descent+1; - yp = y+m_rotfont->per_char[ichar].lbearing; + if (orient == ROT270) { + xp = x-rotfont->per_char[ichar].ascent; + yp = y-rotfont->per_char[ichar].rbearing; + } else if (orient == ROT180) { + xp = x-rotfont->per_char[ichar].rbearing; + yp = y-rotfont->per_char[ichar].descent+1; + } else { // ROT90 + xp = x-rotfont->per_char[ichar].descent; + yp = y+rotfont->per_char[ichar].lbearing; } // draw the glyph - XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm); + XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm); XSetTSOrigin(dpy, my_gc, xp, yp); XFillRectangle(dpy, w, my_gc, xp, yp, - m_rotfont->per_char[ichar].glyph.bit_w, - m_rotfont->per_char[ichar].glyph.bit_h); + rotfont->per_char[ichar].glyph.bit_w, + rotfont->per_char[ichar].glyph.bit_h); // advance position - if (dir == 1) - y -= m_rotfont->per_char[ichar].width; - else if (dir == 2) - x -= m_rotfont->per_char[ichar].width; + if (orient == ROT270) + y -= rotfont->per_char[ichar].width; + else if (orient == ROT180) + x -= rotfont->per_char[ichar].width; else - y += m_rotfont->per_char[ichar].width; + y += rotfont->per_char[ichar].width; } } } -unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const { - - if (text == 0) - return 0; - - unsigned int width = 0; - for (size_t i = 0; i= 0 && ichar < 95) - width += m_rotfont->per_char[ichar].width; - } +bool XFontImp::validOrientation(FbTk::Orientation orient) { + if (orient == ROT0 || m_rotfonts[orient]) + return true; - return width; + rotate(orient); + return m_rotfonts[orient] != 0; } }; diff --git a/src/FbTk/XFontImp.hh b/src/FbTk/XFontImp.hh index 6b5a34b..0312fb5 100644 --- a/src/FbTk/XFontImp.hh +++ b/src/FbTk/XFontImp.hh @@ -38,50 +38,49 @@ public: bool load(const std::string &filename); unsigned int textWidth(const char * const text, unsigned int size) const; unsigned int height() const; - int angle() const { return m_angle; } int ascent() const; int descent() const { return m_fontstruct ? m_fontstruct->descent : 0; } void drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const; + bool validOrientation(FbTk::Orientation orient); + bool loaded() const { return m_fontstruct != 0; } - void rotate(int angle); - /// enable/disable rotation witout alloc/dealloc rotfont structures - void setRotate(bool val) { m_rotate = val; } + private: - void freeRotFont(); - void drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const; - unsigned int rotTextWidth(const char * const text, unsigned int size) const; struct BitmapStruct { - int bit_w; + int bit_w; int bit_h; Pixmap bm; }; - struct XRotCharStruct { - int ascent; - int descent; - int lbearing; - int rbearing; + int ascent; + int descent; + int lbearing; + int rbearing; int width; BitmapStruct glyph; }; struct XRotFontStruct { - int dir; - int height; - int max_ascent; - int max_descent; - int max_char; + int height; + int max_ascent; + int max_descent; + int max_char; int min_char; XRotCharStruct per_char[95]; }; - XRotFontStruct *m_rotfont; ///< rotated font structure + + void rotate(FbTk::Orientation orient); + + void freeRotFont(XRotFontStruct * rotfont); + void drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const; + + XRotFontStruct *m_rotfonts[4]; ///< rotated font structure (only 3 used) XFontStruct *m_fontstruct; ///< X font structure - int m_angle; ///< the rotated angle - bool m_rotate; ///< used to disable/enable rotation temprarly without reallocating m_rotfont + }; } // end namespace FbTk diff --git a/src/FbWinFrame.cc b/src/FbWinFrame.cc index 0e33b5a..18bae9a 100644 --- a/src/FbWinFrame.cc +++ b/src/FbWinFrame.cc @@ -42,6 +42,7 @@ #include #include +#include using namespace std; // mem_fun FbWinFrame::FbWinFrame(BScreen &screen, FbWinFrameTheme &theme, FbTk::ImageControl &imgctrl, @@ -334,6 +335,7 @@ void FbWinFrame::alignTabs() { if (m_tabmode != EXTERNAL) return; + FbTk::Orientation orig_orient = m_tab_container.orientation(); unsigned int orig_tabwidth = m_tab_container.maxWidthPerClient(); @@ -374,14 +376,14 @@ void FbWinFrame::alignTabs() { if (orig_orient != FbTk::ROT90) m_tab_container.hide(); m_tab_container.setOrientation(FbTk::ROT90); m_tab_container.setAlignment(Container::LEFT); - tabx = x() + width(); + tabx = x() + width() + m_window.borderWidth(); taby = y(); break; case RIGHTBOTTOM: if (orig_orient != FbTk::ROT90) m_tab_container.hide(); m_tab_container.setOrientation(FbTk::ROT90); m_tab_container.setAlignment(Container::RIGHT); - tabx = x() + width(); + tabx = x() + width() + m_window.borderWidth(); taby = y() + height() - m_tab_container.height(); break; case BOTTOMLEFT: @@ -1106,6 +1108,15 @@ void FbWinFrame::reconfigureTitlebar() { if (m_tabmode == INTERNAL) m_tab_container.moveResize(next_x, m_bevel, space_left, button_size); + else { + if (m_use_tabs) { + if (m_tab_container.orientation() == FbTk::ROT0) { + m_tab_container.resize(m_tab_container.width(), button_size); + } else { + m_tab_container.resize(button_size, m_tab_container.height()); + } + } + } next_x += m_label.width() + m_bevel; -- cgit v0.11.2