pjs/cmd/qtfe/drawing.cpp

497 строки
12 KiB
C++

/* $Id: drawing.cpp,v 1.1 1998-09-25 18:01:33 ramiro%netscape.com Exp $
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. Portions
* created by Warwick Allison, Kalle Dalheimer, Eirik Eng, Matthias
* Ettrich, Arnt Gulbrandsen, Haavard Nord and Paul Olav Tvete are
* Copyright (C) 1998 Warwick Allison, Kalle Dalheimer, Eirik Eng,
* Matthias Ettrich, Arnt Gulbrandsen, Haavard Nord and Paul Olav
* Tvete. All Rights Reserved.
*/
#include "libi18n.h"
#include "QtContext.h"
#include <qpainter.h>
#include <qdrawutl.h>
/* Taken from the xfe implementation. */
char *
QtContext::translateISOText(int charset, char *ISO_Text)
{
unsigned char *s;
/* charsets such as Shift-JIS contain 0240's that are valid */
if (INTL_CharSetType(charset) != SINGLEBYTE)
return ISO_Text;
/* When &nbsp; is encountered, display a normal space character instead.
This is necessary because the MIT fonts are messed up, and have a
zero-width character for nobreakspace, so we need to print it as a
normal space instead. */
if (ISO_Text)
for (s = (unsigned char *) ISO_Text; *s; s++)
if (*s == 0240) *s = ' ';
return ISO_Text;
}
static QFont getFontWithFamily( const char *fam, int pts, int wgt, bool ita )
{
QString familyList = fam;
QString token;
QString realFamily;
QFont returnFont( "times", pts, wgt, ita );
// debug( "Font family list: %s", fam );
int pos;
do {
pos = familyList.find( "," );
if ( pos != -1 ) {
token = familyList.left( pos );
familyList.remove( 0, pos + 1 );
} else {
token = familyList;
}
token = token.stripWhiteSpace();
if ( token[0] == '"' )
token.remove( 0, 1 );
int len = token.length();
if ( token[len - 1] == '"' )
token.remove( len - 1, 1 );
returnFont.setFamily( token );
// fi.setFont( returnFont ); Should chech if font family is available
// debug( "Font family chosen: %s", token.data() );
return returnFont;
} while (pos != -1 );
returnFont.setFamily( "times" );
return returnFont;
}
// return a QFont* for a given Netscape TextStruct.
// This will use a cached result if possible
QFont QtContext::getFont(LO_TextAttr *text_attr)
{
if (text_attr->FE_Data){
return *((QFont*) (text_attr->FE_Data));
}
const char* fam;
int pts, wgt;
bool ita;
if (!text_attr->font_face){
fam= (text_attr->fontmask & LO_FONT_FIXED) ? "courier" : "times";
}
else
fam=text_attr->font_face;
wgt=text_attr->font_weight;
ita=text_attr->fontmask & LO_FONT_ITALIC;
//#warning Matthias TODO implement charsets
// result->setCharSet(text_attr->charset);
pts = int(text_attr->point_size);
if ( pts <= 0) {
int size3 = 12;
switch ( text_attr->size ) {
case 1:
pts = 8;
break;
case 2:
pts = 10;
break;
case 3:
pts = 12;
break;
case 4:
pts = 14;
break;
case 5:
pts = 18;
break;
case 6:
pts = 24;
break;
default:
pts = (text_attr->size-6)*4+24;
}
pts = pts * size3 / 12;
}
QFont result = getFontWithFamily(fam, pts, wgt, ita);
if (!wgt) result.setBold(text_attr->fontmask & LO_FONT_BOLD);
result.setStrikeOut(text_attr->attrmask & LO_ATTR_STRIKEOUT);
result.setUnderline(text_attr->attrmask & LO_ATTR_UNDERLINE);
return result;
}
void QtContext::releaseTextAttrFeData(LO_TextAttr *attr){
if (attr->FE_Data){
delete (QFont*) (attr->FE_Data);
attr->FE_Data = 0;
}
}
void QtContext::displaySubtext( int /* iLocation */,
LO_TextStruct *text, int start_pos, int end_pos,
bool )
{
LO_TextAttr *text_attr = text->text_attr;
QFont font = getFont(text_attr);
QColor fg(text_attr->fg.red,
text_attr->fg.green,
text_attr->fg.blue);
QColor bg(text_attr->bg.red,
text_attr->bg.green,
text_attr->bg.blue);
painter()->setPen(fg);
painter()->setFont(font);
QColor obg = painter()->backgroundColor();
bool selected_p = false;
QFontMetrics fm = painter()->fontMetrics();
/* this check is inspired by the fxe. not too sure but it cannot really harm....
*/
if ((text->ele_attrmask & LO_ELE_SELECTED) &&
(start_pos >= text->sel_start) && (end_pos-1 <= text->sel_end))
selected_p = true;
/* use black and white for selections
*/
if (selected_p){
painter()->setBackgroundMode(OpaqueMode);
painter()->setBackgroundColor(black);
painter()->setPen(white);
}
else if (text->text_attr->no_background){
painter()->setPen(fg);
}
else {
painter()->setBackgroundMode(OpaqueMode);
painter()->setBackgroundColor(bg);
painter()->setPen(fg);
}
/* do the drawing */
painter()->drawText(text->x - documentXOffset(),
text->y + text->y_offset + fm.ascent() - documentYOffset(),
(char*) (text->text + start_pos),
end_pos - start_pos);
/* reset the background mode of the qpainter
*/
painter()->setBackgroundColor(TransparentMode);
painter()->setBackgroundColor(obg);
}
void QtContext::clearPainter()
{
if (internal_painter && internal_painter->isActive())
internal_painter->end();
if (internal_painter) delete internal_painter;
internal_painter = 0;
}
int QtContext::documentXOffset() const
{
return 0;
}
int QtContext::documentYOffset() const
{
return 0;
}
void QtContext::displayText (int iLocation, LO_TextStruct *text, bool){
displaySubtext(iLocation, text, 0, text->text_len, false);
}
void QtContext::getTextInfo(LO_TextStruct *text, LO_TextInfo *text_info){
#if defined(XP_WINDAUGE)
QFontMetrics fontMetrics(QFont("helvetica", 12)); // EE ###getFont(text->text_attr));
#else
QFontMetrics fontMetrics(getFont(text->text_attr));
#endif
text_info->max_width = fontMetrics.width((char*)text->text, text->text_len);
text_info->ascent = fontMetrics.ascent();
text_info->descent = fontMetrics.descent();
text_info->lbearing = fontMetrics.minLeftBearing();
text_info->rbearing = fontMetrics.minRightBearing();
}
void QtContext::getTextFrame(LO_TextStruct *text, int32 start,
int32 end, XP_Rect *frame)
{
QFontMetrics fontMetrics(getFont(text->text_attr));
frame->left = text->x + text->x_offset;
frame->top = text->y + text->y_offset;
frame->right = frame->left + fontMetrics.width( (char*)text->text+start,
end-start );
frame->bottom = frame->top + fontMetrics.lineSpacing();
}
void QtContext::displayTable(int loc, LO_TableStruct *ts){
// fe_Drawable *fe_drawable = CONTEXT_DATA (context)->drawable;
// long x = ts->x + ts->x_offset - CONTEXT_DATA (context)->document_x +
// fe_drawable->x_origin;
// long y = ts->y + ts->y_offset - CONTEXT_DATA (context)->document_y +
// fe_drawable->y_origin;
// if ((x > 0 && x > CONTEXT_DATA (context)->scrolled_width) ||
// (y > 0 && y > CONTEXT_DATA (context)->scrolled_height) ||
// (x + ts->width < 0) ||
// (y + ts->line_height< 0))
// return;
// painter()->drawText(text->x - documentXOffset(),
// text->y + text->y_offset + fm.ascent() - documentYOffset(),
// (char*) (text->text + start_pos),
// end_pos - start_pos);
long x = ts->x + ts->x_offset - documentXOffset() + getXOrigin();
long y = ts->y + ts->y_offset - documentYOffset() + getYOrigin();
bool hasBorder = (ts->border_top_width > 0 || ts->border_right_width > 0
|| ts->border_bottom_width > 0 || ts->border_left_width > 0);
QRect table_rect(x,y,ts->width,ts->height);
if (hasBorder)
{
int w = ts->border_top_width;
displayTableBorder(ts, table_rect, w );
}
}
QColorGroup QtContext::colorGroup(const QColor& col)
{
QColor topsh = col.light();
QColor botsh = col.dark();
int h,s,v;
col.hsv(&h,&s,&v);
if ( v > 200 ) {
topsh.setHsv(h,s,200);
} else if ( v < 90 ) {
topsh.setHsv(h,s,90);
botsh.setHsv(h,s,60);
}
return QColorGroup(col,
contentWidget()->colorGroup().background(),
topsh,
botsh,
col,
contentWidget()->colorGroup().text(),
col);
}
void QtContext::displayTableBorder(LO_TableStruct *ts,
QRect r, int bw)
{
if (!contentWidget())
return;
QColor col (ts->border_color.red,
ts->border_color.green,
ts->border_color.blue);
QColorGroup g = colorGroup( col );
switch (ts->border_style)
{
case BORDER_NONE:
break;
case BORDER_DOTTED:
case BORDER_DASHED:
case BORDER_SOLID:
qDrawPlainRect(painter(), r, col, bw);
break;
case BORDER_DOUBLE:
{
int ws = (bw+1)/3;
qDrawPlainRect(painter(), r, col, ws);
qDrawPlainRect(painter(), QRect(r.x()+bw-ws, r.y()+bw-ws,
r.width()- 2*(bw-ws),
r.height()- 2*(bw-ws)),
col, ws);
}
break;
case BORDER_GROOVE:
if (bw<2) bw = 2;
qDrawShadeRect(painter(), r, g, true, 1, bw-2);
break;
case BORDER_RIDGE:
if (bw<2) bw = 2;
qDrawShadeRect(painter(), r, g, false, 1, bw-2);
break;
case BORDER_INSET:
qDrawShadePanel(painter(), r, g, true, bw);
break;
case BORDER_OUTSET:
qDrawShadePanel(painter(), r, g, false, bw);
break;
default:
XP_ASSERT(0);
break;
}
}
void QtContext::displayBorder(int iLocation, int x, int y, int width,
int height, int bw, LO_Color *color, LO_LineStyle style)
{
// debug( "QTFE_DisplayBorder %d, %d, %d, %d, %d, %d, %p, %d",
// iLocation, x, y, width,
// height, bw, color, (int)style);
if (bw <= 0)
return;
QColor col (color->red,
color->green,
color->blue);
QColorGroup g = colorGroup( col );
QRect r(x - documentXOffset() + getXOrigin(),
y - documentYOffset() + getYOrigin(),
width,
height);
switch (style){
case LO_SOLID:
qDrawPlainRect(painter(), r, col, bw);
break;
case LO_BEVEL:
if (bw<2)
bw = 2;
qDrawShadeRect(painter(), r, g, false, 1, bw-2);
break;
default:
break;
}
}
/* From ./lay.c: */
void QtContext::displayCell(int loc, LO_CellStruct *cell)
{
int bw = cell->border_width;
if (bw <= 0)
return;
QRect r(cell->x + cell->x_offset - documentXOffset() + getXOrigin(),
cell->y + cell->y_offset - documentYOffset() + getYOrigin(),
cell->width,
cell->height);
qDrawShadePanel(painter(), r,
contentWidget()->colorGroup(),
true, bw);
}
/* From ./lay.c: */
void QtContext::eraseBackground(int iLocation, int32 x, int32 y,
uint32 width, uint32 height, LO_Color *bg)
{
QColor col (bg->red,
bg->green,
bg->blue);
QRect r(x - documentXOffset(),
y - documentYOffset(),
width,
height);
painter()->fillRect(r, col);
}
/* From ./lay.c: */
void QtContext::displayHR(int iLocation, LO_HorizRuleStruct *hr)
{
QPoint p1( hr->x + hr->x_offset - documentXOffset() + getXOrigin(),
hr->y + hr->y_offset - documentYOffset() + getYOrigin() );
QPoint p2 = p1 + QPoint(hr->width,0);
if ( hr->ele_attrmask & LO_ELE_SHADED ) {
qDrawShadeLine(painter(), p1, p2, contentWidget()->colorGroup(),
hr->height, 1);
} else {
QColor hrCol = painter()->pen().color(); //#####???
painter()->setPen( QPen( hrCol, hr->height) );
painter()->drawLine( p1, p2 );
}
// debug( "QTFE_DisplayHR %d, %p", iLocation, hr);
}
/* From ./lay.c: */
void QtContext::displayBullet(int iLocation, LO_BulletStruct *bul)
{
//The front end should only ever see
//bullets of type BULLET_ROUND and BULLET_SQUARE
QCOORD x = bul->x + bul->x_offset - documentXOffset() + getXOrigin();
QCOORD y = bul->y + bul->y_offset - documentYOffset() + getYOrigin();
QCOORD w = bul->bullet_size;
LO_TextAttr *text_attr = bul->text_attr;
QColor fg(text_attr->fg.red,
text_attr->fg.green,
text_attr->fg.blue);
QColor bg(text_attr->bg.red,
text_attr->bg.green,
text_attr->bg.blue);
if ( bul->bullet_type == BULLET_SQUARE ) {
painter()->fillRect( x, y, w, w, fg );
} else {
if ( bul->bullet_type != BULLET_ROUND
&& bul->bullet_type != BULLET_BASIC )
warning( "QtContext::displayBullet unknown type %d",
bul->bullet_type);
painter()->setBrush( fg );
painter()->setPen( fg );
painter()->drawEllipse( x, y, w, w);
}
}