📄 kwqpainter.cpp
字号:
void QPainter::setPaintingDisabled(bool f)
{
data->state.paintingDisabled = f;
}
bool QPainter::paintingDisabled() const
{
return data->state.paintingDisabled;
}
//CGContextRef QPainter::currentContext()
//{
// return (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
//}
void QPainter::beginTransparencyLayer(float opacity)
{
/* [NSGraphicsContext saveGraphicsState];
CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
CGContextSetAlpha(context, opacity);
CGContextBeginTransparencyLayer(context, 0);*/
}
void QPainter::endTransparencyLayer()
{
/* CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
CGContextEndTransparencyLayer(context);
[NSGraphicsContext restoreGraphicsState];*/
}
void QPainter::setShadow(int x, int y, int blur, const QColor& color)
{
// Check for an invalid color, as this means that the color was not set for the shadow
// and we should therefore just use the default shadow color.
/* CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
if (!color.isValid())
CGContextSetShadow(context, CGSizeMake(x,-y), blur); // y is flipped.
else {
NSColor* deviceColor = [color.getNSColor() colorUsingColorSpaceName: @"NSDeviceRGBColorSpace"];
float red = [deviceColor redComponent];
float green = [deviceColor greenComponent];
float blue = [deviceColor blueComponent];
float alpha = [deviceColor alphaComponent];
const float components[] = { red, green, blue, alpha };
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef color = CGColorCreate(colorSpace, components);
CGColorSpaceRelease(colorSpace);
CGContextSetShadowWithColor(context,
CGSizeMake(x,-y), // y is flipped.
blur,
color);
CGColorRelease(color);
}*/
}
void QPainter::clearShadow()
{
/* CGContextRef context = (CGContextRef)([[NSGraphicsContext currentContext] graphicsPort]);
CGContextSetShadowWithColor(context, CGSizeZero, 0, NULL);*/
}
class RectEdge
{
public:
RectEdge() : direction(0) {}
RectEdge(const QRect& r, int n) : rect(r), direction(n) {}
RectEdge(const RectEdge& o) : rect(o.rect), direction(o.direction) { }
bool operator==(const RectEdge& o) const { return rect==o.rect && direction==o.direction; }
QPoint begin() const { return begin(direction); }
QPoint end() const { return begin((direction+1)%4); }
bool contains(const QPoint& p) const {
QPoint s = begin();
QPoint e = end();
if (e.x()<s.x())
swap(s,e);
if (e.y()<s.y())
swap(s,e);
if (s.x()==e.x())
return p.x()==s.x() && s.y()<=p.y() && p.y()<=e.y();
else if (s.y()==e.y())
return p.y()==s.y() && s.x()<=p.x() && p.x()<=e.x();
else
return false;
}
QPoint begin(int edgeDirection) const {
switch (edgeDirection) {
case 0:
return rect.topLeft();
case 1:
return rect.topRight();
case 2:
return rect.bottomRight();
case 3:
default:
return rect.bottomLeft();
}
}
bool extends(const RectEdge& edge) const {
if (&edge==this || edge.direction != direction)
return false;
QPoint p = edge.end();
return contains(p) && p!=end();
}
QRect rect;
int direction;
};
struct PolyRect {
QRect rect;
bool used;
};
class RectPolygon
{
public:
void append(const QRect& r) {
if (r.width()<=0 || r.height()<=0)
return;
PolyRect pr;
pr.rect = r;
pr.used = false;
rects.append(pr);
}
bool isEmpty() const {
return rects.isEmpty();
}
QValueList<QPoint>* nextContour();
private:
bool startingEdge(RectEdge& edge);
bool findCrossingEdge(const RectEdge& current, RectEdge& edge, QPoint& crossing);
bool findExtendEdge(const RectEdge& current, RectEdge& edge);
RectEdge nextEdge(const RectEdge& current, QPoint& crossing);
void removeUsed();
private:
QValueList<PolyRect> rects;
};
bool lineCrosses(QPoint h0, QPoint h1, QPoint v0, QPoint v1, QPoint& crossing)
{
if (h0.y()!=h1.y()) {
swap(h0,v0);
swap(h1,v1);
}
if (h1.x()<h0.x())
swap(h0,h1);
if (v1.y()<v0.y())
swap(v0,v1);
if ( (h0.x()<=v0.x() && v0.x()<=h1.x()) &&
v0.y()<=h0.y() && h0.y()<=v1.y() ) {
crossing = QPoint(v0.x(),h0.y());
return true;
}
return false;
}
void RectPolygon::removeUsed()
{
// remove rectangles marked as used
// if anything remains they are part of a different polygon
bool hasUnused = true;
QValueListIterator<PolyRect> it;
for ( it = rects.begin(); it != rects.end() ; ) {
if ((*it).used) {
if (hasUnused) {
// also remove unused rectangles that touch used rectangles
QValueListIterator<PolyRect> it2;
bool unusedRemaining = false;
for ( it2 = rects.begin(); it2 != rects.end() ; ) {
if (!(*it2).used) {
if ((*it2).rect.intersects((*it).rect))
it2 = rects.remove(it2);
else {
unusedRemaining = true;
it2++;
}
} else
it2++;
}
if (!unusedRemaining)
hasUnused = false;
}
it = rects.remove(it);
}
else
it++;
}
}
bool RectPolygon::startingEdge(RectEdge& edge)
{
// find a any point which is certain to be on an outside edge of a polygon
QPoint topLeft(1000000, 1000000);
QValueListIterator<PolyRect> it;
PolyRect* res = 0;
for ( it = rects.begin(); it != rects.end() ; it++) {
QPoint p = (*it).rect.topLeft();
if (p.y() < topLeft.y()) {
res = &(*it);
topLeft = p;
} else if (p.y() == topLeft.y() && p.x()<topLeft.x()) {
res = &(*it);
topLeft = p;
}
}
if (!res)
return false;
res->used = true;
edge = RectEdge(res->rect,0);
return true;
}
bool RectPolygon::findExtendEdge(const RectEdge& current, RectEdge& extendEdge)
{
QPoint c1 = current.end();
QValueListIterator<PolyRect> it;
for ( it = rects.begin(); it != rects.end() ; it++) {
if ((*it).rect == current.rect)
continue;
RectEdge searchEdge((*it).rect, current.direction);
if ( searchEdge.contains(c1) && c1!=searchEdge.end() ){
extendEdge = searchEdge;
(*it).used = true;
return true;
}
}
return false;
}
bool RectPolygon::findCrossingEdge(const RectEdge& current, RectEdge& crossingEdge, QPoint& lastCrossing)
{
QPoint c0 = lastCrossing;
QPoint c1 = current.end();
QValueListIterator<PolyRect> it;
for ( it = rects.begin(); it != rects.end() ; it++) {
if ((*it).rect == current.rect)
continue;
RectEdge searchEdge((*it).rect, current.direction==0?3:current.direction-1);
QPoint e0 = searchEdge.begin();
QPoint e1 = searchEdge.end();
QPoint crossingPoint;
if ( lineCrosses(c0,c1,e0,e1,crossingPoint) && crossingPoint!=e1 ){
crossingEdge = searchEdge;
lastCrossing = crossingPoint;
(*it).used = true;
return true;
}
}
return false;
}
RectEdge RectPolygon::nextEdge(const RectEdge& current, QPoint& crossing)
{
RectEdge next;
bool found = findCrossingEdge(current, next, crossing);
if (!found) {
crossing = current.end();
found = findExtendEdge(current, next);
}
if (!found)
next = RectEdge(current.rect, (current.direction+1)%4);
return next;
}
QValueList<QPoint>* RectPolygon::nextContour()
{
QValueList<QPoint>* res = 0;
RectEdge edge;
if (startingEdge(edge)) {
res = new QValueList<QPoint>();
QPoint start = edge.begin();
QPoint currentCrossing = start;
res->append(start);
do {
RectEdge nextedge = nextEdge(edge, currentCrossing);
if (!nextedge.extends(edge))
res->append(currentCrossing);
edge = nextedge;
} while (edge.begin()!=start);
removeUsed();
}
return res;
}
void QPainter::initFocusRing(int width, int offset)
{
if (!_drawsFocusRing)
return;
clearFocusRing();
data->focusRingWidth = width;
data->hasFocusRingColor = false;
data->focusRingOffset = offset;
data->focusRingPath = new RectPolygon();
}
void QPainter::initFocusRing(int width, int offset, const QColor &color)
{
if (!_drawsFocusRing)
return;
initFocusRing(width, offset);
data->hasFocusRingColor = true;
data->focusRingColor = color;
}
void QPainter::addFocusRingRect(int x, int y, int width, int height)
{
if (!_drawsFocusRing)
return;
ASSERT(data->focusRingPath);
int offset = (data->focusRingWidth-1)/2 + data->focusRingOffset;
QRect rect(x-offset, y-offset, width+2*offset, height+2*offset);
data->focusRingPath->append(rect);
}
void paintEdge(CFbsBitGc& gc, QPoint p0, QPoint p1, int w, QColor col)
{
gc.SetPenStyle(CGraphicsContext::ESolidPen);
gc.SetBrushStyle(CGraphicsContext::ENullBrush);
bool down = p0.y()<p1.y();
bool up = p0.y()>p1.y();
bool right = p0.x()<p1.x();
for (int n=0; n<w; n++) {
TRgb c(max(0,col.red()-50*n/w),max(0,col.green()-50*n/w),max(0,col.blue()-50*n/w));
gc.SetPenColor(c);
TPoint tp0 = p0.Point();
TPoint tp1 = p1.Point();
if (down) {
tp0.iX = tp0.iX + w/2 - n;
tp0.iY = tp0.iY - w/2 + (n==0?1:n);
tp1.iX = tp1.iX + w/2 - n;
tp1.iY = tp1.iY + w/2 - n;
} else if (up) {
tp0.iX = tp0.iX - w/2 + n;
tp0.iY = tp0.iY + w/2 - (n==0?1:n);
tp1.iX = tp1.iX - w/2 + n;
tp1.iY = tp1.iY - w/2 + n;
} else if (right) {
tp0.iY = tp0.iY - w/2 + n;
tp0.iX = tp0.iX - w/2 + (n==0?1:n);
tp1.iY = tp1.iY - w/2 + n;
tp1.iX = tp1.iX + w/2 - n;
} else {
tp0.iY = tp0.iY + w/2 - n;
tp0.iX = tp0.iX + w/2 - (n==0?1:n);
tp1.iY = tp1.iY + w/2 - n;
tp1.iX = tp1.iX - w/2 + n;
}
gc.DrawLine(tp0,tp1);
}
}
void QPainter::drawFocusRing()
{
if (!_drawsFocusRing)
return;
ASSERT(data->focusRingPath);
if (data->state.paintingDisabled)
return;
if (!data->focusRingPath || data->focusRingPath->isEmpty()) {
ERROR("Request to draw focus ring with no control points");
return;
}
CFbsBitGc& gc = data->iGc->Gc();
QValueList<QPoint>* contour = data->focusRingPath->nextContour();
while (contour) {
QValueListIterator<QPoint> it;
QPoint p0 = contour->last();
QPoint p1;
for ( it = contour->begin(); it != contour->end() ; it++)
{
p1 = *it;
//int radius = (data->focusRingWidth-1)/2;
//Apply translation for zoomlevel when painting
paintEdge(gc,xForm(p0),xForm(p1),3,data->hasFocusRingColor ? data->focusRingColor : QColor(0xaa,0xaa,0xaa));
p0 = p1;
}
delete contour;
contour = data->focusRingPath->nextContour();
}
}
void QPainter::clearFocusRing()
{
if (data->focusRingPath) {
delete data->focusRingPath;
data->focusRingPath = 0;
}
}
TPoint QPainter::xForm ( const TPoint & p ) const {
TInt z(data->iGc->View().ScalingFactor());
return TPoint(p.iX*z/100,p.iY*z/100);
};
TRect QPainter::xForm ( const TRect & r ) const {
return TRect(xForm(r.iTl),xForm(r.iBr));
};
TSize QPainter::xForm ( const TSize & s ) const {
TInt z(data->iGc->View().ScalingFactor());
return TSize(s.iWidth*z/100,s.iHeight*z/100);
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -