developing new draw

git-svn-id: svn://ultimatepp.org/upp/trunk@1372 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2009-07-06 20:31:00 +00:00
parent 7ae5221acb
commit 04a06f8ce7
74 changed files with 3278 additions and 3431 deletions

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP

View file

@ -1,7 +1,7 @@
#ifndef CTRLCORE_H
#define CTRLCORE_H
#include <Draw/Draw.h>
#include "SystemDraw.h"
NAMESPACE_UPP

View file

@ -7,6 +7,22 @@ uses
library(WIN32 !MSC8ARM) "advapi32 comdlg32 comctl32";
file
SystemDraw readonly separator,
DrawWin32.h,
DrawWin32.cpp,
DrawOpWin32.cpp,
DrawTextWin32.cpp,
ImageWin32.cpp,
MetaFile.cpp,
DrawX11.h,
DrawX11.cpp,
DrawOpX11.cpp,
DrawTextX11.cpp,
ImageX11.cpp,
SystemDraw.h,
BackDraw.cpp,
SystemDraw.cpp,
DrawUtil.cpp,
Core readonly separator,
CtrlCore.h,
Win32Keys.i,

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP
@ -10,7 +10,7 @@ NAMESPACE_UPP
void SystemDraw::BeginOp()
{
LTIMING("Begin");
DrawLock __;
GuiLock __;
Cloff& w = cloff.Add();
w.org = actual_offset;
w.hrgn = CreateRectRgn(0, 0, 0, 0);
@ -25,7 +25,7 @@ void SystemDraw::BeginOp()
void SystemDraw::OffsetOp(Point p)
{
DrawLock __;
GuiLock __;
Begin();
actual_offset += p;
LTIMING("Offset");
@ -34,7 +34,7 @@ void SystemDraw::OffsetOp(Point p)
bool SystemDraw::ClipOp(const Rect& r)
{
DrawLock __;
GuiLock __;
Begin();
LTIMING("Clip");
return IntersectClip(r);
@ -42,7 +42,7 @@ bool SystemDraw::ClipOp(const Rect& r)
bool SystemDraw::ClipoffOp(const Rect& r)
{
DrawLock __;
GuiLock __;
Begin();
LTIMING("Clipoff");
LLOG("ClipoffOp " << r << ", GetClip() = " << GetClip() << ", actual_offset = " << actual_offset);
@ -55,7 +55,7 @@ bool SystemDraw::ClipoffOp(const Rect& r)
void SystemDraw::EndOp()
{
DrawLock __;
GuiLock __;
LTIMING("End");
ASSERT(cloff.GetCount());
Cloff& w = cloff.Top();
@ -69,7 +69,7 @@ void SystemDraw::EndOp()
bool SystemDraw::ExcludeClipOp(const Rect& r)
{
DrawLock __;
GuiLock __;
#ifdef PLATFORM_WINCE
int q = ExcludeClipRect(handle, r.left, r.top, r.right, r.bottom);
#else
@ -85,7 +85,7 @@ bool SystemDraw::ExcludeClipOp(const Rect& r)
bool SystemDraw::IntersectClipOp(const Rect& r)
{
DrawLock __;
GuiLock __;
#ifdef PLATFORM_WINCE
int q = IntersectClipRect(handle, r.left, r.top, r.right, r.bottom);
#else
@ -101,7 +101,7 @@ bool SystemDraw::IntersectClipOp(const Rect& r)
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
DrawLock __;
GuiLock __;
LTIMING("IsPainting");
LLOG("SystemDraw::IsPaintingOp r: " << r);
return ::RectVisible(handle, r);
@ -109,7 +109,7 @@ bool SystemDraw::IsPaintingOp(const Rect& r) const
void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
DrawLock __;
GuiLock __;
LTIMING("DrawRect");
LLOG("DrawRect " << RectC(x, y, cx, cy) << ": " << color);
if(IsNull(color)) return;
@ -124,7 +124,7 @@ void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
DrawLock __;
GuiLock __;
if(IsNull(width) || IsNull(color)) return;
SetDrawPen(width, color);
::MoveToEx(handle, x1, y1, NULL);
@ -137,7 +137,7 @@ void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor)
{
DrawLock __;
GuiLock __;
ASSERT(count_count > 0 && vertex_count > 0);
if(vertex_count < 2 || IsNull(color))
return;
@ -161,7 +161,7 @@ static void DrawPolyPolyPolygonRaw(
const int *subpolygon_counts, int subpolygon_count_count,
const int *disjunct_polygon_counts, int disjunct_polygon_count_count)
{
DrawLock __;
GuiLock __;
for(int i = 0; i < disjunct_polygon_count_count; i++, disjunct_polygon_counts++)
{
int poly = *disjunct_polygon_counts;
@ -192,7 +192,7 @@ void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
Color color, int width, Color outline, uint64 pattern, Color doxor)
{
DrawLock __;
GuiLock __;
if(vertex_count == 0)
return;
bool is_xor = !IsNull(doxor);
@ -262,7 +262,7 @@ void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
DrawLock __;
GuiLock __;
SetDrawPen(width, color);
::Arc(GetHandle(), rc.left, rc.top, rc.right, rc.bottom, start.x, start.y, end.x, end.y);
}
@ -271,7 +271,7 @@ void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Co
void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int width, Color pencolor)
{
DrawLock __;
GuiLock __;
SetColor(color);
SetDrawPen(width, pencolor);
::Ellipse(GetHandle(), r.left, r.top, r.right, r.bottom);

View file

@ -1,303 +1,303 @@
#include "Draw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
#define LLOG(x) // LOG(x)
#define LTIMING(x) // TIMING(x)
void SystemDraw::BeginOp()
{
Cloff f = cloff.Top();
Vector<Rect> newclip;
newclip <<= clip.Top();
f.clipi = clip.GetCount();
clip.Add() = newclip;
cloff.Add(f);
}
void SystemDraw::OffsetOp(Point p)
{
Cloff f = cloff.Top();
f.offseti = offset.GetCount();
actual_offset += p;
offset.Add(actual_offset);
cloff.Add(f);
}
bool SystemDraw::ClipOp(const Rect& r)
{
LLOG("SystemDraw::ClipOp(" << r << ")");
Cloff f = cloff.Top();
bool ch = false;
Vector<Rect> newclip = Intersect(clip.Top(), r + actual_offset, ch);
if(ch) {
f.clipi = clip.GetCount();
clip.Add() = newclip;
}
cloff.Add(f);
if(ch)
SetClip();
return clip.Top().GetCount();
}
bool SystemDraw::ClipoffOp(const Rect& r)
{
LLOG("SystemDraw::ClipOffOp(" << r << ")");
Cloff f = cloff.Top();
bool ch = false;
Vector<Rect> newclip = Intersect(clip.Top(), r + actual_offset, ch);
if(ch) {
f.clipi = clip.GetCount();
clip.Add() = newclip;
}
f.offseti = offset.GetCount();
actual_offset += r.TopLeft();
offset.Add(actual_offset);
cloff.Add(f);
if(ch)
SetClip();
return clip.Top().GetCount();
}
void SystemDraw::EndOp()
{
ASSERT(cloff.GetCount());
cloff.Drop();
actual_offset = offset[cloff.Top().offseti];
clip.SetCount(cloff.Top().clipi + 1);
SetClip();
}
bool SystemDraw::ExcludeClipOp(const Rect& r)
{
LLOG("SystemDraw::ExcludeClipOp(" << r << ")");
CloneClip();
Vector<Rect>& cl = clip.Top();
bool ch = false;
Vector<Rect> ncl = Subtract(cl, r + actual_offset, ch);
if(ch) {
cl = ncl;
SetClip();
}
return clip.Top().GetCount();
}
bool SystemDraw::IntersectClipOp(const Rect& r)
{
CloneClip();
Vector<Rect>& cl = clip.Top();
bool ch = false;
Vector<Rect> ncl = Intersect(cl, r + actual_offset, ch);
if(ch) {
cl = ncl;
SetClip();
}
return clip.Top().GetCount();
}
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
LTIMING("IsPaintingOp");
Rect rr = r + actual_offset;
const Vector<Rect>& cl = clip[cloff.Top().clipi];
for(int i = 0; i < cl.GetCount(); i++)
if(cl[i].Intersects(rr))
return true;
return false;
}
void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
LTIMING("DrawRect");
DrawLock __;
LLOG("DrawRect " << RectC(x, y, cx, cy) << ": " << color);
if(IsNull(color)) return;
if(cx <= 0 || cy <= 0) return;
if(color == InvertColor) {
XSetFunction(Xdisplay, gc, GXinvert);
XFillRectangle(Xdisplay, dw, gc, x + actual_offset.x, y + actual_offset.y, cx, cy);
XSetFunction(Xdisplay, gc, GXcopy);
}
else {
SetForeground(color);
XFillRectangle(Xdisplay, dw, gc, x + actual_offset.x, y + actual_offset.y, cx, cy);
}
}
void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
DrawLock __;
if(IsNull(width) || IsNull(color)) return;
SetLineStyle(width);
SetForeground(color);
XDrawLine(Xdisplay, dw, gc,
x1 + actual_offset.x, y1 + actual_offset.y,
x2 + actual_offset.x, y2 + actual_offset.y);
}
void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor)
{
DrawLock __;
ASSERT(count_count > 0 && vertex_count > 0);
if(vertex_count < 2 || IsNull(color))
return;
XGCValues gcv_old, gcv_new;
XGetGCValues(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
gcv_new.function = IsNull(doxor) ? X11_ROP2_COPY : X11_ROP2_XOR;
gcv_new.foreground = GetXPixel(color) ^ (IsNull(doxor) ? 0 : GetXPixel(doxor));
gcv_new.line_width = width;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_new);
enum { REQUEST_LENGTH = 256 }; // X server XDrawLines request length (heuristic)
Point offset = GetOffset();
if(vertex_count == 2)
XDrawLine(Xdisplay, GetDrawable(), GetGC(),
vertices[0].x + offset.x, vertices[0].y + offset.y,
vertices[1].x + offset.x, vertices[1].y + offset.y);
else if(count_count == 1 || vertex_count > count_count * (REQUEST_LENGTH + 2)) {
for(; --count_count >= 0; counts++)
{
Buffer<XPoint> part(*counts);
for(XPoint *vo = part, *ve = vo + *counts; vo < ve; vo++, vertices++)
{
vo -> x = (short)(vertices -> x + offset.x);
vo -> y = (short)(vertices -> y + offset.y);
}
XDrawLines(Xdisplay, GetDrawable(), GetGC(), part, *counts, CoordModeOrigin);
}
}
else {
int segment_count = vertex_count - count_count;
Buffer<XSegment> segments(segment_count);
XSegment *so = segments;
while(--count_count >= 0)
{
const Point *end = vertices + *counts++;
so -> x1 = (short)(vertices -> x + offset.x);
so -> y1 = (short)(vertices -> y + offset.y);
vertices++;
so -> x2 = (short)(vertices -> x + offset.x);
so -> y2 = (short)(vertices -> y + offset.y);
so++;
while(++vertices < end) {
so -> x1 = so[-1].x2;
so -> y1 = so[-1].y2;
so -> x2 = (short)(vertices -> x + offset.x);
so -> y2 = (short)(vertices -> y + offset.y);
so++;
}
}
ASSERT(so == segments + segment_count);
XDrawSegments(Xdisplay, GetDrawable(), GetGC(), segments, segment_count);
}
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
}
static void DrawPolyPolyPolygonRaw(SystemDraw& draw, const Point *vertices, int vertex_count,
const int *subpolygon_counts, int subpolygon_count_count, const int *, int)
{
DrawLock __;
Point offset = draw.GetOffset();
const Point *in = vertices;
for(int i = 0; i < subpolygon_count_count; i++) {
int n = subpolygon_counts[i];
Buffer<XPoint> out_points(n);
XPoint *t = out_points;
XPoint *e = t + n;
while(t < e) {
t->x = (short)(in->x + offset.x);
t->y = (short)(in->y + offset.y);
t++;
in++;
}
XFillPolygon(Xdisplay, draw.GetDrawable(), draw.GetGC(), out_points, n, Nonconvex, CoordModeOrigin);
}
}
void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int subpolygon_count_count,
const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
Color color, int width, Color outline, uint64 pattern, Color doxor)
{
DrawLock __;
if(vertex_count == 0)
return;
bool is_xor = !IsNull(doxor);
XGCValues gcv_old, gcv_new;
XGetGCValues(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
unsigned xor_pixel = (is_xor ? GetXPixel(doxor) : 0);
if(!IsNull(color))
{
gcv_new.foreground = GetXPixel(color) ^ xor_pixel;
gcv_new.function = is_xor ? X11_ROP2_XOR : X11_ROP2_COPY;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_new);
DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
subpolygon_counts, subpolygon_count_count,
disjunct_polygon_counts, disjunct_polygon_count_count);
}
if(!IsNull(outline))
{
gcv_new.foreground = GetXPixel(outline) ^ xor_pixel;
gcv_new.line_width = width;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth, &gcv_new);
Point offset = GetOffset();
for(const int *sp = subpolygon_counts, *se = sp + subpolygon_count_count; sp < se; sp++)
{
Buffer<XPoint> segment(*sp + 1);
XPoint *out = segment;
for(const Point *end = vertices + *sp; vertices < end; vertices++, out++)
{
out -> x = (short)(vertices -> x + offset.x);
out -> y = (short)(vertices -> y + offset.y);
}
*out = segment[0];
XDrawLines(Xdisplay, GetDrawable(), GetGC(), segment, *sp + 1, CoordModeOrigin);
}
}
XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
}
void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
DrawLock __;
SetLineStyle(pen);
if(!IsNull(color)) {
SetForeground(color);
XFillArc(Xdisplay, dw, gc, r.left + actual_offset.x, r.top + actual_offset.y,
r.Width() - 1, r.Height() - 1, 0, 360 * 64);
}
if(!IsNull(pencolor) && !IsNull(pen)) {
SetForeground(pencolor);
XDrawArc(Xdisplay, dw, gc, r.left + actual_offset.x, r.top + actual_offset.y,
r.Width() - 1, r.Height() - 1, 0, 360 * 64);
}
}
void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
DrawLock __;
XGCValues gcv, gcv_old;
XGetGCValues(Xdisplay, GetGC(), GCForeground, &gcv_old);
Point offset = GetOffset();
gcv.foreground = GetXPixel(color);
XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv);
Point centre = rc.CenterPoint();
int angle1 = fround(360 * 64 / (2 * M_PI) *
atan2(centre.y - start.y, start.x - centre.x));
int angle2 = fround(360 * 64 / (2 * M_PI) *
atan2(centre.y - end.y, end.x - centre.x));
if(angle2 <= angle1)
angle2 += 360 * 64;
angle2 -= angle1;
XDrawArc(Xdisplay, GetDrawable(), GetGC(), rc.left + offset.x, rc.top + offset.y,
rc.Width(), rc.Height(), angle1, angle2);
XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_old);
}
#endif
END_UPP_NAMESPACE
#include "SystemDraw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
#define LLOG(x) // LOG(x)
#define LTIMING(x) // TIMING(x)
void SystemDraw::BeginOp()
{
Cloff f = cloff.Top();
Vector<Rect> newclip;
newclip <<= clip.Top();
f.clipi = clip.GetCount();
clip.Add() = newclip;
cloff.Add(f);
}
void SystemDraw::OffsetOp(Point p)
{
Cloff f = cloff.Top();
f.offseti = offset.GetCount();
actual_offset += p;
offset.Add(actual_offset);
cloff.Add(f);
}
bool SystemDraw::ClipOp(const Rect& r)
{
LLOG("SystemDraw::ClipOp(" << r << ")");
Cloff f = cloff.Top();
bool ch = false;
Vector<Rect> newclip = Intersect(clip.Top(), r + actual_offset, ch);
if(ch) {
f.clipi = clip.GetCount();
clip.Add() = newclip;
}
cloff.Add(f);
if(ch)
SetClip();
return clip.Top().GetCount();
}
bool SystemDraw::ClipoffOp(const Rect& r)
{
LLOG("SystemDraw::ClipOffOp(" << r << ")");
Cloff f = cloff.Top();
bool ch = false;
Vector<Rect> newclip = Intersect(clip.Top(), r + actual_offset, ch);
if(ch) {
f.clipi = clip.GetCount();
clip.Add() = newclip;
}
f.offseti = offset.GetCount();
actual_offset += r.TopLeft();
offset.Add(actual_offset);
cloff.Add(f);
if(ch)
SetClip();
return clip.Top().GetCount();
}
void SystemDraw::EndOp()
{
ASSERT(cloff.GetCount());
cloff.Drop();
actual_offset = offset[cloff.Top().offseti];
clip.SetCount(cloff.Top().clipi + 1);
SetClip();
}
bool SystemDraw::ExcludeClipOp(const Rect& r)
{
LLOG("SystemDraw::ExcludeClipOp(" << r << ")");
CloneClip();
Vector<Rect>& cl = clip.Top();
bool ch = false;
Vector<Rect> ncl = Subtract(cl, r + actual_offset, ch);
if(ch) {
cl = ncl;
SetClip();
}
return clip.Top().GetCount();
}
bool SystemDraw::IntersectClipOp(const Rect& r)
{
CloneClip();
Vector<Rect>& cl = clip.Top();
bool ch = false;
Vector<Rect> ncl = Intersect(cl, r + actual_offset, ch);
if(ch) {
cl = ncl;
SetClip();
}
return clip.Top().GetCount();
}
bool SystemDraw::IsPaintingOp(const Rect& r) const
{
LTIMING("IsPaintingOp");
Rect rr = r + actual_offset;
const Vector<Rect>& cl = clip[cloff.Top().clipi];
for(int i = 0; i < cl.GetCount(); i++)
if(cl[i].Intersects(rr))
return true;
return false;
}
void SystemDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
LTIMING("DrawRect");
GuiLock __;
LLOG("DrawRect " << RectC(x, y, cx, cy) << ": " << color);
if(IsNull(color)) return;
if(cx <= 0 || cy <= 0) return;
if(color == InvertColor) {
XSetFunction(Xdisplay, gc, GXinvert);
XFillRectangle(Xdisplay, dw, gc, x + actual_offset.x, y + actual_offset.y, cx, cy);
XSetFunction(Xdisplay, gc, GXcopy);
}
else {
SetForeground(color);
XFillRectangle(Xdisplay, dw, gc, x + actual_offset.x, y + actual_offset.y, cx, cy);
}
}
void SystemDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
GuiLock __;
if(IsNull(width) || IsNull(color)) return;
SetLineStyle(width);
SetForeground(color);
XDrawLine(Xdisplay, dw, gc,
x1 + actual_offset.x, y1 + actual_offset.y,
x2 + actual_offset.x, y2 + actual_offset.y);
}
void SystemDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor)
{
GuiLock __;
ASSERT(count_count > 0 && vertex_count > 0);
if(vertex_count < 2 || IsNull(color))
return;
XGCValues gcv_old, gcv_new;
XGetGCValues(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
gcv_new.function = IsNull(doxor) ? X11_ROP2_COPY : X11_ROP2_XOR;
gcv_new.foreground = GetXPixel(color) ^ (IsNull(doxor) ? 0 : GetXPixel(doxor));
gcv_new.line_width = width;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_new);
enum { REQUEST_LENGTH = 256 }; // X server XDrawLines request length (heuristic)
Point offset = GetOffset();
if(vertex_count == 2)
XDrawLine(Xdisplay, GetDrawable(), GetGC(),
vertices[0].x + offset.x, vertices[0].y + offset.y,
vertices[1].x + offset.x, vertices[1].y + offset.y);
else if(count_count == 1 || vertex_count > count_count * (REQUEST_LENGTH + 2)) {
for(; --count_count >= 0; counts++)
{
Buffer<XPoint> part(*counts);
for(XPoint *vo = part, *ve = vo + *counts; vo < ve; vo++, vertices++)
{
vo -> x = (short)(vertices -> x + offset.x);
vo -> y = (short)(vertices -> y + offset.y);
}
XDrawLines(Xdisplay, GetDrawable(), GetGC(), part, *counts, CoordModeOrigin);
}
}
else {
int segment_count = vertex_count - count_count;
Buffer<XSegment> segments(segment_count);
XSegment *so = segments;
while(--count_count >= 0)
{
const Point *end = vertices + *counts++;
so -> x1 = (short)(vertices -> x + offset.x);
so -> y1 = (short)(vertices -> y + offset.y);
vertices++;
so -> x2 = (short)(vertices -> x + offset.x);
so -> y2 = (short)(vertices -> y + offset.y);
so++;
while(++vertices < end) {
so -> x1 = so[-1].x2;
so -> y1 = so[-1].y2;
so -> x2 = (short)(vertices -> x + offset.x);
so -> y2 = (short)(vertices -> y + offset.y);
so++;
}
}
ASSERT(so == segments + segment_count);
XDrawSegments(Xdisplay, GetDrawable(), GetGC(), segments, segment_count);
}
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth | GCFunction, &gcv_old);
}
static void DrawPolyPolyPolygonRaw(SystemDraw& draw, const Point *vertices, int vertex_count,
const int *subpolygon_counts, int subpolygon_count_count, const int *, int)
{
GuiLock __;
Point offset = draw.GetOffset();
const Point *in = vertices;
for(int i = 0; i < subpolygon_count_count; i++) {
int n = subpolygon_counts[i];
Buffer<XPoint> out_points(n);
XPoint *t = out_points;
XPoint *e = t + n;
while(t < e) {
t->x = (short)(in->x + offset.x);
t->y = (short)(in->y + offset.y);
t++;
in++;
}
XFillPolygon(Xdisplay, draw.GetDrawable(), draw.GetGC(), out_points, n, Nonconvex, CoordModeOrigin);
}
}
void SystemDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int subpolygon_count_count,
const int *disjunct_polygon_counts, int disjunct_polygon_count_count,
Color color, int width, Color outline, uint64 pattern, Color doxor)
{
GuiLock __;
if(vertex_count == 0)
return;
bool is_xor = !IsNull(doxor);
XGCValues gcv_old, gcv_new;
XGetGCValues(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
unsigned xor_pixel = (is_xor ? GetXPixel(doxor) : 0);
if(!IsNull(color))
{
gcv_new.foreground = GetXPixel(color) ^ xor_pixel;
gcv_new.function = is_xor ? X11_ROP2_XOR : X11_ROP2_COPY;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction, &gcv_new);
DrawPolyPolyPolygonRaw(*this, vertices, vertex_count,
subpolygon_counts, subpolygon_count_count,
disjunct_polygon_counts, disjunct_polygon_count_count);
}
if(!IsNull(outline))
{
gcv_new.foreground = GetXPixel(outline) ^ xor_pixel;
gcv_new.line_width = width;
XChangeGC(Xdisplay, GetGC(), GCForeground | GCLineWidth, &gcv_new);
Point offset = GetOffset();
for(const int *sp = subpolygon_counts, *se = sp + subpolygon_count_count; sp < se; sp++)
{
Buffer<XPoint> segment(*sp + 1);
XPoint *out = segment;
for(const Point *end = vertices + *sp; vertices < end; vertices++, out++)
{
out -> x = (short)(vertices -> x + offset.x);
out -> y = (short)(vertices -> y + offset.y);
}
*out = segment[0];
XDrawLines(Xdisplay, GetDrawable(), GetGC(), segment, *sp + 1, CoordModeOrigin);
}
}
XChangeGC(Xdisplay, GetGC(), GCForeground | GCFunction | GCLineWidth, &gcv_old);
}
void SystemDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
GuiLock __;
SetLineStyle(pen);
if(!IsNull(color)) {
SetForeground(color);
XFillArc(Xdisplay, dw, gc, r.left + actual_offset.x, r.top + actual_offset.y,
r.Width() - 1, r.Height() - 1, 0, 360 * 64);
}
if(!IsNull(pencolor) && !IsNull(pen)) {
SetForeground(pencolor);
XDrawArc(Xdisplay, dw, gc, r.left + actual_offset.x, r.top + actual_offset.y,
r.Width() - 1, r.Height() - 1, 0, 360 * 64);
}
}
void SystemDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
{
GuiLock __;
XGCValues gcv, gcv_old;
XGetGCValues(Xdisplay, GetGC(), GCForeground, &gcv_old);
Point offset = GetOffset();
gcv.foreground = GetXPixel(color);
XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv);
Point centre = rc.CenterPoint();
int angle1 = fround(360 * 64 / (2 * M_PI) *
atan2(centre.y - start.y, start.x - centre.x));
int angle2 = fround(360 * 64 / (2 * M_PI) *
atan2(centre.y - end.y, end.x - centre.x));
if(angle2 <= angle1)
angle2 += 360 * 64;
angle2 -= angle1;
XDrawArc(Xdisplay, GetDrawable(), GetGC(), rc.left + offset.x, rc.top + offset.y,
rc.Width(), rc.Height(), angle1, angle2);
XChangeGC(Xdisplay, GetGC(), GCForeground, &gcv_old);
}
#endif
END_UPP_NAMESPACE

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP
@ -22,7 +22,7 @@ void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font fon
n -= 30000;
text += 30000;
}
DrawLock __;
GuiLock __;
COLORREF cr = GetColor(ink);
if(cr != lastTextColor) {
LLOG("Setting text color: " << ink);

View file

@ -1,207 +1,207 @@
#include "Draw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
#define LTIMING(x)
#define LLOG(x)
int gtk_antialias = -1;
int gtk_hinting = -1;
String gtk_hintstyle;
String gtk_rgba;
XftFont *CreateXftFont(Font font, int angle)
{
LTIMING("CreateXftFont");
XftFont *xftfont;
double sina, cosa;
Std(font);
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int i = font.GetFace();
if(i < 0 || i >= Font::GetFaceCount())
i = 0;
String face = font.GetFaceName();
FcPattern *p = FcPatternCreate();
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
FcPatternAddBool(p, FC_MINSPACE, 1);
if(angle) {
FcMatrix mx;
Draw::SinCos(angle, sina, cosa);
mx.xx = cosa;
mx.xy = -sina;
mx.yx = sina;
mx.yy = cosa;
FcPatternAddMatrix(p, FC_MATRIX, &mx);
}
FcResult result;
FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result);
if(font.IsNonAntiAliased() || gtk_antialias >= 0) {
FcPatternDel(m, FC_ANTIALIAS);
FcPatternAddBool(m, FC_ANTIALIAS,
font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse);
}
if(gtk_hinting >= 0) {
FcPatternDel(m, FC_HINTING);
FcPatternAddBool(m, FC_HINTING, gtk_hinting);
}
const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" };
for(int i = 0; i < 4; i++)
if(gtk_hintstyle == hs[i]) {
FcPatternDel(m, FC_HINT_STYLE);
FcPatternAddInteger(m, FC_HINT_STYLE, i);
}
const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" };
for(int i = 0; i < __countof(rgba); i++)
if(gtk_rgba == rgba[i]) {
FcPatternDel(m, FC_RGBA);
FcPatternAddInteger(m, FC_RGBA, i);
}
xftfont = XftFontOpenPattern(Xdisplay, m);
FcPatternDestroy(p);
return xftfont;
}
#define FONTCACHE 37
struct XftEntry {
Font font;
int angle;
XftFont *xftfont;
};
XftFont *GetXftFont(Font fnt, int angle)
{
static XftEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
XftEntry be;
be = cache[0];
for(int i = 0; i < FONTCACHE; i++) {
XftEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.xftfont;
}
be = e;
}
if(be.xftfont) {
XftFontClose(Xdisplay, be.xftfont);
}
be.font = fnt;
be.angle = angle;
be.xftfont = CreateXftFont(fnt, angle);
cache[0] = be;
return be.xftfont;
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx) {
DrawLock __;
LTIMING("DrawText");
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
//TODO - X11 seems to crash when displaying too long strings (?)
int ox = x + actual_offset.x;
int oy = y + actual_offset.y;
SetForeground(ink);
XftColor c;
c.color.red = ink.GetR() << 8;
c.color.green = ink.GetG() << 8;
c.color.blue = ink.GetB() << 8;
c.color.alpha = 0xffff;
c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB());
XftFont *xftfont = GetXftFont(font, angle);
Size offset = Point(0, 0);
double sina, cosa;
int ascent = font.Info().GetAscent();
if(angle) {
SinCos(angle, sina, cosa);
offset.cx = fround(ascent * sina);
offset.cy = fround(ascent * cosa);
}
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int underline_thickness = max(hg / 20, 1);
int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0));
if(angle) {
int xpos = 0;
for(int i = 0; i < n; i++) {
wchar h = text[i];
XftDrawString16(xftdraw, &c, xftfont,
int(ox + xpos * cosa + offset.cx),
int(oy - xpos * sina + offset.cy),
(FcChar16 *)&h, 1);
xpos += dx ? dx[i] : lastFont[text[i]];
}
if(font.IsUnderline() || font.IsStrikeout()) {
x += offset.cx;
y += offset.cy;
if(font.IsUnderline())
DrawLine(
int(x + underline_position * sina),
int(y + underline_position * cosa),
int(x + xpos * cosa + underline_position * sina),
int(y - xpos * sina + underline_position * cosa),
underline_thickness,
ink
);
if(font.IsStrikeout()) {
int p = 2 * ascent / 3;
DrawLine(
int(x + p * sina),
int(y + p * cosa),
int(x + xpos * cosa + p * sina),
int(y - xpos * sina + p * cosa),
underline_thickness,
ink
);
}
}
}
else {
if(dx) {
int xpos = ox;
Buffer<XftCharSpec> ch(n);
for(int i = 0; i < n; i++) {
ch[i].ucs4 = text[i];
ch[i].x = xpos;
ch[i].y = oy + ascent;
xpos += dx[i];
}
XftDrawCharSpec(xftdraw, &c, xftfont, ch, n);
}
else
XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent,
(FcChar16 *)text, n);
LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue
<< ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel));
if(font.IsUnderline() || font.IsStrikeout()) {
int cx;
if(dx && n > 0) {
cx = 0;
Sum(cx, dx, dx + n - 1);
cx += lastFont[text[n - 1]];
}
else
cx = GetTextSize(text, font, n).cx;
if(font.IsUnderline())
DrawRect(x, y + ascent + underline_position, cx, underline_thickness, ink);
if(font.IsStrikeout())
DrawRect(x, y + 2 * ascent / 3, cx, underline_thickness, ink);
}
}
}
#endif
END_UPP_NAMESPACE
#include "SystemDraw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
#define LTIMING(x)
#define LLOG(x)
int gtk_antialias = -1;
int gtk_hinting = -1;
String gtk_hintstyle;
String gtk_rgba;
XftFont *CreateXftFont(Font font, int angle)
{
LTIMING("CreateXftFont");
XftFont *xftfont;
double sina, cosa;
Std(font);
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int i = font.GetFace();
if(i < 0 || i >= Font::GetFaceCount())
i = 0;
String face = font.GetFaceName();
FcPattern *p = FcPatternCreate();
FcPatternAddString(p, FC_FAMILY, (FcChar8*)~face);
FcPatternAddInteger(p, FC_SLANT, font.IsItalic() ? 110 : 0);
FcPatternAddInteger(p, FC_PIXEL_SIZE, hg);
FcPatternAddInteger(p, FC_WEIGHT, font.IsBold() ? 200 : 100);
FcPatternAddBool(p, FC_MINSPACE, 1);
if(angle) {
FcMatrix mx;
Draw::SinCos(angle, sina, cosa);
mx.xx = cosa;
mx.xy = -sina;
mx.yx = sina;
mx.yy = cosa;
FcPatternAddMatrix(p, FC_MATRIX, &mx);
}
FcResult result;
FcPattern *m = XftFontMatch(Xdisplay, Xscreenno, p, &result);
if(font.IsNonAntiAliased() || gtk_antialias >= 0) {
FcPatternDel(m, FC_ANTIALIAS);
FcPatternAddBool(m, FC_ANTIALIAS,
font.IsNonAntiAliased() ? FcFalse : gtk_antialias ? FcTrue : FcFalse);
}
if(gtk_hinting >= 0) {
FcPatternDel(m, FC_HINTING);
FcPatternAddBool(m, FC_HINTING, gtk_hinting);
}
const char *hs[] = { "hintnone", "hintslight", "hintmedium", "hintfull" };
for(int i = 0; i < 4; i++)
if(gtk_hintstyle == hs[i]) {
FcPatternDel(m, FC_HINT_STYLE);
FcPatternAddInteger(m, FC_HINT_STYLE, i);
}
const char *rgba[] = { "_", "rgb", "bgr", "vrgb", "vbgr" };
for(int i = 0; i < __countof(rgba); i++)
if(gtk_rgba == rgba[i]) {
FcPatternDel(m, FC_RGBA);
FcPatternAddInteger(m, FC_RGBA, i);
}
xftfont = XftFontOpenPattern(Xdisplay, m);
FcPatternDestroy(p);
return xftfont;
}
#define FONTCACHE 37
struct XftEntry {
Font font;
int angle;
XftFont *xftfont;
};
XftFont *GetXftFont(Font fnt, int angle)
{
static XftEntry cache[FONTCACHE];
ONCELOCK {
for(int i = 0; i < FONTCACHE; i++)
cache[i].font.Height(-30000);
}
XftEntry be;
be = cache[0];
for(int i = 0; i < FONTCACHE; i++) {
XftEntry e = cache[i];
if(i)
cache[i] = be;
if(e.font == fnt && e.angle == angle) {
if(i)
cache[0] = e;
return e.xftfont;
}
be = e;
}
if(be.xftfont) {
XftFontClose(Xdisplay, be.xftfont);
}
be.font = fnt;
be.angle = angle;
be.xftfont = CreateXftFont(fnt, angle);
cache[0] = be;
return be.xftfont;
}
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx) {
GuiLock __;
LTIMING("DrawText");
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
//TODO - X11 seems to crash when displaying too long strings (?)
int ox = x + actual_offset.x;
int oy = y + actual_offset.y;
SetForeground(ink);
XftColor c;
c.color.red = ink.GetR() << 8;
c.color.green = ink.GetG() << 8;
c.color.blue = ink.GetB() << 8;
c.color.alpha = 0xffff;
c.pixel = GetXPixel(ink.GetR(), ink.GetG(), ink.GetB());
XftFont *xftfont = GetXftFont(font, angle);
Size offset = Point(0, 0);
double sina, cosa;
int ascent = font.Info().GetAscent();
if(angle) {
SinCos(angle, sina, cosa);
offset.cx = fround(ascent * sina);
offset.cy = fround(ascent * cosa);
}
int hg = abs(font.GetHeight());
if(hg == 0) hg = 10;
int underline_thickness = max(hg / 20, 1);
int underline_position = max(hg / 15, int(font.Info().GetDescent() > 0));
if(angle) {
int xpos = 0;
for(int i = 0; i < n; i++) {
wchar h = text[i];
XftDrawString16(xftdraw, &c, xftfont,
int(ox + xpos * cosa + offset.cx),
int(oy - xpos * sina + offset.cy),
(FcChar16 *)&h, 1);
xpos += dx ? dx[i] : lastFont[text[i]];
}
if(font.IsUnderline() || font.IsStrikeout()) {
x += offset.cx;
y += offset.cy;
if(font.IsUnderline())
DrawLine(
int(x + underline_position * sina),
int(y + underline_position * cosa),
int(x + xpos * cosa + underline_position * sina),
int(y - xpos * sina + underline_position * cosa),
underline_thickness,
ink
);
if(font.IsStrikeout()) {
int p = 2 * ascent / 3;
DrawLine(
int(x + p * sina),
int(y + p * cosa),
int(x + xpos * cosa + p * sina),
int(y - xpos * sina + p * cosa),
underline_thickness,
ink
);
}
}
}
else {
if(dx) {
int xpos = ox;
Buffer<XftCharSpec> ch(n);
for(int i = 0; i < n; i++) {
ch[i].ucs4 = text[i];
ch[i].x = xpos;
ch[i].y = oy + ascent;
xpos += dx[i];
}
XftDrawCharSpec(xftdraw, &c, xftfont, ch, n);
}
else
XftDrawString16(xftdraw, &c, xftfont, ox, oy + ascent,
(FcChar16 *)text, n);
LLOG("XftColor: r=" << c.color.red << ", g=" << c.color.green << ", b=" << c.color.blue
<< ", alpha=" << c.color.alpha << ", pixel=" << FormatIntHex(c.pixel));
if(font.IsUnderline() || font.IsStrikeout()) {
int cx;
if(dx && n > 0) {
cx = 0;
Sum(cx, dx, dx + n - 1);
cx += lastFont[text[n - 1]];
}
else
cx = GetTextSize(text, font, n).cx;
if(font.IsUnderline())
DrawRect(x, y + ascent + underline_position, cx, underline_thickness, ink);
if(font.IsStrikeout())
DrawRect(x, y + 2 * ascent / 3, cx, underline_thickness, ink);
}
}
}
#endif
END_UPP_NAMESPACE

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP
@ -11,7 +11,7 @@ static COLORREF sLightGray;
dword SystemDraw::GetInfo() const
{
return native || !(style & DOTS) ? style|NATIVE : style;
return DATABANDS|(native || !(style & DOTS) ? style|NATIVE : style);
}
Size SystemDraw::GetPageSize() const
@ -110,7 +110,7 @@ void SystemDraw::InitColors()
void SystemDraw::SetColor(Color color)
{
DrawLock __;
GuiLock __;
LLOG("SetColor " << color);
if(color != lastColor) {
LLOG("Setting, lastColor:" << FormatIntHex(lastColor.GetRaw())
@ -133,7 +133,7 @@ void SystemDraw::SetColor(Color color)
}
void SystemDraw::SetDrawPen(int width, Color color) {
DrawLock __;
GuiLock __;
if(IsNull(width))
width = PEN_NULL;
if(width != lastPen || color != lastPenColor) {
@ -155,7 +155,7 @@ void SystemDraw::SetDrawPen(int width, Color color) {
}
void SystemDraw::SetOrg() {
DrawLock __;
GuiLock __;
#ifdef PLATFORM_WINCE
::SetViewportOrgEx(handle, actual_offset.x, actual_offset.y, 0);
#else
@ -167,26 +167,26 @@ void SystemDraw::SetOrg() {
#ifndef PLATFORM_WINCE
Point SystemDraw::LPtoDP(Point p) const {
DrawLock __;
GuiLock __;
::LPtoDP(handle, p, 1);
return p;
}
Point SystemDraw::DPtoLP(Point p) const {
DrawLock __;
GuiLock __;
::DPtoLP(handle, p, 1);
return p;
}
Rect SystemDraw::LPtoDP(const Rect& r) const {
DrawLock __;
GuiLock __;
Rect w = r;
::LPtoDP(handle, reinterpret_cast<POINT *>(&w), 2);
return w;
}
Rect SystemDraw::DPtoLP(const Rect& r) const {
DrawLock __;
GuiLock __;
Rect w = r;
::LPtoDP(handle, reinterpret_cast<POINT *>(&w), 2);
return w;
@ -194,7 +194,7 @@ Rect SystemDraw::DPtoLP(const Rect& r) const {
#endif
Size SystemDraw::GetSizeCaps(int i, int j) const {
DrawLock __;
GuiLock __;
return Size(GetDeviceCaps(handle, i), GetDeviceCaps(handle, j));
}
@ -232,7 +232,7 @@ int SystemDraw::GetCloffLevel() const
}
void SystemDraw::LoadCaps() {
DrawLock __;
GuiLock __;
color16 = false;
palette = (GetDeviceCaps(handle, RASTERCAPS) & RC_PALETTE);
if(palette)
@ -243,7 +243,7 @@ void SystemDraw::LoadCaps() {
}
void SystemDraw::Cinit() {
DrawLock __;
GuiLock __;
lastColor = Color::FromCR(COLORREF(-5));
lastPenColor = Color::FromCR(COLORREF(-5));
lastTextColor = COLORREF(-1);
@ -253,7 +253,7 @@ void SystemDraw::Cinit() {
}
void SystemDraw::Init() {
DrawLock __;
GuiLock __;
Cinit();
SetBkMode(handle, TRANSPARENT);
::SetTextAlign(handle, TA_BASELINE);
@ -266,12 +266,12 @@ void SystemDraw::Init() {
}
void SystemDraw::Reset() {
DrawLock __;
GuiLock __;
style = GUI;
}
SystemDraw::SystemDraw() {
DrawLock __;
GuiLock __;
native = 0;
InitColors();
actual_offset = Point(0, 0);
@ -280,7 +280,7 @@ SystemDraw::SystemDraw() {
}
SystemDraw::SystemDraw(HDC hdc) {
DrawLock __;
GuiLock __;
native = 0;
InitColors();
Reset();
@ -288,7 +288,7 @@ SystemDraw::SystemDraw(HDC hdc) {
}
void SystemDraw::Unselect0() {
DrawLock __;
GuiLock __;
if(orgPen) SelectObject(handle, orgPen);
if(orgBrush) SelectObject(handle, orgBrush);
if(actPen) DeleteObject(actPen);
@ -297,33 +297,33 @@ void SystemDraw::Unselect0() {
}
void SystemDraw::Unselect() {
DrawLock __;
GuiLock __;
while(cloff.GetCount())
End();
Unselect0();
}
SystemDraw::~SystemDraw() {
DrawLock __;
GuiLock __;
if(handle)
Unselect();
}
HDC SystemDraw::BeginGdi() {
DrawLock __;
GuiLock __;
Begin();
return handle;
}
void SystemDraw::EndGdi() {
DrawLock __;
GuiLock __;
Unselect0();
End();
}
void BackDraw::Create(SystemDraw& w, int cx, int cy) {
ASSERT(w.GetHandle());
DrawLock __;
GuiLock __;
Destroy();
size.cx = cx;
size.cy = cy;
@ -342,7 +342,7 @@ void BackDraw::Create(SystemDraw& w, int cx, int cy) {
}
void BackDraw::Put(SystemDraw& w, int x, int y) {
DrawLock __;
GuiLock __;
ASSERT(handle);
LTIMING("BackDraw::Put");
#ifdef PLATFORM_WINCE
@ -354,7 +354,7 @@ void BackDraw::Put(SystemDraw& w, int x, int y) {
}
void BackDraw::Destroy() {
DrawLock __;
GuiLock __;
if(handle) {
Unselect();
::SelectObject(handle, hbmpold);
@ -365,7 +365,7 @@ void BackDraw::Destroy() {
}
ScreenDraw::ScreenDraw(bool ic) {
DrawLock __;
GuiLock __;
#ifdef PLATFORM_WINCE
Attach(CreateDC(NULL, NULL, NULL, NULL));
#else
@ -378,7 +378,7 @@ ScreenDraw::ScreenDraw(bool ic) {
}
ScreenDraw::~ScreenDraw() {
DrawLock __;
GuiLock __;
Unselect();
DeleteDC(handle);
}
@ -387,7 +387,7 @@ ScreenDraw::~ScreenDraw() {
void PrintDraw::InitPrinter()
{
DrawLock __;
GuiLock __;
Init();
style = PRINTER|DOTS;
DotsMode();
@ -400,7 +400,7 @@ void PrintDraw::InitPrinter()
void PrintDraw::StartPage()
{
DrawLock __;
GuiLock __;
if(aborted) return;
Unselect();
if(::StartPage(handle) <= 0)
@ -411,7 +411,7 @@ void PrintDraw::StartPage()
void PrintDraw::EndPage()
{
DrawLock __;
GuiLock __;
if(aborted) return;
Unselect();
if(::EndPage(handle) <= 0)
@ -421,7 +421,7 @@ void PrintDraw::EndPage()
PrintDraw::PrintDraw(HDC hdc, const char *docname)
: SystemDraw(hdc)
{
DrawLock __;
GuiLock __;
DOCINFO di;
memset(&di, 0, sizeof(di));
di.cbSize = sizeof(di);
@ -434,7 +434,7 @@ PrintDraw::PrintDraw(HDC hdc, const char *docname)
}
PrintDraw::~PrintDraw() {
DrawLock __;
GuiLock __;
if(aborted)
::AbortDoc(handle);
else
@ -445,16 +445,6 @@ PrintDraw::~PrintDraw() {
#endif
bool ScreenInPaletteMode()
{
return ScreenInfo().PaletteMode();
}
Size GetScreenSize()
{
return ScreenInfo().GetPageSize();
}
#endif
END_UPP_NAMESPACE

View file

@ -1,5 +1,7 @@
#ifdef PLATFORM_WIN32
NAMESPACE_UPP
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
@ -253,4 +255,9 @@ inline void DrawEllipse(HDC hdc, const Rect& rc) { Ellipse(hdc,
inline void DrawRect(HDC hdc, const Rect& rc) { Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom); }
HDC ScreenHDC();
HPALETTE GetQlibPalette();
END_UPP_NAMESPACE
#endif

View file

@ -1,452 +1,452 @@
#include "Draw.h"
#ifdef PLATFORM_X11
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#ifndef flagNOGTK
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkprivate.h>
#endif
#undef Picture
#undef Time
#undef Font
#undef Display
NAMESPACE_UPP
#define LLOG(x) //LOG(x)
#define LTIMING(x) //TIMING(x)
XDisplay *Xdisplay;
int Xscreenno;
Visual *Xvisual;
Window Xroot;
Screen *Xscreen;
Colormap Xcolormap;
int Xheight;
int Xwidth;
int XheightMM;
int XwidthMM;
int Xdepth;
dword Xblack;
dword Xwhite;
int Xconnection;
byte *Xmapcolor;
byte *Xunmapcolor;
bool Xpalette;
dword (*Xgetpixel)(int r, int g, int b);
EXITBLOCK
{
if(Xdisplay) {
// No CloseDisplay for now...
XCloseDisplay(Xdisplay);
LLOG("Xdisplay closed");
Xdisplay = NULL;
}
if(Xmapcolor)
delete[] Xmapcolor;
if(Xunmapcolor)
delete[] Xunmapcolor;
}
void XError()
{
Panic("X11 error !");
}
void XError(const char *s)
{
Panic(String("X11 error:") + s + " !");
}
static int sAcs;
bool sAllocColor(int xr, int xg, int xb)
{
XColor ce;
ce.red = xr;
ce.green = xg;
ce.blue = xb;
ce.flags = DoRed | DoGreen | DoBlue;
if(!XAllocColor(Xdisplay, Xcolormap, &ce)) return false;
sAcs++;
return sAcs < 257;
}
void sAllocColors()
{
int r, g, b;
for(r = 0; r < 2; r++)
for(g = 0; g < 2; g++)
for(b = 0; b < 2; b++)
if(!sAllocColor(65535 * r, 65535 * g, 65535 * b)) return;
for(r = 0; r < 3; r++)
for(g = 0; g < 3; g++)
for(b = 0; b < 3; b++)
if((r == 1 || g == 1 || b == 1) &&
!sAllocColor((65535 * r) / 2, (65535 * g) / 2, (65535 * b) / 2)) return;
for(r = 5; r >= 0; r--)
for(g = 5; g >= 0; g--)
for(b = 5; b >= 0; b--)
if((r != 0 && r != 5 || g != 0 && g != 5 || b != 0 && b != 5) &&
!sAllocColor((65535 * r) / 5, (65535 * g) / 5, (65535 * b) / 5)) return;
for(r = 1; r <= 11; r += 2)
if(!sAllocColor((65535 * r) / 11, (65535 * r) / 11, (65535 * r) / 11)) return;
for(int r = 255; r >= 0; r--)
if(!sAllocColor(r << 8, r << 8, r << 8)) return;
}
dword GetPseudoColorPixel(int r, int g, int b)
{
return Xmapcolor[r * 11 / 255 * (24 * 12) + g * 23 / 255 * 12 + b * 11 / 255];
}
static
struct Xshift {
dword mask;
int bits;
int shift;
dword Do(int c) { return (c >> bits << shift) & mask; }
}
Xred, Xgreen, Xblue;
Xshift CalcXShift(dword mask)
{
Xshift f;
f.mask = mask;
f.shift = 0;
f.bits = 0;
while((mask & 1) == 0) {
mask >>= 1;
f.shift++;
}
while((mask & 1) == 1) {
mask >>= 1;
f.bits++;
}
f.bits = 8 - f.bits;
if(f.bits < 0) {
f.shift += f.bits;
f.bits = 0;
}
LLOG("xshift(" << FormatIntHex(mask) << "): mask = "
<< FormatIntHex(f.mask) << ", bits = " << f.bits << ", shift = " << f.shift);
return f;
}
dword GetTrueColorPixel(int r, int g, int b)
{
return Xred.Do(r) | Xgreen.Do(g) | Xblue.Do(b);
}
inline int ssq(int x) { return x * x; }
void InitX11Draw(XDisplay *display)
{
Xdisplay = display;
if(!Xdisplay) {
puts(NFormat("No X11 display, errno = %d, %s", errno, strerror(errno)));
fflush(stdout);
XError();
}
int Xscreenno = DefaultScreen(Xdisplay);
Xroot = RootWindow(Xdisplay, Xscreenno);
Xscreen = ScreenOfDisplay(Xdisplay, Xscreenno);
Xcolormap = DefaultColormap(Xdisplay, Xscreenno);
// Xcolormap = (Colormap)GDK().gdk_x11_colormap_get_xcolormap(GDK().gdk_rgb_get_colormap());
Xheight = DisplayHeight(Xdisplay, Xscreenno);
Xwidth = DisplayWidth(Xdisplay, Xscreenno);
XheightMM = DisplayHeightMM(Xdisplay, Xscreenno);
XwidthMM = DisplayWidthMM(Xdisplay, Xscreenno);
LLOG("Xwidth = " << Xwidth << ", XwidthMM = " << XwidthMM);
LLOG("Xheight = " << Xheight << ", XheightMM = " << XheightMM);
Xdepth = DefaultDepth(Xdisplay, Xscreenno);
Xblack = BlackPixel(Xdisplay, 0);
Xwhite = WhitePixel(Xdisplay, 0);
Xconnection = XConnectionNumber(Xdisplay);
Xvisual = DefaultVisual(Xdisplay, Xscreenno);
Visual *v = Xvisual;
if(v->c_class == TrueColor) {
Xred = CalcXShift(v->red_mask);
Xgreen = CalcXShift(v->green_mask);
Xblue = CalcXShift(v->blue_mask);
Xgetpixel = GetTrueColorPixel;
}
else {
Xpalette = true;
sAllocColors();
int colorcount = max(1 << Xdepth, 256);
Buffer<XColor> cs(colorcount);
int i;
for(i = 0; i < colorcount; i++)
cs[i].pixel = i;
XQueryColors(Xdisplay, Xcolormap, cs, colorcount);
Xunmapcolor = new byte[3 * colorcount];
for(i = 0; i < colorcount; i++)
{
Xunmapcolor[3 * i + 0] = cs[i].blue;
Xunmapcolor[3 * i + 1] = cs[i].green;
Xunmapcolor[3 * i + 2] = cs[i].red;
}
byte *cm = Xmapcolor = new byte[12 * 24 * 12];
for(int r = 0; r < 12; r++)
for(int g = 0; g < 24; g++)
for(int b = 0; b < 12; b++) {
int mind = INT_MAX;
int mini;
for(int i = 0; i < colorcount; i++) {
int d = ssq(r * 255 / 11 - (cs[i].red >> 8)) +
ssq(g * 255 / 23 - (cs[i].green >> 8)) +
ssq(b * 255 / 11 - (cs[i].blue >> 8));
if(d < mind) {
mini = i;
mind = d;
}
}
*cm++ = mini;
}
Xgetpixel = GetPseudoColorPixel;
}
// XFree(v);
Font::SetStdFont(ScreenSans(12));
}
void InitX11Draw(const char *dispname)
{
#ifdef flagNOGTK
if(!dispname || !*dispname) {
int f = Environment().Find("DISPLAY");
dispname = (f >= 0 ? ~Environment()[f] : ":0.0");
}
InitX11Draw(XOpenDisplay(dispname));
#else
MemoryIgnoreLeaksBlock __;
const Vector<String>& cmd = CommandLine();
char **argv = (char**) MemoryAllocPermanent(sizeof(char *) * cmd.GetCount());
for(int i = 0; i < cmd.GetCount(); i++)
argv[i] = PermanentCopy(cmd[i]);
int argc = cmd.GetCount();
gtk_init (&argc, &argv);
GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GdkDisplay *d = gtk_widget_get_display(w);
gdk_x11_display_get_xdisplay(d);
InitX11Draw(gdk_x11_display_get_xdisplay(d));
gtk_widget_destroy(w);
#endif
}
void SetClip(GC gc, XftDraw *xftdraw, const Vector<Rect>& cl)
{
DrawLock __;
LTIMING("SetClip");
Buffer<XRectangle> xr(cl.GetCount());
LLOG("SetClip");
for(int i = 0; i < cl.GetCount(); i++) {
XRectangle& r = xr[i];
const Rect& cr = cl[i];
LLOG("[" << i << "] = " << cr);
r.x = cr.left;
r.y = cr.top;
r.width = cr.Width();
r.height = cr.Height();
}
XSetClipRectangles(Xdisplay, gc, 0, 0, xr, cl.GetCount(), Unsorted);
LLOG("XftDrawSetClipRectangles, # = " << cl.GetCount() << ", xftdraw = " << FormatIntHex(xftdraw));
XftDrawSetClipRectangles(xftdraw, 0, 0, xr, cl.GetCount());
LLOG("//XftDrawSetClipRectangles");
}
void SystemDraw::CloneClip()
{
if(cloff.GetCount() > 1 && cloff.Top().clipi == cloff[cloff.GetCount() - 2].clipi) {
cloff.Top().clipi = clip.GetCount();
Vector<Rect>& c = clip.Add();
c <<= clip[clip.GetCount() - 2];
}
}
void SystemDraw::SetForeground(Color color)
{
DrawLock __;
LTIMING("SetForeground");
int p = GetXPixel(color.GetR(), color.GetG(), color.GetB());
if(p == foreground) return;
LTIMING("XSetForeground");
LLOG("XSetForeground " << color);
foreground = p;
XSetForeground(Xdisplay, gc, foreground);
}
void SystemDraw::SetClip() {
DrawLock __;
if(dw == Xroot) return;
LTIMING("SetClip");
UPP::SetClip(gc, xftdraw, clip.Top());
}
void SystemDraw::SetLineStyle(int width)
{
DrawLock __;
if(width == linewidth) return;
linewidth = width;
if(IsNull(width))
width = 1;
if(width < PEN_SOLID) {
static const char dash[] = { 18, 6 };
static const char dot[] = { 3, 3 };
static const char dashdot[] = { 9, 6, 3, 6 };
static const char dashdotdot[] = { 9, 3, 3, 3, 3, 3 };
static struct {
const char *dash;
int len;
} ds[] = {
{ dash, __countof(dash) },
{ dot, __countof(dot) },
{ dashdot, __countof(dashdot) },
{ dashdotdot, __countof(dashdotdot) }
};
int i = -(width - PEN_DASH);
ASSERT(i >= 0 && i < 4);
XSetDashes(Xdisplay, gc, 0, ds[i].dash, ds[i].len);
}
XSetLineAttributes(Xdisplay, gc, max(width, 1),
width < PEN_SOLID ? LineOnOffDash : LineSolid, CapRound, JoinRound);
}
void SystemDraw::Init()
{
DrawLock __;
pageSize = Size(Xwidth, Xheight);
cloff.Clear();
clip.Clear();
foreground = linewidth = Null;
}
void SystemDraw::Init(const Vector<Rect>& _clip, Point _offset)
{
DrawLock __;
Init();
clip.Add() <<= _clip;
offset.Add(_offset);
actual_offset = _offset;
Cloff& f = cloff.Add();
f.offseti = 0;
f.clipi = 0;
SetClip();
}
dword SystemDraw::GetInfo() const
{
return 0;
}
Size SystemDraw::GetPageSize() const
{
return pageSize;
}
SystemDraw::SystemDraw()
{
DrawLock __;
dw = None;
gc = None;
actual_offset = Point(0, 0);
Init();
}
Size SystemDraw::GetNativeDpi() const
{
return Size(96, 96);
}
void SystemDraw::BeginNative() {}
void SystemDraw::EndNative() {}
int SystemDraw::GetCloffLevel() const
{
return cloff.GetCount();
}
Rect SystemDraw::GetClip() const
{
LLOG("Draw::GetClipOp; #clip = " << clip.GetCount() << ", #cloff = " << cloff.GetCount()
<< ", clipi = " << cloff.Top().clipi);
const Vector<Rect>& cl = clip[cloff.Top().clipi];
Rect box(0, 0, 0, 0);
if(!cl.GetCount()) return box;
box = cl[0];
LLOG("cl[0] = " << box);
for(int i = 1; i < cl.GetCount(); i++) {
LLOG("cl[" << i << "] = " << cl[i]);
box |= cl[i];
}
LLOG("out box = " << box << ", actual offset = " << actual_offset);
return box - actual_offset;
}
SystemDraw::SystemDraw(Drawable _dw, GC _gc, XftDraw *_xftdraw, const Vector<Rect>& _clip)
{
LLOG("SystemDraw");
dw = _dw;
gc = _gc;
xftdraw = _xftdraw;
Init(_clip);
}
void BackDraw::Create(SystemDraw& w, int cx, int cy)
{
DrawLock __;
LLOG("Creating BackDraw " << cx << "x" << cy);
Destroy();
size.cx = cx;
size.cy = cy;
dw = XCreatePixmap(Xdisplay, w.GetDrawable(), max(cx, 1), max(cy, 1), Xdepth);
gc = XCreateGC(Xdisplay, dw, 0, 0);
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw,
DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
Vector<Rect> clip;
clip.Add(RectC(0, 0, cx, cy));
Init(clip, Point(0, 0));
}
void BackDraw::Put(SystemDraw& w, int x, int y)
{
DrawLock __;
LLOG("Putting BackDraw");
ASSERT(dw != None);
XCopyArea(Xdisplay, dw, w.GetDrawable(), w.GetGC(), 0, 0, size.cx, size.cy,
x + w.GetOffset().x, y + w.GetOffset().y);
}
void BackDraw::Destroy()
{
DrawLock __;
if(dw != None) {
XftDrawDestroy(xftdraw);
XFreePixmap(Xdisplay, dw);
XFreeGC(Xdisplay, gc);
}
}
bool ScreenInPaletteMode()
{
return Xpalette;
}
Size GetScreenSize()
{
return Size(Xwidth, Xheight);
}
END_UPP_NAMESPACE
#endif
#include "SystemDraw.h"
#ifdef PLATFORM_X11
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#ifndef flagNOGTK
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkprivate.h>
#endif
#undef Picture
#undef Time
#undef Font
#undef Display
NAMESPACE_UPP
#define LLOG(x) //LOG(x)
#define LTIMING(x) //TIMING(x)
XDisplay *Xdisplay;
int Xscreenno;
Visual *Xvisual;
Window Xroot;
Screen *Xscreen;
Colormap Xcolormap;
int Xheight;
int Xwidth;
int XheightMM;
int XwidthMM;
int Xdepth;
dword Xblack;
dword Xwhite;
int Xconnection;
byte *Xmapcolor;
byte *Xunmapcolor;
bool Xpalette;
dword (*Xgetpixel)(int r, int g, int b);
EXITBLOCK
{
if(Xdisplay) {
// No CloseDisplay for now...
XCloseDisplay(Xdisplay);
LLOG("Xdisplay closed");
Xdisplay = NULL;
}
if(Xmapcolor)
delete[] Xmapcolor;
if(Xunmapcolor)
delete[] Xunmapcolor;
}
void XError()
{
Panic("X11 error !");
}
void XError(const char *s)
{
Panic(String("X11 error:") + s + " !");
}
static int sAcs;
bool sAllocColor(int xr, int xg, int xb)
{
XColor ce;
ce.red = xr;
ce.green = xg;
ce.blue = xb;
ce.flags = DoRed | DoGreen | DoBlue;
if(!XAllocColor(Xdisplay, Xcolormap, &ce)) return false;
sAcs++;
return sAcs < 257;
}
void sAllocColors()
{
int r, g, b;
for(r = 0; r < 2; r++)
for(g = 0; g < 2; g++)
for(b = 0; b < 2; b++)
if(!sAllocColor(65535 * r, 65535 * g, 65535 * b)) return;
for(r = 0; r < 3; r++)
for(g = 0; g < 3; g++)
for(b = 0; b < 3; b++)
if((r == 1 || g == 1 || b == 1) &&
!sAllocColor((65535 * r) / 2, (65535 * g) / 2, (65535 * b) / 2)) return;
for(r = 5; r >= 0; r--)
for(g = 5; g >= 0; g--)
for(b = 5; b >= 0; b--)
if((r != 0 && r != 5 || g != 0 && g != 5 || b != 0 && b != 5) &&
!sAllocColor((65535 * r) / 5, (65535 * g) / 5, (65535 * b) / 5)) return;
for(r = 1; r <= 11; r += 2)
if(!sAllocColor((65535 * r) / 11, (65535 * r) / 11, (65535 * r) / 11)) return;
for(int r = 255; r >= 0; r--)
if(!sAllocColor(r << 8, r << 8, r << 8)) return;
}
dword GetPseudoColorPixel(int r, int g, int b)
{
return Xmapcolor[r * 11 / 255 * (24 * 12) + g * 23 / 255 * 12 + b * 11 / 255];
}
static
struct Xshift {
dword mask;
int bits;
int shift;
dword Do(int c) { return (c >> bits << shift) & mask; }
}
Xred, Xgreen, Xblue;
Xshift CalcXShift(dword mask)
{
Xshift f;
f.mask = mask;
f.shift = 0;
f.bits = 0;
while((mask & 1) == 0) {
mask >>= 1;
f.shift++;
}
while((mask & 1) == 1) {
mask >>= 1;
f.bits++;
}
f.bits = 8 - f.bits;
if(f.bits < 0) {
f.shift += f.bits;
f.bits = 0;
}
LLOG("xshift(" << FormatIntHex(mask) << "): mask = "
<< FormatIntHex(f.mask) << ", bits = " << f.bits << ", shift = " << f.shift);
return f;
}
dword GetTrueColorPixel(int r, int g, int b)
{
return Xred.Do(r) | Xgreen.Do(g) | Xblue.Do(b);
}
inline int ssq(int x) { return x * x; }
void InitX11Draw(XDisplay *display)
{
Xdisplay = display;
if(!Xdisplay) {
puts(NFormat("No X11 display, errno = %d, %s", errno, strerror(errno)));
fflush(stdout);
XError();
}
int Xscreenno = DefaultScreen(Xdisplay);
Xroot = RootWindow(Xdisplay, Xscreenno);
Xscreen = ScreenOfDisplay(Xdisplay, Xscreenno);
Xcolormap = DefaultColormap(Xdisplay, Xscreenno);
// Xcolormap = (Colormap)GDK().gdk_x11_colormap_get_xcolormap(GDK().gdk_rgb_get_colormap());
Xheight = DisplayHeight(Xdisplay, Xscreenno);
Xwidth = DisplayWidth(Xdisplay, Xscreenno);
XheightMM = DisplayHeightMM(Xdisplay, Xscreenno);
XwidthMM = DisplayWidthMM(Xdisplay, Xscreenno);
LLOG("Xwidth = " << Xwidth << ", XwidthMM = " << XwidthMM);
LLOG("Xheight = " << Xheight << ", XheightMM = " << XheightMM);
Xdepth = DefaultDepth(Xdisplay, Xscreenno);
Xblack = BlackPixel(Xdisplay, 0);
Xwhite = WhitePixel(Xdisplay, 0);
Xconnection = XConnectionNumber(Xdisplay);
Xvisual = DefaultVisual(Xdisplay, Xscreenno);
Visual *v = Xvisual;
if(v->c_class == TrueColor) {
Xred = CalcXShift(v->red_mask);
Xgreen = CalcXShift(v->green_mask);
Xblue = CalcXShift(v->blue_mask);
Xgetpixel = GetTrueColorPixel;
}
else {
Xpalette = true;
sAllocColors();
int colorcount = max(1 << Xdepth, 256);
Buffer<XColor> cs(colorcount);
int i;
for(i = 0; i < colorcount; i++)
cs[i].pixel = i;
XQueryColors(Xdisplay, Xcolormap, cs, colorcount);
Xunmapcolor = new byte[3 * colorcount];
for(i = 0; i < colorcount; i++)
{
Xunmapcolor[3 * i + 0] = cs[i].blue;
Xunmapcolor[3 * i + 1] = cs[i].green;
Xunmapcolor[3 * i + 2] = cs[i].red;
}
byte *cm = Xmapcolor = new byte[12 * 24 * 12];
for(int r = 0; r < 12; r++)
for(int g = 0; g < 24; g++)
for(int b = 0; b < 12; b++) {
int mind = INT_MAX;
int mini;
for(int i = 0; i < colorcount; i++) {
int d = ssq(r * 255 / 11 - (cs[i].red >> 8)) +
ssq(g * 255 / 23 - (cs[i].green >> 8)) +
ssq(b * 255 / 11 - (cs[i].blue >> 8));
if(d < mind) {
mini = i;
mind = d;
}
}
*cm++ = mini;
}
Xgetpixel = GetPseudoColorPixel;
}
// XFree(v);
Font::SetStdFont(ScreenSans(12));
}
void InitX11Draw(const char *dispname)
{
#ifdef flagNOGTK
if(!dispname || !*dispname) {
int f = Environment().Find("DISPLAY");
dispname = (f >= 0 ? ~Environment()[f] : ":0.0");
}
InitX11Draw(XOpenDisplay(dispname));
#else
MemoryIgnoreLeaksBlock __;
const Vector<String>& cmd = CommandLine();
char **argv = (char**) MemoryAllocPermanent(sizeof(char *) * cmd.GetCount());
for(int i = 0; i < cmd.GetCount(); i++)
argv[i] = PermanentCopy(cmd[i]);
int argc = cmd.GetCount();
gtk_init (&argc, &argv);
GtkWidget *w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GdkDisplay *d = gtk_widget_get_display(w);
gdk_x11_display_get_xdisplay(d);
InitX11Draw(gdk_x11_display_get_xdisplay(d));
gtk_widget_destroy(w);
#endif
}
void SetClip(GC gc, XftDraw *xftdraw, const Vector<Rect>& cl)
{
GuiLock __;
LTIMING("SetClip");
Buffer<XRectangle> xr(cl.GetCount());
LLOG("SetClip");
for(int i = 0; i < cl.GetCount(); i++) {
XRectangle& r = xr[i];
const Rect& cr = cl[i];
LLOG("[" << i << "] = " << cr);
r.x = cr.left;
r.y = cr.top;
r.width = cr.Width();
r.height = cr.Height();
}
XSetClipRectangles(Xdisplay, gc, 0, 0, xr, cl.GetCount(), Unsorted);
LLOG("XftDrawSetClipRectangles, # = " << cl.GetCount() << ", xftdraw = " << FormatIntHex(xftdraw));
XftDrawSetClipRectangles(xftdraw, 0, 0, xr, cl.GetCount());
LLOG("//XftDrawSetClipRectangles");
}
void SystemDraw::CloneClip()
{
if(cloff.GetCount() > 1 && cloff.Top().clipi == cloff[cloff.GetCount() - 2].clipi) {
cloff.Top().clipi = clip.GetCount();
Vector<Rect>& c = clip.Add();
c <<= clip[clip.GetCount() - 2];
}
}
void SystemDraw::SetForeground(Color color)
{
GuiLock __;
LTIMING("SetForeground");
int p = GetXPixel(color.GetR(), color.GetG(), color.GetB());
if(p == foreground) return;
LTIMING("XSetForeground");
LLOG("XSetForeground " << color);
foreground = p;
XSetForeground(Xdisplay, gc, foreground);
}
void SystemDraw::SetClip() {
GuiLock __;
if(dw == Xroot) return;
LTIMING("SetClip");
UPP::SetClip(gc, xftdraw, clip.Top());
}
void SystemDraw::SetLineStyle(int width)
{
GuiLock __;
if(width == linewidth) return;
linewidth = width;
if(IsNull(width))
width = 1;
if(width < PEN_SOLID) {
static const char dash[] = { 18, 6 };
static const char dot[] = { 3, 3 };
static const char dashdot[] = { 9, 6, 3, 6 };
static const char dashdotdot[] = { 9, 3, 3, 3, 3, 3 };
static struct {
const char *dash;
int len;
} ds[] = {
{ dash, __countof(dash) },
{ dot, __countof(dot) },
{ dashdot, __countof(dashdot) },
{ dashdotdot, __countof(dashdotdot) }
};
int i = -(width - PEN_DASH);
ASSERT(i >= 0 && i < 4);
XSetDashes(Xdisplay, gc, 0, ds[i].dash, ds[i].len);
}
XSetLineAttributes(Xdisplay, gc, max(width, 1),
width < PEN_SOLID ? LineOnOffDash : LineSolid, CapRound, JoinRound);
}
void SystemDraw::Init()
{
GuiLock __;
pageSize = Size(Xwidth, Xheight);
cloff.Clear();
clip.Clear();
foreground = linewidth = Null;
}
void SystemDraw::Init(const Vector<Rect>& _clip, Point _offset)
{
GuiLock __;
Init();
clip.Add() <<= _clip;
offset.Add(_offset);
actual_offset = _offset;
Cloff& f = cloff.Add();
f.offseti = 0;
f.clipi = 0;
SetClip();
}
dword SystemDraw::GetInfo() const
{
return 0;
}
Size SystemDraw::GetPageSize() const
{
return pageSize;
}
SystemDraw::SystemDraw()
{
GuiLock __;
dw = None;
gc = None;
actual_offset = Point(0, 0);
Init();
}
Size SystemDraw::GetNativeDpi() const
{
return Size(96, 96);
}
void SystemDraw::BeginNative() {}
void SystemDraw::EndNative() {}
int SystemDraw::GetCloffLevel() const
{
return cloff.GetCount();
}
Rect SystemDraw::GetClip() const
{
LLOG("Draw::GetClipOp; #clip = " << clip.GetCount() << ", #cloff = " << cloff.GetCount()
<< ", clipi = " << cloff.Top().clipi);
const Vector<Rect>& cl = clip[cloff.Top().clipi];
Rect box(0, 0, 0, 0);
if(!cl.GetCount()) return box;
box = cl[0];
LLOG("cl[0] = " << box);
for(int i = 1; i < cl.GetCount(); i++) {
LLOG("cl[" << i << "] = " << cl[i]);
box |= cl[i];
}
LLOG("out box = " << box << ", actual offset = " << actual_offset);
return box - actual_offset;
}
SystemDraw::SystemDraw(Drawable _dw, GC _gc, XftDraw *_xftdraw, const Vector<Rect>& _clip)
{
LLOG("SystemDraw");
dw = _dw;
gc = _gc;
xftdraw = _xftdraw;
Init(_clip);
}
void BackDraw::Create(SystemDraw& w, int cx, int cy)
{
GuiLock __;
LLOG("Creating BackDraw " << cx << "x" << cy);
Destroy();
size.cx = cx;
size.cy = cy;
dw = XCreatePixmap(Xdisplay, w.GetDrawable(), max(cx, 1), max(cy, 1), Xdepth);
gc = XCreateGC(Xdisplay, dw, 0, 0);
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw,
DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
Vector<Rect> clip;
clip.Add(RectC(0, 0, cx, cy));
Init(clip, Point(0, 0));
}
void BackDraw::Put(SystemDraw& w, int x, int y)
{
GuiLock __;
LLOG("Putting BackDraw");
ASSERT(dw != None);
XCopyArea(Xdisplay, dw, w.GetDrawable(), w.GetGC(), 0, 0, size.cx, size.cy,
x + w.GetOffset().x, y + w.GetOffset().y);
}
void BackDraw::Destroy()
{
GuiLock __;
if(dw != None) {
XftDrawDestroy(xftdraw);
XFreePixmap(Xdisplay, dw);
XFreeGC(Xdisplay, gc);
}
}
bool ScreenInPaletteMode()
{
return Xpalette;
}
Size GetScreenSize()
{
return Size(Xwidth, Xheight);
}
END_UPP_NAMESPACE
#endif

View file

@ -1,107 +1,179 @@
#ifdef PLATFORM_X11
void SetClip(GC gc, XftDraw *xftdraw, const Vector<Rect>& cl);
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc,
Color color, int width, Color outline,
uint64 pattern, Color doxor);
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx);
virtual Size GetNativeDpi() const;
virtual void BeginNative();
virtual void EndNative();
virtual int GetCloffLevel() const;
private:
Size pageSize;
SystemDraw();
friend class ImageDraw;
friend class FontInfo;
friend class Font;
friend class ViewDraw;
friend void StaticExitDraw_();
friend Font StdFont();
FontInfo lastFont;
Point actual_offset;
Point actual_offset_bak;
struct Cloff : Moveable<Cloff> {
Point org;
int clipi;
int offseti;
Rect drawingclip;
};
Array<Cloff> cloff;
Rect drawingclip;
Vector< Vector<Rect> > clip;
Vector<Point> offset;
Drawable dw;
GC gc;
XftDraw *xftdraw;
int foreground;
int linewidth;
void Init();
void Init(const Vector<Rect>& clip, Point offset = Point(0, 0));
void CloneClip();
friend class BackDraw;
friend class ScreenDraw;
public:
static void Flush() { XSync(Xdisplay, false); }
Point GetOffset() const { return actual_offset; }
static XftFont *CreateXftFont(Font f, int angle);
XftDraw *GetXftDraw() const { return xftdraw; }
Rect GetClip() const;
void SetForeground(Color color);
void SetLineStyle(int width);
void SetClip();
Drawable GetDrawable() const { return dw; }
GC GetGC() const { return gc; }
const Vector<Rect>& GetClipList() const { return clip.Top(); }
SystemDraw(Drawable dw, GC gc, XftDraw *xftdraw, const Vector<Rect>& clip);
};
#endif
#ifdef PLATFORM_X11
#define Time XTime
#define Font XFont
#define Display XDisplay
#define Picture XPicture
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/extensions/Xrender.h>
#undef Picture
#undef Time
#undef Font
#undef Display
#undef True
#undef False
#define XFalse 0
#define XTrue 1
NAMESPACE_UPP
extern XDisplay *Xdisplay;
extern Visual *Xvisual;
extern int Xscreenno;
extern Window Xroot;
extern Screen *Xscreen;
extern Colormap Xcolormap;
extern int Xheight;
extern int Xwidth;
extern int XheightMM;
extern int XwidthMM;
extern int Xdepth;
extern dword Xblack;
extern dword Xwhite;
extern int Xconnection;
extern dword (*Xgetpixel)(int r, int g, int b);
void InitX11Draw(const char *dispname = NULL);
void InitX11Draw(XDisplay *display);
void XError();
void XError(const char *s);
inline dword GetXPixel(int r, int g, int b) { return (*Xgetpixel)(r, g, b); }
inline dword GetXPixel(Color color) { return (*Xgetpixel)(color.GetR(), color.GetG(), color.GetB()); }
enum {
X11_ROP2_ZERO,
X11_ROP2_AND,
X11_ROP2_AND_NOT,
X11_ROP2_COPY,
X11_ROP2_NOT_AND,
X11_ROP2_NOP,
X11_ROP2_XOR,
X11_ROP2_OR,
X11_ROP2_NOT_AND_NOT,
X11_ROP2_NOT_XOR,
X11_ROP2_INVERT,
X11_ROP2_OR_NOT,
X11_ROP2_NOT_COPY,
X11_ROP2_NOT_OR,
X11_ROP2_NOT_OR_NOT,
X11_ROP2_ONE,
};
void SetClip(GC gc, XftDraw *xftdraw, const Vector<Rect>& cl);
class SystemDraw : public Draw {
public:
virtual dword GetInfo() const;
virtual Size GetPageSize() const;
virtual void BeginOp();
virtual void EndOp();
virtual void OffsetOp(Point p);
virtual bool ClipOp(const Rect& r);
virtual bool ClipoffOp(const Rect& r);
virtual bool ExcludeClipOp(const Rect& r);
virtual bool IntersectClipOp(const Rect& r);
virtual bool IsPaintingOp(const Rect& r) const;
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
const int *counts, int count_count,
int width, Color color, Color doxor);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
const int *subpolygon_counts, int scc,
const int *disjunct_polygon_counts, int dpcc,
Color color, int width, Color outline,
uint64 pattern, Color doxor);
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
Color ink, int n, const int *dx);
virtual Size GetNativeDpi() const;
virtual void BeginNative();
virtual void EndNative();
virtual int GetCloffLevel() const;
private:
Size pageSize;
SystemDraw();
friend class ImageDraw;
friend class FontInfo;
friend class Font;
friend class ViewDraw;
friend void StaticExitDraw_();
friend Font StdFont();
FontInfo lastFont;
Point actual_offset;
Point actual_offset_bak;
struct Cloff : Moveable<Cloff> {
Point org;
int clipi;
int offseti;
Rect drawingclip;
};
Array<Cloff> cloff;
Rect drawingclip;
Vector< Vector<Rect> > clip;
Vector<Point> offset;
Drawable dw;
GC gc;
XftDraw *xftdraw;
int foreground;
int linewidth;
void Init();
void Init(const Vector<Rect>& clip, Point offset = Point(0, 0));
void CloneClip();
friend class BackDraw;
friend class ScreenDraw;
public:
static void Flush() { XSync(Xdisplay, false); }
Point GetOffset() const { return actual_offset; }
static XftFont *CreateXftFont(Font f, int angle);
XftDraw *GetXftDraw() const { return xftdraw; }
Rect GetClip() const;
void SetForeground(Color color);
void SetLineStyle(int width);
void SetClip();
Drawable GetDrawable() const { return dw; }
GC GetGC() const { return gc; }
const Vector<Rect>& GetClipList() const { return clip.Top(); }
SystemDraw(Drawable dw, GC gc, XftDraw *xftdraw, const Vector<Rect>& clip);
};
END_UPP_NAMESPACE
#endif

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
#ifdef PLATFORM_WIN32
#include <shellapi.h>
@ -60,7 +60,7 @@ BitmapInfo32__::BitmapInfo32__(int cx, int cy)
HBITMAP CreateBitMask(const RGBA *data, Size sz, Size tsz, Size csz, RGBA *ct)
{
DrawLock __;
GuiLock __;
memset(ct, 0, tsz.cx * tsz.cy * sizeof(RGBA));
int linelen = (tsz.cx + 15) >> 4 << 1;
Buffer<byte> mask(tsz.cy * linelen, 0xff);
@ -90,7 +90,7 @@ HBITMAP CreateBitMask(const RGBA *data, Size sz, Size tsz, Size csz, RGBA *ct)
void SetSurface(HDC dc, int x, int y, int cx, int cy, const RGBA *pixels)
{
DrawLock __;
GuiLock __;
BitmapInfo32__ bi(cx, cy);
::SetDIBitsToDevice(dc, x, y, cx, cy, 0, 0, 0, cy, pixels,
bi, DIB_RGB_COLORS);
@ -125,7 +125,7 @@ public:
void DrawSurface::Init(SystemDraw& w, int _x, int _y, int cx, int cy)
{
DrawLock __;
GuiLock __;
dc = w.GetHandle();
size = Size(cx, cy);
x = _x;
@ -149,7 +149,7 @@ DrawSurface::DrawSurface(SystemDraw& w, int x, int y, int cx, int cy)
DrawSurface::~DrawSurface()
{
DrawLock __;
GuiLock __;
::BitBlt(dc, x, y, size.cx, size.cy, dcMem, 0, 0, SRCCOPY);
::DeleteObject(::SelectObject(dcMem, hbmpOld));
::DeleteDC(dcMem);
@ -166,17 +166,17 @@ void Image::Data::SysRelease()
{
SystemData& sd = Sys();
if(sd.hbmp) {
DrawLock __;
GuiLock __;
DeleteObject(sd.hbmp);
ResCount -= !paintonly;
}
if(sd.hmask) {
DrawLock __;
GuiLock __;
DeleteObject(sd.hmask);
ResCount -= !paintonly;
}
if(sd.himg) {
DrawLock __;
GuiLock __;
DeleteObject(sd.himg);
ResCount -= !paintonly;
}
@ -191,7 +191,7 @@ typedef BOOL (WINAPI *tAlphaBlend)(HDC hdcDest, int nXOriginDest, int nYOriginDe
static tAlphaBlend fnAlphaBlend()
{
DrawLock __;
GuiLock __;
static tAlphaBlend pSet;
static bool inited = false;
if(!inited) {
@ -227,7 +227,7 @@ int Image::Data::GetResCount() const
void Image::Data::CreateHBMP(HDC dc, const RGBA *data)
{
DrawLock __;
GuiLock __;
SystemData& sd = Sys();
Size sz = buffer.GetSize();
BitmapInfo32__ bi(sz.cx, sz.cy);
@ -250,7 +250,7 @@ void Image::Data::CreateHBMP(HDC dc, const RGBA *data)
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
{
DrawLock __;
GuiLock __;
SystemData& sd = Sys();
ASSERT(!paintonly || IsNull(c));
int max = IsWinNT() ? 250 : 100;
@ -365,7 +365,7 @@ void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
void ImageDraw::Section::Init(int cx, int cy)
{
DrawLock __;
GuiLock __;
dc = ::CreateCompatibleDC(ScreenHDC());
BitmapInfo32__ bi(cx, cy);
hbmp = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (void **)&pixels, NULL, 0);
@ -374,14 +374,14 @@ void ImageDraw::Section::Init(int cx, int cy)
ImageDraw::Section::~Section()
{
DrawLock __;
GuiLock __;
::DeleteObject(::SelectObject(dc, hbmpOld));
::DeleteDC(dc);
}
void ImageDraw::Init()
{
DrawLock __;
GuiLock __;
rgb.Init(size.cx, size.cy);
a.Init(size.cx, size.cy);
Attach(rgb.dc);
@ -468,7 +468,7 @@ Image Image::SizeBottomRight() { return Null; }
static Image sWin32Icon(HICON icon, bool cursor)
{
DrawLock __;
GuiLock __;
ICONINFO iconinfo;
if(!icon || !GetIconInfo(icon, &iconinfo))
return Image();
@ -573,7 +573,7 @@ Image Win32Cursor(int id)
HICON IconWin32(const Image& img, bool cursor)
{
DrawLock __;
GuiLock __;
if(img.IsEmpty())
return NULL;
if(cursor) {

View file

@ -1,436 +1,436 @@
#include "Draw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
struct Image::Data::SystemData {
int cursor_cheat;
XPicture picture;
XPicture picture8;
};
Image::Data::SystemData& Image::Data::Sys() const
{
ASSERT(sizeof(system_buffer) >= sizeof(SystemData));
return *(SystemData *)system_buffer;
}
void Image::SetCursorCheat(int id)
{
data->Sys().cursor_cheat = id;
}
int Image::GetCursorCheat() const
{
return data ? data->Sys().cursor_cheat : -1;
}
static void sInitXImage(XImage& ximg, Size sz)
{
Zero(ximg);
ximg.width = sz.cx;
ximg.height = sz.cy;
ximg.xoffset = 0;
ximg.format = ZPixmap;
ximg.bitmap_bit_order = MSBFirst;
#ifdef CPU_LITTLE_ENDIAN
ximg.byte_order = LSBFirst;
#else
ximg.byte_order = MSBFirst;
#endif
}
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
{
DrawLock __;
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, cx, cy, 24);
XPicture picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardRGB24),
0, 0
);
XImage ximg;
sInitXImage(ximg, Size(cx, cy));
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
Buffer<RGBA> pma;
ximg.bitmap_unit = 32;
ximg.depth = 24;
ximg.data = (char *)pixels;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, cx, cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
XRenderComposite(Xdisplay, PictOpOver,
picture, 0, XftDrawPicture(w.GetXftDraw()),
0, 0, 0, 0, x, y, cx, cy);
XRenderFreePicture(Xdisplay, picture);
}
int Image::Data::GetResCount() const
{
return !!Sys().picture + !!Sys().picture8;
}
void Image::Data::SysInit()
{
SystemData& sd = Sys();
sd.picture = 0;
sd.picture8 = 0;
sd.cursor_cheat = -1;
}
void Image::Data::SysRelease()
{
SystemData& sd = Sys();
if(sd.picture) {
DrawLock __;
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture);
ResCount -= !paintonly;
sd.picture = 0;
}
if(sd.picture8) {
DrawLock __;
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture8);
ResCount -= !paintonly;
sd.picture8 = 0;
}
}
struct XRSolidFill {
Color color;
XPicture picture;
Pixmap pixmap;
};
enum { XRSolidFillCount = 67 };
static XRSolidFill sFill[XRSolidFillCount];
inline int s255d16(int x)
{
return (x << 8)|x;
}
static XPicture sGetSolidFill(Color c)
{
DrawLock __;
int q = GetHashValue(c) % (int)XRSolidFillCount;
XRSolidFill& f = sFill[q];
if(f.color == c && f.picture)
return f.picture;
if(f.picture)
XRenderFreePicture(Xdisplay, f.picture);
if(f.pixmap)
XFreePixmap(Xdisplay, f.pixmap);
f.pixmap = XCreatePixmap(Xdisplay, Xroot, 1, 1, 32);
XRenderPictureAttributes attr;
attr.repeat = XTrue;
f.picture = XRenderCreatePicture(Xdisplay, f.pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
CPRepeat, &attr);
f.color = c;
XRenderColor xc;
xc.red = s255d16(c.GetR());
xc.green = s255d16(c.GetG());
xc.blue = s255d16(c.GetB());
xc.alpha = 65535;
XRenderFillRectangle(Xdisplay, PictOpSrc, f.picture, &xc, 0, 0, 1, 1);
return f.picture;
}
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
{
DrawLock __;
SystemData& sd = Sys();
while(ResCount > 512) {
Image::Data *l = ResData->GetPrev();
l->SysRelease();
l->Unlink();
}
x += w.GetOffset().x;
y += w.GetOffset().y;
Size sz = buffer.GetSize();
int len = sz.cx * sz.cy;
Rect sr = src & sz;
Size ssz = sr.Size();
if(sr.IsEmpty())
return;
if(GetKind() == IMAGE_EMPTY)
return;
if(GetKind() == IMAGE_OPAQUE && !IsNull(c)) {
w.DrawRect(x, y, sz.cx, sz.cy, c);
return;
}
if(GetKind() == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz)) {
SetSurface(w, x, y, sz.cx, sz.cy, buffer);
paintcount++;
return;
}
Unlink();
LinkAfter(ResData);
if(IsNull(c)) {
if(!sd.picture) {
bool opaque = GetKind() == IMAGE_OPAQUE;
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32);
sd.picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24
: PictStandardARGB32),
0, 0
);
ResCount++;
XImage ximg;
sInitXImage(ximg, sz);
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * sz.cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
ximg.bitmap_unit = 32;
ximg.data = (char *)~buffer;
ximg.depth = opaque ? 24 : 32;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
PaintOnlyShrink();
}
XRenderComposite(Xdisplay, PictOpOver,
sd.picture, 0, XftDrawPicture(w.GetXftDraw()),
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
}
else {
ASSERT(!paintonly);
if(!sd.picture8) {
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8);
sd.picture8 = XRenderCreatePicture(Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
0, 0);
ResCount++;
Buffer<byte> ab(len);
byte *t = ab;
const RGBA *s = buffer;
const RGBA *e = s + len;
while(s < e)
*t++ = (s++)->a;
XImage ximg;
sInitXImage(ximg, sz);
ximg.data = (char *)~ab;
ximg.bitmap_unit = 8;
ximg.bitmap_pad = 8;
ximg.depth = 8;
ximg.bytes_per_line = sz.cx;
ximg.bits_per_pixel = 8;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
}
XRenderComposite(Xdisplay, PictOpOver,
sGetSolidFill(c), sd.picture8, XftDrawPicture(w.GetXftDraw()),
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
}
}
void ImageDraw::Init()
{
DrawLock __;
dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
gc = XCreateGC(Xdisplay, dw, 0, 0);
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
alpha.dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
alpha.gc = XCreateGC(Xdisplay, alpha.dw, 0, 0);
alpha.xftdraw = XftDrawCreate(Xdisplay, (Drawable) alpha.dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
Vector<Rect> clip;
clip.Add(RectC(0, 0, size.cx, size.cy));
SystemDraw::Init(clip, Point(0, 0));
alpha.Init(clip, Point(0, 0));
has_alpha = false;
}
ImageDraw::operator Image() const
{
DrawLock __;
XImage *xim = XGetImage(Xdisplay, dw, 0, 0, max(size.cx, 1), max(size.cy, 1), AllPlanes, ZPixmap);
Visual *v = DefaultVisual(Xdisplay, Xscreenno);
RasterFormat fmt;
RGBA palette[256];
switch(xim->depth) {
case 15:
case 16:
if(xim->byte_order == LSBFirst)
fmt.Set16le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set16be(v->red_mask, v->green_mask, v->blue_mask);
break;
case 8: {
int n = min(v->map_entries, 256);
XColor colors[256];
for(int i = 0; i < 256; i++) {
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
}
XQueryColors(Xdisplay, Xcolormap, colors, n);
XColor *s = colors;
XColor *e = s + n;
while(s < e) {
RGBA& t = palette[s->pixel];
t.r = s->red >> 8;
t.g = s->green >> 8;
t.b = s->blue >> 8;
t.a = 255;
s++;
}
fmt.Set8();
break;
}
default:
if(xim->bits_per_pixel == 32)
if(xim->byte_order == LSBFirst)
fmt.Set32le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set32be(v->red_mask, v->green_mask, v->blue_mask);
else
if(xim->byte_order == LSBFirst)
fmt.Set24le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set24be(v->red_mask, v->green_mask, v->blue_mask);
break;
}
ImageBuffer ib(size);
const byte *s = (const byte *)xim->data;
RGBA *t = ib;
for(int y = 0; y < size.cy; y++) {
fmt.Read(t, s, size.cx, palette);
s += xim->bytes_per_line;
t += size.cx;
}
XDestroyImage(xim);
if(has_alpha) {
xim = XGetImage(Xdisplay, alpha.dw, 0, 0, size.cx, size.cy, AllPlanes, ZPixmap);
const byte *s = (const byte *)xim->data;
t = ib;
Buffer<RGBA> line(size.cx);
for(int y = 0; y < size.cy; y++) {
fmt.Read(line, s, size.cx, palette);
for(int x = 0; x < size.cx; x++)
(t++)->a = line[x].r;
s += xim->bytes_per_line;
}
XDestroyImage(xim);
}
Premultiply(ib);
return ib;
}
ImageDraw::ImageDraw(Size sz)
{
size = sz;
Init();
}
ImageDraw::ImageDraw(int cx, int cy)
{
size = Size(cx, cy);
Init();
}
ImageDraw::~ImageDraw()
{
DrawLock __;
XftDrawDestroy(xftdraw);
XFreePixmap(Xdisplay, dw);
XFreeGC(Xdisplay, gc);
XftDrawDestroy(alpha.xftdraw);
XFreePixmap(Xdisplay, alpha.dw);
XFreeGC(Xdisplay, alpha.gc);
}
Image sX11Cursor__(int c)
{
ImageBuffer b(32, 32);
Image m(b);
m.SetCursorCheat(c);
return m;
}
#include <X11/cursorfont.h>
#define FCURSOR_(x) { Image h; INTERLOCKED { static Image m = sX11Cursor__(x); h = m; } return h; }
Image Image::Arrow() FCURSOR_(XC_left_ptr)
Image Image::Wait() FCURSOR_(XC_watch)
Image Image::IBeam() FCURSOR_(XC_xterm)
Image Image::No() FCURSOR_(XC_circle)
Image Image::SizeAll() FCURSOR_(XC_fleur)
Image Image::SizeHorz() FCURSOR_(XC_sb_h_double_arrow)
Image Image::SizeVert() FCURSOR_(XC_double_arrow)
Image Image::SizeTopLeft() FCURSOR_(XC_top_left_corner)
Image Image::SizeTop() FCURSOR_(XC_top_side)
Image Image::SizeTopRight() FCURSOR_(XC_top_right_corner)
Image Image::SizeLeft() FCURSOR_(XC_left_side)
Image Image::SizeRight() FCURSOR_(XC_right_side)
Image Image::SizeBottomLeft() FCURSOR_(XC_bottom_left_corner)
Image Image::SizeBottom() FCURSOR_(XC_bottom_side)
Image Image::SizeBottomRight() FCURSOR_(XC_bottom_right_corner)
Image Image::Cross() FCURSOR_(XC_crosshair)
Image Image::Hand() FCURSOR_(XC_hand1)
Cursor X11Cursor(const Image& img)
{
DrawLock __;
int q = img.GetCursorCheat();
if(q >= 0)
return XCreateFontCursor(Xdisplay, q);
int len = img.GetLength();
Size sz = img.GetSize();
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 32);
XPicture picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
0, 0
);
XImage ximg;
sInitXImage(ximg, sz);
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * sz.cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
Buffer<RGBA> pma;
pma.Alloc(len);
memcpy(pma, ~img, len * sizeof(RGBA));
ximg.bitmap_unit = 32;
ximg.depth = 32;
ximg.data = (char *)~pma;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
Point p = img.GetHotSpot();
Cursor c = XRenderCreateCursor(Xdisplay, picture, p.x, p.y);
XRenderFreePicture(Xdisplay, picture);
return c;
}
#endif
END_UPP_NAMESPACE
#include "SystemDraw.h"
NAMESPACE_UPP
#ifdef PLATFORM_X11
struct Image::Data::SystemData {
int cursor_cheat;
XPicture picture;
XPicture picture8;
};
Image::Data::SystemData& Image::Data::Sys() const
{
ASSERT(sizeof(system_buffer) >= sizeof(SystemData));
return *(SystemData *)system_buffer;
}
void Image::SetCursorCheat(int id)
{
data->Sys().cursor_cheat = id;
}
int Image::GetCursorCheat() const
{
return data ? data->Sys().cursor_cheat : -1;
}
static void sInitXImage(XImage& ximg, Size sz)
{
Zero(ximg);
ximg.width = sz.cx;
ximg.height = sz.cy;
ximg.xoffset = 0;
ximg.format = ZPixmap;
ximg.bitmap_bit_order = MSBFirst;
#ifdef CPU_LITTLE_ENDIAN
ximg.byte_order = LSBFirst;
#else
ximg.byte_order = MSBFirst;
#endif
}
void SetSurface(SystemDraw& w, int x, int y, int cx, int cy, const RGBA *pixels)
{
GuiLock __;
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, cx, cy, 24);
XPicture picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardRGB24),
0, 0
);
XImage ximg;
sInitXImage(ximg, Size(cx, cy));
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
Buffer<RGBA> pma;
ximg.bitmap_unit = 32;
ximg.depth = 24;
ximg.data = (char *)pixels;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, cx, cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
XRenderComposite(Xdisplay, PictOpOver,
picture, 0, XftDrawPicture(w.GetXftDraw()),
0, 0, 0, 0, x, y, cx, cy);
XRenderFreePicture(Xdisplay, picture);
}
int Image::Data::GetResCount() const
{
return !!Sys().picture + !!Sys().picture8;
}
void Image::Data::SysInit()
{
SystemData& sd = Sys();
sd.picture = 0;
sd.picture8 = 0;
sd.cursor_cheat = -1;
}
void Image::Data::SysRelease()
{
SystemData& sd = Sys();
if(sd.picture) {
GuiLock __;
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture);
ResCount -= !paintonly;
sd.picture = 0;
}
if(sd.picture8) {
GuiLock __;
if(Xdisplay) XRenderFreePicture(Xdisplay, sd.picture8);
ResCount -= !paintonly;
sd.picture8 = 0;
}
}
struct XRSolidFill {
Color color;
XPicture picture;
Pixmap pixmap;
};
enum { XRSolidFillCount = 67 };
static XRSolidFill sFill[XRSolidFillCount];
inline int s255d16(int x)
{
return (x << 8)|x;
}
static XPicture sGetSolidFill(Color c)
{
GuiLock __;
int q = GetHashValue(c) % (int)XRSolidFillCount;
XRSolidFill& f = sFill[q];
if(f.color == c && f.picture)
return f.picture;
if(f.picture)
XRenderFreePicture(Xdisplay, f.picture);
if(f.pixmap)
XFreePixmap(Xdisplay, f.pixmap);
f.pixmap = XCreatePixmap(Xdisplay, Xroot, 1, 1, 32);
XRenderPictureAttributes attr;
attr.repeat = XTrue;
f.picture = XRenderCreatePicture(Xdisplay, f.pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
CPRepeat, &attr);
f.color = c;
XRenderColor xc;
xc.red = s255d16(c.GetR());
xc.green = s255d16(c.GetG());
xc.blue = s255d16(c.GetB());
xc.alpha = 65535;
XRenderFillRectangle(Xdisplay, PictOpSrc, f.picture, &xc, 0, 0, 1, 1);
return f.picture;
}
void Image::Data::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
{
GuiLock __;
SystemData& sd = Sys();
while(ResCount > 512) {
Image::Data *l = ResData->GetPrev();
l->SysRelease();
l->Unlink();
}
x += w.GetOffset().x;
y += w.GetOffset().y;
Size sz = buffer.GetSize();
int len = sz.cx * sz.cy;
Rect sr = src & sz;
Size ssz = sr.Size();
if(sr.IsEmpty())
return;
if(GetKind() == IMAGE_EMPTY)
return;
if(GetKind() == IMAGE_OPAQUE && !IsNull(c)) {
w.DrawRect(x, y, sz.cx, sz.cy, c);
return;
}
if(GetKind() == IMAGE_OPAQUE && paintcount == 0 && sr == Rect(sz)) {
SetSurface(w, x, y, sz.cx, sz.cy, buffer);
paintcount++;
return;
}
Unlink();
LinkAfter(ResData);
if(IsNull(c)) {
if(!sd.picture) {
bool opaque = GetKind() == IMAGE_OPAQUE;
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, opaque ? 24 : 32);
sd.picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, opaque ? PictStandardRGB24
: PictStandardARGB32),
0, 0
);
ResCount++;
XImage ximg;
sInitXImage(ximg, sz);
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * sz.cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
ximg.bitmap_unit = 32;
ximg.data = (char *)~buffer;
ximg.depth = opaque ? 24 : 32;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
PaintOnlyShrink();
}
XRenderComposite(Xdisplay, PictOpOver,
sd.picture, 0, XftDrawPicture(w.GetXftDraw()),
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
}
else {
ASSERT(!paintonly);
if(!sd.picture8) {
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 8);
sd.picture8 = XRenderCreatePicture(Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardA8),
0, 0);
ResCount++;
Buffer<byte> ab(len);
byte *t = ab;
const RGBA *s = buffer;
const RGBA *e = s + len;
while(s < e)
*t++ = (s++)->a;
XImage ximg;
sInitXImage(ximg, sz);
ximg.data = (char *)~ab;
ximg.bitmap_unit = 8;
ximg.bitmap_pad = 8;
ximg.depth = 8;
ximg.bytes_per_line = sz.cx;
ximg.bits_per_pixel = 8;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
}
XRenderComposite(Xdisplay, PictOpOver,
sGetSolidFill(c), sd.picture8, XftDrawPicture(w.GetXftDraw()),
sr.left, sr.top, 0, 0, x, y, ssz.cx, ssz.cy);
}
}
void ImageDraw::Init()
{
GuiLock __;
dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
gc = XCreateGC(Xdisplay, dw, 0, 0);
xftdraw = XftDrawCreate(Xdisplay, (Drawable) dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
alpha.dw = XCreatePixmap(Xdisplay, Xroot, max(size.cx, 1), max(size.cy, 1), Xdepth);
alpha.gc = XCreateGC(Xdisplay, alpha.dw, 0, 0);
alpha.xftdraw = XftDrawCreate(Xdisplay, (Drawable) alpha.dw, DefaultVisual(Xdisplay, Xscreenno), Xcolormap);
Vector<Rect> clip;
clip.Add(RectC(0, 0, size.cx, size.cy));
SystemDraw::Init(clip, Point(0, 0));
alpha.Init(clip, Point(0, 0));
has_alpha = false;
}
ImageDraw::operator Image() const
{
GuiLock __;
XImage *xim = XGetImage(Xdisplay, dw, 0, 0, max(size.cx, 1), max(size.cy, 1), AllPlanes, ZPixmap);
Visual *v = DefaultVisual(Xdisplay, Xscreenno);
RasterFormat fmt;
RGBA palette[256];
switch(xim->depth) {
case 15:
case 16:
if(xim->byte_order == LSBFirst)
fmt.Set16le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set16be(v->red_mask, v->green_mask, v->blue_mask);
break;
case 8: {
int n = min(v->map_entries, 256);
XColor colors[256];
for(int i = 0; i < 256; i++) {
colors[i].pixel = i;
colors[i].flags = DoRed|DoGreen|DoBlue;
}
XQueryColors(Xdisplay, Xcolormap, colors, n);
XColor *s = colors;
XColor *e = s + n;
while(s < e) {
RGBA& t = palette[s->pixel];
t.r = s->red >> 8;
t.g = s->green >> 8;
t.b = s->blue >> 8;
t.a = 255;
s++;
}
fmt.Set8();
break;
}
default:
if(xim->bits_per_pixel == 32)
if(xim->byte_order == LSBFirst)
fmt.Set32le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set32be(v->red_mask, v->green_mask, v->blue_mask);
else
if(xim->byte_order == LSBFirst)
fmt.Set24le(v->red_mask, v->green_mask, v->blue_mask);
else
fmt.Set24be(v->red_mask, v->green_mask, v->blue_mask);
break;
}
ImageBuffer ib(size);
const byte *s = (const byte *)xim->data;
RGBA *t = ib;
for(int y = 0; y < size.cy; y++) {
fmt.Read(t, s, size.cx, palette);
s += xim->bytes_per_line;
t += size.cx;
}
XDestroyImage(xim);
if(has_alpha) {
xim = XGetImage(Xdisplay, alpha.dw, 0, 0, size.cx, size.cy, AllPlanes, ZPixmap);
const byte *s = (const byte *)xim->data;
t = ib;
Buffer<RGBA> line(size.cx);
for(int y = 0; y < size.cy; y++) {
fmt.Read(line, s, size.cx, palette);
for(int x = 0; x < size.cx; x++)
(t++)->a = line[x].r;
s += xim->bytes_per_line;
}
XDestroyImage(xim);
}
Premultiply(ib);
return ib;
}
ImageDraw::ImageDraw(Size sz)
{
size = sz;
Init();
}
ImageDraw::ImageDraw(int cx, int cy)
{
size = Size(cx, cy);
Init();
}
ImageDraw::~ImageDraw()
{
GuiLock __;
XftDrawDestroy(xftdraw);
XFreePixmap(Xdisplay, dw);
XFreeGC(Xdisplay, gc);
XftDrawDestroy(alpha.xftdraw);
XFreePixmap(Xdisplay, alpha.dw);
XFreeGC(Xdisplay, alpha.gc);
}
Image sX11Cursor__(int c)
{
ImageBuffer b(32, 32);
Image m(b);
m.SetCursorCheat(c);
return m;
}
#include <X11/cursorfont.h>
#define FCURSOR_(x) { Image h; INTERLOCKED { static Image m = sX11Cursor__(x); h = m; } return h; }
Image Image::Arrow() FCURSOR_(XC_left_ptr)
Image Image::Wait() FCURSOR_(XC_watch)
Image Image::IBeam() FCURSOR_(XC_xterm)
Image Image::No() FCURSOR_(XC_circle)
Image Image::SizeAll() FCURSOR_(XC_fleur)
Image Image::SizeHorz() FCURSOR_(XC_sb_h_double_arrow)
Image Image::SizeVert() FCURSOR_(XC_double_arrow)
Image Image::SizeTopLeft() FCURSOR_(XC_top_left_corner)
Image Image::SizeTop() FCURSOR_(XC_top_side)
Image Image::SizeTopRight() FCURSOR_(XC_top_right_corner)
Image Image::SizeLeft() FCURSOR_(XC_left_side)
Image Image::SizeRight() FCURSOR_(XC_right_side)
Image Image::SizeBottomLeft() FCURSOR_(XC_bottom_left_corner)
Image Image::SizeBottom() FCURSOR_(XC_bottom_side)
Image Image::SizeBottomRight() FCURSOR_(XC_bottom_right_corner)
Image Image::Cross() FCURSOR_(XC_crosshair)
Image Image::Hand() FCURSOR_(XC_hand1)
Cursor X11Cursor(const Image& img)
{
GuiLock __;
int q = img.GetCursorCheat();
if(q >= 0)
return XCreateFontCursor(Xdisplay, q);
int len = img.GetLength();
Size sz = img.GetSize();
Pixmap pixmap = XCreatePixmap(Xdisplay, Xroot, sz.cx, sz.cy, 32);
XPicture picture = XRenderCreatePicture(
Xdisplay, pixmap,
XRenderFindStandardFormat(Xdisplay, PictStandardARGB32),
0, 0
);
XImage ximg;
sInitXImage(ximg, sz);
ximg.bitmap_pad = 32;
ximg.bytes_per_line = 4 * sz.cx;
ximg.bits_per_pixel = 32;
ximg.blue_mask = 0x00ff0000;
ximg.green_mask = 0x0000ff00;
ximg.red_mask = 0x000000ff;
Buffer<RGBA> pma;
pma.Alloc(len);
memcpy(pma, ~img, len * sizeof(RGBA));
ximg.bitmap_unit = 32;
ximg.depth = 32;
ximg.data = (char *)~pma;
XInitImage(&ximg);
GC gc = XCreateGC(Xdisplay, pixmap, 0, 0);
XPutImage(Xdisplay, pixmap, gc, &ximg, 0, 0, 0, 0, sz.cx, sz.cy);
XFreeGC(Xdisplay, gc);
XFreePixmap(Xdisplay, pixmap);
Point p = img.GetHotSpot();
Cursor c = XRenderCreateCursor(Xdisplay, picture, p.x, p.y);
XRenderFreePicture(Xdisplay, picture);
return c;
}
#endif
END_UPP_NAMESPACE

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP

View file

@ -1,4 +1,4 @@
#include "Draw.h"
#include "SystemDraw.h"
NAMESPACE_UPP
@ -6,7 +6,7 @@ NAMESPACE_UPP
void SystemDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color)
{
DrawLock __;
GuiLock __;
LTIMING("DrawImageOp");
bool tonative = !IsNative();
if(tonative) {
@ -40,4 +40,14 @@ void SystemDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& img, con
EndNative();
}
Draw& ImageDraw::Alpha()
{
if(!has_alpha) {
alpha.DrawRect(size, GrayColor(0));
has_alpha = true;
}
return alpha;
}
END_UPP_NAMESPACE

View file

@ -1,3 +1,25 @@
#include <Draw/Draw.h>
#ifdef PLATFORM_WIN32
#include "DrawWin32.h"
#endif
#ifdef PLATFORM_X11
#include "DrawX11.h"
#endif
NAMESPACE_UPP
typedef DrawLock GuiLock;
inline void EnterGuiMutex() { EnterGMutex(); }
inline void EnterGuiMutex(int n) { EnterGMutex(n); }
inline void LeaveGuiMutex() { LeaveGMutex(); }
inline int LeaveGuiMutexAll() { return LeaveGMutexAll(); }
bool ScreenInPaletteMode();
Size GetScreenSize();
class BackDraw : public SystemDraw {
public:
virtual bool IsPaintingOp(const Rect& r) const;
@ -76,3 +98,10 @@ public:
ImageDraw(int cx, int cy);
~ImageDraw();
};
typedef ImageDraw SystemImageDraw;
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, uint64 pattern);
END_UPP_NAMESPACE

View file

@ -2,7 +2,7 @@
#define _CtrlCore_icpp_init_stub
#include "Draw/init"
#include "plugin\bmp/init"
#define BLITZ_INDEX__ F3E00C8C1D354C9B98AA929A9E9F39109
#define BLITZ_INDEX__ F50C6488AA9AC98A955BA0CD0115A83C1
#include "CtrlCore.icpp"
#undef BLITZ_INDEX__
#endif

View file

@ -411,26 +411,6 @@ void Draw::DrawPainting(int x, int y, int cx, int cy, const Painting& ig)
DrawPainting(RectC(x, y, cx, cy), ig);
}
#ifdef PLATFORM_WIN32_
HDC Draw::BeginGdi()
{
SystemDraw *w = dynamic_cast<SystemDraw *>(this);
return w ? w->BeginGdi() : NULL;
}
void Draw::EndGdi()
{
SystemDraw *w = dynamic_cast<SystemDraw *>(this);
if(w) w->EndGdi();
}
void Draw::Flush()
{
SystemDraw::Flush();
}
#endif
// ---------------------------
dword NilDraw::GetInfo() const { return DOTS; }

File diff suppressed because it is too large Load diff

View file

@ -1,81 +1,79 @@
description "Fundamental graphics operations, including raster image processing\377B128,0,255";
acceptflags
NOGTK;
uses
Core;
library((LINUX | BSD) & !NOGTK) "gtk-x11-2.0 gdk-x11-2.0 atk-1.0 gdk_pixbuf-2.0 m pangocairo-1.0 fontconfig Xext Xrender Xinerama Xi Xrandr Xcursor Xfixes pango-1.0 cairo X11 gobject-2.0 gmodule-2.0 glib-2.0";
library(WIN32 !MSC8ARM) "user32 gdi32";
library(LINUX) X11;
library(LINUX) dl;
library(LINUX !XLFD) Xft;
library(BSD) "X11 Xau Xdmcp";
library(BSD !XLFD) "Xft fontconfig Xrender freetype expat";
library(LINUX !XLFD !SHARED) "fontconfig Xrender freetype expat";
library(OSX11) "X11 Xft fontconfig Xrender freetype expat";
library(FREEBSD) xcb;
file
Draw.h,
Mt.cpp,
FontInt.h,
Font.cpp,
FontCR.cpp,
FontWin32.cpp,
FontFc.cpp,
Draw.cpp,
DrawText.cpp,
DrawData.cpp,
Drawing.cpp,
DrawUtil.cpp,
DrawTextUtil.cpp,
Display.h,
Display.cpp,
Debug.h,
Debug.cpp,
Image readonly separator,
Image.h,
Image.cpp,
ImageBlit.cpp,
Raster.h,
RasterFormat.cpp,
RasterWrite.cpp,
Palette.cpp,
Raster.cpp,
RasterEncoder.cpp,
ImageOp.h,
ImageOp.cpp,
ImageChOp.cpp,
ImageScale.cpp,
MakeCache.cpp,
DrawRasterData.cpp,
iml.h,
iml_header.h,
iml_source.h,
DrawImg.iml,
Chameleon readonly separator,
Cham.h,
Cham.cpp,
SSettings.cpp,
GTK-dli readonly separator,
gobj.dli,
gdk.dli,
gpixbuf.dli,
gtk.dli,
gnome.dli,
Info readonly separator,
src.tpp,
srcdoc.tpp,
Copying;
description "Fundamental graphics operations, including raster image processing\377B128,0,255";
acceptflags
NOGTK;
uses
Core;
library((LINUX | BSD) & !NOGTK) "gtk-x11-2.0 gdk-x11-2.0 atk-1.0 gdk_pixbuf-2.0 m pangocairo-1.0 fontconfig Xext Xrender Xinerama Xi Xrandr Xcursor Xfixes pango-1.0 cairo X11 gobject-2.0 gmodule-2.0 glib-2.0";
library(WIN32 !MSC8ARM) "user32 gdi32";
library(LINUX) X11;
library(LINUX) dl;
library(LINUX !XLFD) Xft;
library(BSD) "X11 Xau Xdmcp";
library(BSD !XLFD) "Xft fontconfig Xrender freetype expat";
library(LINUX !XLFD !SHARED) "fontconfig Xrender freetype expat";
library(OSX11) "X11 Xft fontconfig Xrender freetype expat";
library(FREEBSD) xcb;
file
Draw.h,
DrawLock.cpp,
FontInt.h,
Font.cpp,
FontCR.cpp,
FontWin32.cpp,
FontFc.cpp,
Draw.cpp,
DrawText.cpp,
DrawData.cpp,
Drawing.cpp,
DrawUtil.cpp,
DrawTextUtil.cpp,
Display.h,
Display.cpp,
Image readonly separator,
Image.h,
Image.cpp,
ImageBlit.cpp,
Raster.h,
RasterFormat.cpp,
RasterWrite.cpp,
Palette.cpp,
Raster.cpp,
RasterEncoder.cpp,
ImageOp.h,
ImageOp.cpp,
ImageChOp.cpp,
ImageScale.cpp,
MakeCache.cpp,
DrawRasterData.cpp,
iml.h,
iml_header.h,
iml_source.h,
DrawImg.iml,
Chameleon readonly separator,
Cham.h,
Cham.cpp,
SSettings.cpp,
GTK-dli readonly separator,
gobj.dli,
gdk.dli,
gpixbuf.dli,
gtk.dli,
gnome.dli,
Info readonly separator,
src.tpp,
srcdoc.tpp,
Copying;

View file

@ -102,7 +102,7 @@ void Draw::DrawDataOp(int x, int y, int cx, int cy, const String& data, const ch
One<DataDrawer> dd = DataDrawer::Create(id);
if(dd) {
dd->Open(data, cx, cy);
if((cx > 2048 || cy > 2048) && dynamic_cast<SystemDraw *>(this)) {
if((cx > 2048 || cy > 2048) && GetInfo() & DATABANDS) {
int yy = 0;
while(yy < cy) {
int ccy = min(cy - yy, 32);

View file

@ -484,139 +484,6 @@ void DrawXPButton(Draw& w, Rect r, int type)
}
}
#ifdef PLATFORM_WIN32
HRGN GetFrameRgn(const Rect& rect, int n) {
HRGN rgn = CreateRectRgnIndirect(rect);
Rect r = rect;
r.Deflate(n);
if(r.Width() > 0 && r.Height() > 0) {
HRGN rgnin = CreateRectRgnIndirect(r);
CombineRgn(rgn, rgn, rgnin, RGN_XOR);
DeleteObject(rgnin);
}
return rgn;
}
void DrawDragRect(SystemDraw& w, const Rect& _rect1, const Rect& _rect2, const Rect& _clip, int n, Color color, uint64 pattern)
{
Point o = w.GetOffset();
Rect rect1 = _rect1 + o;
Rect rect2 = _rect2 + o;
Rect clip = _clip + o;
HDC hdc = w.BeginGdi();
word wpat[8] = {
(byte)(pattern >> 56), (byte)(pattern >> 48), (byte)(pattern >> 40), (byte)(pattern >> 32),
(byte)(pattern >> 24), (byte)(pattern >> 16), (byte)(pattern >> 8), (byte)(pattern >> 0),
};
HBITMAP bitmap = CreateBitmap(8, 8, 1, 1, wpat);
HBRUSH brush = ::CreatePatternBrush(bitmap);
DeleteObject(bitmap);
SetTextColor(hdc, color);
SetBkColor(hdc, SColorText());
Point offset;
#ifdef PLATFORM_WINCE
offset = Point(0, 0);
#else
::GetViewportOrgEx(hdc, offset);
#endif
HRGN rgn = GetFrameRgn(rect1 + offset, n);
HRGN rgn2 = GetFrameRgn(rect2 + offset, n);
HRGN cliprgn = CreateRectRgnIndirect(clip + offset);
CombineRgn(rgn, rgn, rgn2, RGN_XOR);
CombineRgn(rgn, rgn, cliprgn, RGN_AND);
SelectClipRgn(hdc, rgn);
Rect r;
GetClipBox(hdc, r);
HBRUSH obrush = (HBRUSH) SelectObject(hdc, brush);
PatBlt(hdc, r.left, r.top, r.Width(), r.Height(), PATINVERT);
SelectObject(hdc, obrush);
SelectClipRgn(hdc, NULL);
DeleteObject(rgn);
DeleteObject(rgn2);
DeleteObject(cliprgn);
ReleaseDC(NULL, hdc);
DeleteObject(brush);
w.EndGdi();
}
#endif
#ifdef PLATFORM_X11
Vector<Rect> RectRgn(const Rect& r)
{
Vector<Rect> q;
q.Add(r);
return q;
}
Vector<Rect> Intersect(const Vector<Rect>& r1, const Vector<Rect>& r2)
{
Vector<Rect> q;
for(int i = 0; i < r1.GetCount(); i++)
for(int j = 0; j < r2.GetCount(); j++) {
Rect r = r1[i] & r2[j];
if(!r.IsEmpty())
q.Add(r);
}
return q;
}
Vector<Rect> Subtract(const Vector<Rect>& r1, const Vector<Rect>& r2)
{
Vector<Rect> q;
bool dummy;
q <<= r1;
for(int i = 0; i < r2.GetCount(); i++)
q = Subtract(q, r2[i], dummy);
return q;
}
Vector<Rect> Xor(const Vector<Rect>& r1, const Vector<Rect>& r2)
{
Vector<Rect> is = Intersect(r1, r2);
Vector<Rect> q = Subtract(r1, is);
q.Append(Subtract(r2, is));
return q;
}
Vector<Rect> GetFrameRgn(const Rect& rect, int n) {
Vector<Rect> q = RectRgn(rect);
q.Add(rect);
Rect r = rect;
r.Deflate(n);
if(r.Width() > 0 && r.Height() > 0)
q = Xor(q, RectRgn(r));
return q;
}
void DrawDragRect(SystemDraw& w, const Rect& rect1, const Rect& rect2, const Rect& clip, int n,
Color color, uint64 pattern)
{
char bd[8];
for(int i = 0; i < 8; i++)
bd[i] = ~(byte)(pattern >> (8 * (7 - i)));
Pixmap stipple = XCreateBitmapFromData(Xdisplay, w.GetDrawable(), bd, 8, 8);
Point offset = w.GetOffset();
GC gc = XCreateGC(Xdisplay, w.GetDrawable(), 0, 0);
SetClip(gc, w.GetXftDraw(),
Intersect(Xor(GetFrameRgn(rect1 + offset, n), GetFrameRgn(rect2 + offset, n)),
RectRgn(clip + offset)));
XGCValues gcv;
gcv.function = X11_ROP2_XOR;
gcv.foreground = GetXPixel(color);
gcv.fill_style = FillStippled;
gcv.stipple = stipple;
XChangeGC(Xdisplay, gc, GCForeground|GCFunction|GCStipple|GCFillStyle, &gcv);
XFillRectangle(Xdisplay, w.GetDrawable(), gc, 0, 0, Xwidth, Xheight);
XFreePixmap(Xdisplay, stipple);
}
#endif
static DrawingToPdfFnType sPdf;
void SetDrawingToPdfFn(DrawingToPdfFnType Pdf)

View file

@ -1,341 +1,343 @@
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
CommonFontInfo GetFontInfoSys(Font font);
GlyphInfo GetGlyphInfoSys(Font font, int chr);
void GetStdFontSys(String& name, int& height);
Vector<FaceInfo> GetAllFacesSys();
bool Replace(Font fnt, int chr, Font& rfnt);
void Std(Font& font)
{
if(IsNull(font))
font = StdFont();
if(font.GetFace() == 0)
font.Face(GetStdFont().GetFace());
if(font.GetHeight() == 0)
font.Height(GetStdFont().GetHeight());
}
Size Font::StdFontSize;
Font Font::AStdFont;
INITBLOCK {
RichValue<Font>::Register();
}
const Vector<FaceInfo>& Font::List()
{
static Vector<FaceInfo> *q;
ONCELOCK {
static Vector<FaceInfo> x;
x = GetAllFacesSys();
q = &x;
}
return *q;
}
void sInitFonts()
{
Font::List();
GetStdFont();
}
INITBLOCK {
sInitFonts();
}
int Font::GetFaceCount()
{
return List().GetCount();
}
String Font::GetFaceName(int index)
{
if(index == 0)
return "STDFONT";
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].name;
return Null;
}
dword Font::GetFaceInfo(int index)
{
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].info;
return 0;
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const String& name) {
if(name == "STDFONT")
return 0;
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
void Font::SyncStdFont()
{
DrawLock __;
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
}
void Font::SetStdFont(Font font)
{
DrawLock __;
InitStdFont();
AStdFont = font;
SyncStdFont();
DLOG("SetStdFont " << font);
}
void Font::InitStdFont()
{
ONCELOCK {
DrawLock __;
List();
AStdFont = Arial(12);
String name;
int height = 0;
GetStdFontSys(name, height);
int q = FindFaceNameIndex(name);
if(q > 0)
SetStdFont(Font(q, max(height, 1)));
}
}
Font Font::GetStdFont()
{
InitStdFont();
return AStdFont;
}
Size Font::GetStdFontSize()
{
InitStdFont();
return StdFontSize;
}
Font StdFont()
{
return Font(0, 0);
}
int Font::GetHeight() const
{
return v.height ? v.height : GetStdFont().GetHeight();
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % v.flags % v.height % v.width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
struct CharEntry {
int64 font;
GlyphInfo info;
word chr;
};
CharEntry fc_cache_global[4093];
bool IsNormal(Font font, int chr)
{
DrawLock __;
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
if(e.font == font.AsInt64() || e.chr == chr)
return e.info.IsNormal();
return GetGlyphInfoSys(font, chr).IsNormal();
}
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
{
DrawLock __;
CharEntry& e = fc_cache_global[hash % 4093];
if(e.font != font.AsInt64() || e.chr != chr) {
e.font = font.AsInt64();
e.chr = chr;
e.info = GetGlyphInfoSys(font, chr);
if(!e.info.IsNormal()) {
ComposedGlyph cg;
Font rfnt;
if(Compose(font, chr, cg)) {
e.info.lspc = -1;
e.info.rspc = cg.basic_char;
}
else
if(Replace(font, chr, rfnt)) {
e.info.lspc = rfnt.GetFace();
e.info.rspc = rfnt.GetHeight();
}
else
e.info.lspc = -2;
}
}
return e;
}
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
Std(font);
unsigned hash = CombineHash(font.GetHashValue(), chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;
}
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
{
if(f.IsReplaced())
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
if(f.IsComposed()) {
f = GetGlyphInfo(font, f.rspc);
if(f.IsComposedLM())
f.rspc += f.width / 2;
}
}
GlyphInfo GetGlyphMetrics(Font font, int chr)
{
GlyphInfo f = GetGlyphInfo(font, chr);
if(f.IsMissing())
f = GetGlyphInfo(font, '?');
GlyphMetrics(f, font, chr);
return f;
}
struct FontEntry {
CommonFontInfo info;
int64 font;
};
thread__ FontEntry fi_cache[64];
const CommonFontInfo& GetFontInfo(Font font)
{
Std(font);
unsigned hash = font.GetHashValue() & 63;
FontEntry& e = fi_cache[hash];
if(e.font != font.AsInt64()) {
DrawLock __;
e.font = font.AsInt64();
e.info = GetFontInfoSys(font);
}
return e.info;
}
int Font::GetWidth(int c) const {
return GetGlyphMetrics(*this, c).width;
}
int Font::GetLeftSpace(int c) const {
return GetGlyphMetrics(*this, c).lspc;
}
int Font::GetRightSpace(int c) const {
return GetGlyphMetrics(*this, c).rspc;
}
thread__ int64 lastFiFont = INT_MIN;
thread__ CommonFontInfo lastFontInfo;
thread__ int64 lastStdFont = INT_MIN;
const CommonFontInfo& Font::Fi() const
{
if(lastStdFont != AStdFont.AsInt64()) {
lastFiFont = INT_MIN;
lastStdFont = AStdFont.AsInt64();
}
if(AsInt64() == lastFiFont)
return lastFontInfo;
lastFontInfo = GetFontInfo(*this);
lastFiFont = AsInt64();
return lastFontInfo;
}
FontInfo Font::Info() const
{
FontInfo h;
h.font = *this;
return h;
}
END_UPP_NAMESPACE
#include "Draw.h"
#define LLOG(x)
NAMESPACE_UPP
CommonFontInfo GetFontInfoSys(Font font);
GlyphInfo GetGlyphInfoSys(Font font, int chr);
void GetStdFontSys(String& name, int& height);
Vector<FaceInfo> GetAllFacesSys();
bool Replace(Font fnt, int chr, Font& rfnt);
void Std(Font& font)
{
if(IsNull(font))
font = StdFont();
if(font.GetFace() == 0)
font.Face(GetStdFont().GetFace());
if(font.GetHeight() == 0)
font.Height(GetStdFont().GetHeight());
}
Size Font::StdFontSize;
Font Font::AStdFont;
INITBLOCK {
RichValue<Font>::Register();
}
const Vector<FaceInfo>& Font::List()
{
static Vector<FaceInfo> *q;
ONCELOCK {
static Vector<FaceInfo> x;
x = GetAllFacesSys();
q = &x;
}
return *q;
}
void sInitFonts()
{
Font::List();
GetStdFont();
}
INITBLOCK {
sInitFonts();
}
int Font::GetFaceCount()
{
return List().GetCount();
}
String Font::GetFaceName(int index)
{
if(index == 0)
return "STDFONT";
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].name;
return Null;
}
dword Font::GetFaceInfo(int index)
{
const Vector<FaceInfo>& l = List();
if(index >= 0 && index < l.GetCount())
return l[index].info;
return 0;
}
int FontFilter(int c)
{
return c >= 'a' && c <= 'z' || c >= '0' && c <= '9' ? c : c >= 'A' && c <= 'Z' ? ToLower(c) : 0;
}
int Font::FindFaceNameIndex(const String& name) {
if(name == "STDFONT")
return 0;
for(int i = 1; i < GetFaceCount(); i++)
if(GetFaceName(i) == name)
return i;
String n = Filter(name, FontFilter);
for(int i = 1; i < GetFaceCount(); i++)
if(Filter(GetFaceName(i), FontFilter) == n)
return i;
return 0;
}
void Font::SyncStdFont()
{
DrawLock __;
StdFontSize = Size(AStdFont.GetAveWidth(), AStdFont().Bold().GetCy());
}
void Font::SetStdFont(Font font)
{
DrawLock __;
static bool x;
InitStdFont();
AStdFont = font;
SyncStdFont();
}
void Font::InitStdFont()
{
ONCELOCK {
DrawLock __;
List();
AStdFont = Arial(12);
String name;
int height = 0;
GetStdFontSys(name, height);
int q = FindFaceNameIndex(name);
if(q > 0) {
AStdFont = Font(q, max(height, 1));
SyncStdFont();
}
}
}
Font Font::GetStdFont()
{
InitStdFont();
return AStdFont;
}
Size Font::GetStdFontSize()
{
InitStdFont();
return StdFontSize;
}
Font StdFont()
{
return Font(0, 0);
}
int Font::GetHeight() const
{
return v.height ? v.height : GetStdFont().GetHeight();
}
String Font::GetFaceName() const {
if(IsNull()) return String();
if(GetFace() == 0)
return "STDFONT";
return GetFaceName(GetFace());
}
dword Font::GetFaceInfo() const {
if(IsNull()) return 0;
return GetFaceInfo(GetFace());
}
Font& Font::FaceName(const String& name) {
int n = FindFaceNameIndex(name);
Face(n < 0 ? 0xffff : n);
return *this;
}
void Font::Serialize(Stream& s) {
int version = 1;
s / version;
if(version >= 1) {
int f = GetFace();
if(f > COURIER)
f = -1;
s / f;
String name;
if(f < 0) {
name = GetFaceName();
s % name;
}
if(s.IsLoading())
if(f >= 0)
Face(f);
else
FaceName(name);
}
else {
String name = GetFaceName();
s % name;
if(s.IsLoading()) {
FaceName(name);
if(IsNull())
Face(COURIER);
}
}
s % v.flags % v.height % v.width;
}
template<>
String AsString(const Font& f) {
if(IsNull(f)) return "<null>";
String s = "<" + f.GetFaceName() + Format(":%d", f.GetHeight());
if(f.IsBold())
s += " Bold";
if(f.IsItalic())
s += " Italic";
if(f.IsUnderline())
s += " Underline";
if(f.IsStrikeout())
s += " Strikeout";
return s + '>';
}
struct CharEntry {
int64 font;
GlyphInfo info;
word chr;
};
CharEntry fc_cache_global[4093];
bool IsNormal(Font font, int chr)
{
DrawLock __;
CharEntry& e = fc_cache_global[CombineHash(font.GetHashValue(), chr) % 4093];
if(e.font == font.AsInt64() || e.chr == chr)
return e.info.IsNormal();
return GetGlyphInfoSys(font, chr).IsNormal();
}
CharEntry GetGlyphEntry(Font font, int chr, unsigned hash)
{
DrawLock __;
CharEntry& e = fc_cache_global[hash % 4093];
if(e.font != font.AsInt64() || e.chr != chr) {
e.font = font.AsInt64();
e.chr = chr;
e.info = GetGlyphInfoSys(font, chr);
if(!e.info.IsNormal()) {
ComposedGlyph cg;
Font rfnt;
if(Compose(font, chr, cg)) {
e.info.lspc = -1;
e.info.rspc = cg.basic_char;
}
else
if(Replace(font, chr, rfnt)) {
e.info.lspc = rfnt.GetFace();
e.info.rspc = rfnt.GetHeight();
}
else
e.info.lspc = -2;
}
}
return e;
}
thread__ CharEntry fc_cache[512];
GlyphInfo GetGlyphInfo(Font font, int chr)
{
Std(font);
unsigned hash = CombineHash(font.GetHashValue(), chr);
CharEntry& e = fc_cache[hash & 511];
if(e.font != font.AsInt64() || e.chr != chr)
e = GetGlyphEntry(font, chr, hash);
return e.info;
}
void GlyphMetrics(GlyphInfo& f, Font font, int chr)
{
if(f.IsReplaced())
f = GetGlyphInfo(font().Face(f.lspc).Height(f.rspc), chr);
if(f.IsComposed()) {
f = GetGlyphInfo(font, f.rspc);
if(f.IsComposedLM())
f.rspc += f.width / 2;
}
}
GlyphInfo GetGlyphMetrics(Font font, int chr)
{
GlyphInfo f = GetGlyphInfo(font, chr);
if(f.IsMissing())
f = GetGlyphInfo(font, '?');
GlyphMetrics(f, font, chr);
return f;
}
struct FontEntry {
CommonFontInfo info;
int64 font;
};
thread__ FontEntry fi_cache[64];
const CommonFontInfo& GetFontInfo(Font font)
{
Std(font);
unsigned hash = font.GetHashValue() & 63;
FontEntry& e = fi_cache[hash];
if(e.font != font.AsInt64()) {
DrawLock __;
e.font = font.AsInt64();
e.info = GetFontInfoSys(font);
}
return e.info;
}
int Font::GetWidth(int c) const {
return GetGlyphMetrics(*this, c).width;
}
int Font::GetLeftSpace(int c) const {
return GetGlyphMetrics(*this, c).lspc;
}
int Font::GetRightSpace(int c) const {
return GetGlyphMetrics(*this, c).rspc;
}
thread__ int64 lastFiFont = INT_MIN;
thread__ CommonFontInfo lastFontInfo;
thread__ int64 lastStdFont = INT_MIN;
const CommonFontInfo& Font::Fi() const
{
if(lastStdFont != AStdFont.AsInt64()) {
lastFiFont = INT_MIN;
lastStdFont = AStdFont.AsInt64();
}
if(AsInt64() == lastFiFont)
return lastFontInfo;
lastFontInfo = GetFontInfo(*this);
lastFiFont = AsInt64();
return lastFontInfo;
}
FontInfo Font::Info() const
{
FontInfo h;
h.font = *this;
return h;
}
END_UPP_NAMESPACE

View file

@ -8,7 +8,7 @@ struct FaceInfo : Moveable<FaceInfo> {
dword info;
};
struct CommonFontInfo : Moveable<CommonFontInfo> {
struct CommonFontInfo {
int ascent;
int descent;
int external;

View file

@ -95,12 +95,6 @@ ImageBuffer::ImageBuffer(Image& img)
Set(img);
}
ImageBuffer::ImageBuffer(ImageDraw& w)
{
Image img = w;
Set(img);
}
ImageBuffer::ImageBuffer(ImageBuffer& b)
{
kind = b.kind;
@ -345,15 +339,6 @@ void Image::Data::PaintOnlyShrink()
}
}
Draw& ImageDraw::Alpha()
{
if(!has_alpha) {
alpha.DrawRect(size, GrayColor(0));
has_alpha = true;
}
return alpha;
}
static void sMultiply(ImageBuffer& b, int (*op)(RGBA *t, const RGBA *s, int len))
{
if(b.GetKind() != IMAGE_OPAQUE && b.GetKind() != IMAGE_EMPTY)

View file

@ -1,334 +1,332 @@
#define NEWIMAGE
enum ImageKind {
IMAGE_UNKNOWN,
IMAGE_EMPTY,
IMAGE_ALPHA,
IMAGE_MASK,
IMAGE_OPAQUE,
};
inline bool operator==(const RGBA& a, const RGBA& b)
{
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}
inline bool operator!=(const RGBA& a, const RGBA& b)
{
return !(a == b);
}
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
void Fill(RGBA *t, const RGBA& src, int n);
void FillColor(RGBA *t, const RGBA& src, int n);
void Copy(RGBA *t, const RGBA *s, int n);
int Premultiply(RGBA *t, const RGBA *s, int len);
int Unmultiply(RGBA *t, const RGBA *s, int len);
void AlphaBlend(RGBA *t, const RGBA *s, int len);
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
int GetChMaskPos32(dword mask);
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
String PackRLE(const RGBA *s, int len);
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
class Image;
class ImageDraw;
class ImageBuffer : NoCopy {
mutable int kind;
Size size;
Buffer<RGBA> pixels;
Point hotspot;
Point spot2;
Size dots;
void Set(Image& img);
void DeepCopy(const ImageBuffer& img);
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
friend class Image;
public:
void SetKind(int k) { kind = k; }
int GetKind() const { return kind; }
int ScanKind() const;
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
void SetHotSpot(Point p) { hotspot = p; }
Point GetHotSpot() const { return hotspot; }
void Set2ndSpot(Point p) { spot2 = p; }
Point Get2ndSpot() const { return spot2; }
void SetDots(Size sz) { dots = sz; }
Size GetDots() const { return dots; }
Size GetSize() const { return size; }
int GetWidth() const { return size.cx; }
int GetHeight() const { return size.cy; }
int GetLength() const { return size.cx * size.cy; }
RGBA *operator[](int i) { return Line(i); }
const RGBA *operator[](int i) const { return Line(i); }
RGBA *operator~() { return pixels; }
operator RGBA*() { return pixels; }
const RGBA *operator~() const { return pixels; }
operator const RGBA*() const { return pixels; }
void Create(int cx, int cy);
void Create(Size sz) { Create(sz.cx, sz.cy); }
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
void Clear() { Create(0, 0); }
void operator=(Image& img);
void operator=(ImageBuffer& img);
ImageBuffer() { Create(0, 0); }
ImageBuffer(int cx, int cy) { Create(cx, cy); }
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
ImageBuffer(Image& img);
ImageBuffer(ImageDraw& w);
ImageBuffer(ImageBuffer& b);
};
void Premultiply(ImageBuffer& b);
void Unmultiply(ImageBuffer& b);
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
private:
struct Data : Link<Data> {
Atomic refcount;
int64 serial;
int paintcount;
static Link<Data> ResData[1];
static int ResCount;
void Retain() { AtomicInc(refcount); }
void Release() { if(AtomicDec(refcount) == 0) delete this; }
struct SystemData;
void *system_buffer[6];
SystemData& Sys() const;
int GetResCount() const;
#ifdef PLATFORM_WIN32
void CreateHBMP(HDC dc, const RGBA *data);
#endif
ImageBuffer buffer;
bool paintonly;
void SysInit();
void SysRelease();
int GetKind();
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
void PaintOnlyShrink();
Data(ImageBuffer& b);
~Data();
};
Data *data;
static Link<Image::Data> ResData[1];
static int ResCount;
void Set(ImageBuffer& b);
friend class ImageBuffer;
friend struct Data;
friend class SystemDraw;
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
friend void SetPaintOnly___(Image& m);
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
#ifdef PLATFORM_WIN32
#ifndef PLATFORM_WINCE
void SetCursorCheat(LPCSTR id);
LPCSTR GetCursorCheat() const;
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
friend HICON IconWin32(const Image& img, bool cursor);
#endif
#endif
#ifdef PLATFORM_X11
void SetCursorCheat(int id);
int GetCursorCheat() const;
friend Cursor X11Cursor(const Image&);
friend Image sX11Cursor__(int c);
#endif
public:
const RGBA* operator~() const;
operator const RGBA*() const;
const RGBA* operator[](int i) const;
Size GetSize() const;
int GetWidth() const { return GetSize().cx; }
int GetHeight() const { return GetSize().cy; }
int GetLength() const;
Point GetHotSpot() const;
Point Get2ndSpot() const;
Size GetDots() const;
int GetKindNoScan() const;
int GetKind() const;
int64 GetSerialId() const { return data ? data->serial : 0; }
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
bool operator==(const Image& img) const;
bool operator!=(const Image& img) const;
dword GetHashValue() const;
String ToString() const;
void Serialize(Stream& s);
void Clear();
Image& operator=(const Image& img);
Image& operator=(ImageBuffer& img);
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
bool IsEmpty() const { return IsNullInstance(); }
operator Value() const { return RichValue<Image>(*this); }
Image() { data = NULL; }
Image(const Nuller&) { data = NULL; }
Image(const Value& src);
Image(const Image& img);
Image(Image (*fn)());
Image(ImageBuffer& b);
~Image();
static Image Arrow();
static Image Wait();
static Image IBeam();
static Image No();
static Image SizeAll();
static Image SizeHorz();
static Image SizeVert();
static Image SizeTopLeft();
static Image SizeTop();
static Image SizeTopRight();
static Image SizeLeft();
static Image SizeRight();
static Image SizeBottomLeft();
static Image SizeBottom();
static Image SizeBottomRight();
static Image Cross();
static Image Hand();
// IML support ("private"), deprecated - legacy .iml
struct Init {
const char *const *scans;
int16 scan_count;
char info[24];
};
explicit Image(const Init& init);
};
Image Premultiply(const Image& img);
Image Unmultiply(const Image& img);
Vector<Image> UnpackImlData(const void *ptr, int len);
Vector<Image> UnpackImlData(const String& d);
class Iml {
struct IImage : Moveable<IImage> {
bool loaded;
Image image;
IImage() { loaded = false; }
};
struct Data : Moveable<Data> {
const char *data;
int len, count;
};
Vector<Data> data;
VectorMap<String, IImage> map;
const Image::Init *img_init;
const char **name;
bool premultiply;
void Init(int n);
public:
void Enter();
void Leave();
void Reset();
int GetCount() const { return map.GetCount(); }
String GetId(int i) { return map.GetKey(i); }
Image Get(int i);
int Find(const String& s) const { return map.Find(s); }
void Set(int i, const Image& img);
void Premultiplied() { premultiply = false; }
#ifdef _DEBUG
int GetBinSize() const;
#endif
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
void AddData(const byte *data, int len, int count);
};
void Register(const char *imageclass, Iml& iml);
int GetImlCount();
String GetImlName(int i);
Iml& GetIml(int i);
int FindIml(const char *name);
Image GetImlImage(const char *name);
void SetImlImage(const char *name, const Image& m);
String StoreImageAsString(const Image& img);
Image LoadImageFromString(const String& s);
Size GetImageStringSize(const String& src);
Size GetImageStringDots(const String& src);
#include "Raster.h"
#include "ImageOp.h"
#ifdef PLATFORM_WIN32
#ifndef PLATFORM_WINCE
Image Win32Icon(LPCSTR id, int iconsize = 0);
Image Win32Icon(int id, int iconsize = 0);
Image Win32Cursor(LPCSTR id);
Image Win32Cursor(int id);
HICON IconWin32(const Image& img, bool cursor = false);
Image Win32DllIcon(const char *dll, int ii, bool large);
#endif
#endif
#ifdef PLATFORM_X11
Cursor X11Cursor(const Image& img);
#endif
#define NEWIMAGE
enum ImageKind {
IMAGE_UNKNOWN,
IMAGE_EMPTY,
IMAGE_ALPHA,
IMAGE_MASK,
IMAGE_OPAQUE,
};
inline bool operator==(const RGBA& a, const RGBA& b)
{
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}
inline bool operator!=(const RGBA& a, const RGBA& b)
{
return !(a == b);
}
inline RGBA RGBAZero() { RGBA c; c.r = c.g = c.b = c.a = 0; return c; }
void Fill(RGBA *t, const RGBA& src, int n);
void FillColor(RGBA *t, const RGBA& src, int n);
void Copy(RGBA *t, const RGBA *s, int n);
int Premultiply(RGBA *t, const RGBA *s, int len);
int Unmultiply(RGBA *t, const RGBA *s, int len);
void AlphaBlend(RGBA *t, const RGBA *s, int len);
void AlphaBlend(RGBA *t, const RGBA *s, int len, Color color);
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len, Color color);
void AlphaBlendOpaque(RGBA *t, const RGBA *s, int len);
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len);
void AlphaBlendStraight(RGBA *b, const RGBA *f, int len, Color color);
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len);
void AlphaBlendStraightOpaque(RGBA *t, const RGBA *s, int len, int alpha);
int GetChMaskPos32(dword mask);
void AlphaBlendOverBgST(RGBA *b, RGBA bg, int len);
const byte *UnpackRLE(RGBA *t, const byte *src, int len);
String PackRLE(const RGBA *s, int len);
inline int Grayscale(int r, int g, int b) { return (77 * r + 151 * g + 28 * b) >> 8; }
inline int Grayscale(const RGBA& c) { return Grayscale(c.r, c.g, c.b); }
inline byte Saturate255(int x) { return byte(~(x >> 24) & (x | (-(x >> 8) >> 24)) & 0xff); }
class Image;
class ImageBuffer : NoCopy {
mutable int kind;
Size size;
Buffer<RGBA> pixels;
Point hotspot;
Point spot2;
Size dots;
void Set(Image& img);
void DeepCopy(const ImageBuffer& img);
RGBA* Line(int i) const { ASSERT(i >= 0 && i < size.cy); return (RGBA *)~pixels + i * size.cx; }
friend void DropPixels___(ImageBuffer& b) { b.pixels.Clear(); }
friend class Image;
public:
void SetKind(int k) { kind = k; }
int GetKind() const { return kind; }
int ScanKind() const;
int GetScanKind() const { return kind == IMAGE_UNKNOWN ? ScanKind() : kind; }
void SetHotSpot(Point p) { hotspot = p; }
Point GetHotSpot() const { return hotspot; }
void Set2ndSpot(Point p) { spot2 = p; }
Point Get2ndSpot() const { return spot2; }
void SetDots(Size sz) { dots = sz; }
Size GetDots() const { return dots; }
Size GetSize() const { return size; }
int GetWidth() const { return size.cx; }
int GetHeight() const { return size.cy; }
int GetLength() const { return size.cx * size.cy; }
RGBA *operator[](int i) { return Line(i); }
const RGBA *operator[](int i) const { return Line(i); }
RGBA *operator~() { return pixels; }
operator RGBA*() { return pixels; }
const RGBA *operator~() const { return pixels; }
operator const RGBA*() const { return pixels; }
void Create(int cx, int cy);
void Create(Size sz) { Create(sz.cx, sz.cy); }
bool IsEmpty() const { return (size.cx | size.cy) == 0; }
void Clear() { Create(0, 0); }
void operator=(Image& img);
void operator=(ImageBuffer& img);
ImageBuffer() { Create(0, 0); }
ImageBuffer(int cx, int cy) { Create(cx, cy); }
ImageBuffer(Size sz) { Create(sz.cx, sz.cy); }
ImageBuffer(Image& img);
ImageBuffer(ImageBuffer& b);
};
void Premultiply(ImageBuffer& b);
void Unmultiply(ImageBuffer& b);
void SetSurface(Draw& w, int x, int y, int cx, int cy, const RGBA *pixels);
class Image : public AssignValueTypeNo< Image, 150, Moveable<Image> > {
private:
struct Data : Link<Data> {
Atomic refcount;
int64 serial;
int paintcount;
static Link<Data> ResData[1];
static int ResCount;
void Retain() { AtomicInc(refcount); }
void Release() { if(AtomicDec(refcount) == 0) delete this; }
struct SystemData;
void *system_buffer[6];
SystemData& Sys() const;
int GetResCount() const;
#ifdef PLATFORM_WIN32
void CreateHBMP(HDC dc, const RGBA *data);
#endif
ImageBuffer buffer;
bool paintonly;
void SysInit();
void SysRelease();
int GetKind();
void Paint(SystemDraw& w, int x, int y, const Rect& src, Color c);
void PaintOnlyShrink();
Data(ImageBuffer& b);
~Data();
};
Data *data;
static Link<Image::Data> ResData[1];
static int ResCount;
void Set(ImageBuffer& b);
friend class ImageBuffer;
friend struct Data;
friend class SystemDraw;
void PaintImage(SystemDraw& w, int x, int y, const Rect& src, Color c) const;
friend void SetPaintOnly___(Image& m);
friend void DrawImageBandRLE(Draw& w, int x, int y, const Image& m, int minp);
#ifdef PLATFORM_WIN32
#ifndef PLATFORM_WINCE
void SetCursorCheat(LPCSTR id);
LPCSTR GetCursorCheat() const;
friend Image Win32IconCursor(LPCSTR id, int iconsize, bool cursor);
friend HICON IconWin32(const Image& img, bool cursor);
#endif
#endif
#ifdef PLATFORM_X11
void SetCursorCheat(int id);
int GetCursorCheat() const;
friend Cursor X11Cursor(const Image&);
friend Image sX11Cursor__(int c);
#endif
public:
const RGBA* operator~() const;
operator const RGBA*() const;
const RGBA* operator[](int i) const;
Size GetSize() const;
int GetWidth() const { return GetSize().cx; }
int GetHeight() const { return GetSize().cy; }
int GetLength() const;
Point GetHotSpot() const;
Point Get2ndSpot() const;
Size GetDots() const;
int GetKindNoScan() const;
int GetKind() const;
int64 GetSerialId() const { return data ? data->serial : 0; }
bool IsSame(const Image& img) const { return GetSerialId() == img.GetSerialId(); }
bool operator==(const Image& img) const;
bool operator!=(const Image& img) const;
dword GetHashValue() const;
String ToString() const;
void Serialize(Stream& s);
void Clear();
Image& operator=(const Image& img);
Image& operator=(ImageBuffer& img);
bool IsNullInstance() const { Size sz = GetSize(); return (sz.cx|sz.cy) == 0; }
bool IsEmpty() const { return IsNullInstance(); }
operator Value() const { return RichValue<Image>(*this); }
Image() { data = NULL; }
Image(const Nuller&) { data = NULL; }
Image(const Value& src);
Image(const Image& img);
Image(Image (*fn)());
Image(ImageBuffer& b);
~Image();
static Image Arrow();
static Image Wait();
static Image IBeam();
static Image No();
static Image SizeAll();
static Image SizeHorz();
static Image SizeVert();
static Image SizeTopLeft();
static Image SizeTop();
static Image SizeTopRight();
static Image SizeLeft();
static Image SizeRight();
static Image SizeBottomLeft();
static Image SizeBottom();
static Image SizeBottomRight();
static Image Cross();
static Image Hand();
// IML support ("private"), deprecated - legacy .iml
struct Init {
const char *const *scans;
int16 scan_count;
char info[24];
};
explicit Image(const Init& init);
};
Image Premultiply(const Image& img);
Image Unmultiply(const Image& img);
Vector<Image> UnpackImlData(const void *ptr, int len);
Vector<Image> UnpackImlData(const String& d);
class Iml {
struct IImage : Moveable<IImage> {
bool loaded;
Image image;
IImage() { loaded = false; }
};
struct Data : Moveable<Data> {
const char *data;
int len, count;
};
Vector<Data> data;
VectorMap<String, IImage> map;
const Image::Init *img_init;
const char **name;
bool premultiply;
void Init(int n);
public:
void Enter();
void Leave();
void Reset();
int GetCount() const { return map.GetCount(); }
String GetId(int i) { return map.GetKey(i); }
Image Get(int i);
int Find(const String& s) const { return map.Find(s); }
void Set(int i, const Image& img);
void Premultiplied() { premultiply = false; }
#ifdef _DEBUG
int GetBinSize() const;
#endif
Iml(const Image::Init *img_init, const char **name, int n);//Deprecated - legacy .iml
void AddData(const byte *data, int len, int count);
};
void Register(const char *imageclass, Iml& iml);
int GetImlCount();
String GetImlName(int i);
Iml& GetIml(int i);
int FindIml(const char *name);
Image GetImlImage(const char *name);
void SetImlImage(const char *name, const Image& m);
String StoreImageAsString(const Image& img);
Image LoadImageFromString(const String& s);
Size GetImageStringSize(const String& src);
Size GetImageStringDots(const String& src);
#include "Raster.h"
#include "ImageOp.h"
#ifdef PLATFORM_WIN32
#ifndef PLATFORM_WINCE
Image Win32Icon(LPCSTR id, int iconsize = 0);
Image Win32Icon(int id, int iconsize = 0);
Image Win32Cursor(LPCSTR id);
Image Win32Cursor(int id);
HICON IconWin32(const Image& img, bool cursor = false);
Image Win32DllIcon(const char *dll, int ii, bool large);
#endif
#endif
#ifdef PLATFORM_X11
Cursor X11Cursor(const Image& img);
#endif

View file

@ -718,11 +718,9 @@ void RichPara::Dump()
String RichPara::CharFormat::ToString() const
{
String out;
out
<< Font(*this)
<< ", ink " << DumpColor(ink);
out << Font(*this) << ", ink " << ink;
if(!UPP::IsNull(paper))
out << ", paper " << DumpColor(paper);
out << ", paper " << paper;
switch(sscript)
{
case 0: break;
@ -730,7 +728,7 @@ String RichPara::CharFormat::ToString() const
case 2: out << ", subscript"; break;
default: out << ", sscript(" << (int)sscript << ")"; break;
}
out << ", lang " << DumpLanguage(language);
out << ", lang " << LNGAsText(language);
if(!UPP::IsNull(link))
out << ", link " << link;
if(capitals)
@ -746,7 +744,7 @@ String RichPara::Format::ToString() const
if(!UPP::IsNull(label))
out << "label <" << label << ">: ";
out
<< DumpAlign(align) << ", left " << lm << ", right " << rm
<< align << ", left " << lm << ", right " << rm
<< ", indent " << indent << ", before " << before << ", after " << after
<< ", tabsize " << tabsize << ", bullet " << bullet
<< (newpage ? ", newpage" : "")
@ -756,7 +754,7 @@ String RichPara::Format::ToString() const
int i;
for(i = 0; i < tab.GetCount(); i++)
out << (i ? "\n" : ", ")
<< "tab[" << i << "] = " << tab[i].pos << ", align " << DumpAlign(tab[i].align)
<< "tab[" << i << "] = " << tab[i].pos << ", align " << tab[i].align
<< ", fill " << FormatIntHex(tab[i].fillchar, 2);
out << "\n";
out << "before_number " << before_number << ", after_number " << after_number