mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
developing new draw
git-svn-id: svn://ultimatepp.org/upp/trunk@1372 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
7ae5221acb
commit
04a06f8ce7
74 changed files with 3278 additions and 3431 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#include "Draw.h"
|
||||
#include "SystemDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef CTRLCORE_H
|
||||
#define CTRLCORE_H
|
||||
|
||||
#include <Draw/Draw.h>
|
||||
#include "SystemDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "Draw.h"
|
||||
#include "SystemDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
1719
uppsrc/Draw/Draw.h
1719
uppsrc/Draw/Draw.h
File diff suppressed because it is too large
Load diff
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ struct FaceInfo : Moveable<FaceInfo> {
|
|||
dword info;
|
||||
};
|
||||
|
||||
struct CommonFontInfo : Moveable<CommonFontInfo> {
|
||||
struct CommonFontInfo {
|
||||
int ascent;
|
||||
int descent;
|
||||
int external;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue