~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Externals/wxWidgets3/src/gtk/region.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
// Name:        src/gtk/region.cpp
 
3
// Purpose:
 
4
// Author:      Robert Roebling
 
5
// Modified:    VZ at 05.10.00: use AllocExclusive(), comparison fixed
 
6
// Copyright:   (c) 1998 Robert Roebling
 
7
// Licence:     wxWindows licence
 
8
/////////////////////////////////////////////////////////////////////////////
 
9
 
 
10
// ============================================================================
 
11
// declarations
 
12
// ============================================================================
 
13
 
 
14
// ----------------------------------------------------------------------------
 
15
// headers
 
16
// ----------------------------------------------------------------------------
 
17
 
 
18
// For compilers that support precompilation, includes "wx.h".
 
19
#include "wx/wxprec.h"
 
20
 
 
21
#include "wx/region.h"
 
22
 
 
23
#include <gdk/gdk.h>
 
24
 
 
25
// ----------------------------------------------------------------------------
 
26
// wxRegionRefData: private class containing the information about the region
 
27
// ----------------------------------------------------------------------------
 
28
 
 
29
class wxRegionRefData : public wxGDIRefData
 
30
{
 
31
public:
 
32
    wxRegionRefData()
 
33
    {
 
34
        m_region = NULL;
 
35
    }
 
36
 
 
37
    wxRegionRefData(const wxRegionRefData& refData)
 
38
        : wxGDIRefData()
 
39
    {
 
40
#ifdef __WXGTK3__
 
41
        m_region = cairo_region_copy(refData.m_region);
 
42
#else
 
43
        m_region = gdk_region_copy(refData.m_region);
 
44
#endif
 
45
    }
 
46
 
 
47
    virtual ~wxRegionRefData()
 
48
    {
 
49
        if (m_region)
 
50
        {
 
51
#ifdef __WXGTK3__
 
52
            cairo_region_destroy(m_region);
 
53
#else
 
54
            gdk_region_destroy( m_region );
 
55
#endif
 
56
        }
 
57
    }
 
58
 
 
59
#ifdef __WXGTK3__
 
60
    cairo_region_t* m_region;
 
61
#else
 
62
    GdkRegion  *m_region;
 
63
#endif
 
64
};
 
65
 
 
66
// ----------------------------------------------------------------------------
 
67
// macros
 
68
// ----------------------------------------------------------------------------
 
69
 
 
70
#define M_REGIONDATA static_cast<wxRegionRefData*>(m_refData)
 
71
#define M_REGIONDATA_OF(r) static_cast<wxRegionRefData*>(r.m_refData)
 
72
 
 
73
IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
 
74
IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
 
75
 
 
76
// ----------------------------------------------------------------------------
 
77
// wxRegion construction
 
78
// ----------------------------------------------------------------------------
 
79
 
 
80
void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
 
81
{
 
82
    GdkRectangle rect;
 
83
    rect.x = x;
 
84
    rect.y = y;
 
85
    rect.width = w;
 
86
    rect.height = h;
 
87
 
 
88
    m_refData = new wxRegionRefData();
 
89
 
 
90
#ifdef __WXGTK3__
 
91
    M_REGIONDATA->m_region = cairo_region_create_rectangle(&rect);
 
92
#else
 
93
    M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
 
94
#endif
 
95
}
 
96
 
 
97
#ifndef __WXGTK3__
 
98
wxRegion::wxRegion(const GdkRegion* region)
 
99
{
 
100
    m_refData = new wxRegionRefData();
 
101
    M_REGIONDATA->m_region = gdk_region_copy(const_cast<GdkRegion*>(region));
 
102
}
 
103
#endif
 
104
 
 
105
wxRegion::wxRegion( size_t n, const wxPoint *points,
 
106
                    wxPolygonFillMode fillStyle )
 
107
{
 
108
#ifdef __WXGTK3__
 
109
    // Make a cairo path from the points, draw it onto an image surface, use
 
110
    // gdk_cairo_region_create_from_surface() to get a cairo region
 
111
 
 
112
    // need at least 3 points to make a useful polygon
 
113
    if (n < 3)
 
114
        return;
 
115
    // get bounding rect
 
116
    int min_x = points[0].x;
 
117
    int max_x = min_x;
 
118
    int min_y = points[0].y;
 
119
    int max_y = min_y;
 
120
    size_t i;
 
121
    for (i = 1; i < n; i++)
 
122
    {
 
123
        const int x = points[i].x;
 
124
        if (min_x > x)
 
125
            min_x = x;
 
126
        else if (max_x < x)
 
127
            max_x = x;
 
128
        const int y = points[i].y;
 
129
        if (min_y > y)
 
130
            min_y = y;
 
131
        else if (max_y < y)
 
132
            max_y = y;
 
133
    }
 
134
    const int w = max_x - min_x + 1;
 
135
    const int h = max_y - min_y + 1;
 
136
    // make surface just big enough to contain polygon (A1 is native format
 
137
    //   for gdk_cairo_region_create_from_surface)
 
138
    cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_A1, w, h);
 
139
    memset(cairo_image_surface_get_data(surface), 0, cairo_image_surface_get_stride(surface) * h);
 
140
    cairo_surface_mark_dirty(surface);
 
141
    cairo_surface_set_device_offset(surface, -min_x, -min_y);
 
142
    cairo_t* cr = cairo_create(surface);
 
143
    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
 
144
    if (fillStyle == wxODDEVEN_RULE)
 
145
        cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
 
146
    // make path
 
147
    cairo_move_to(cr, points[0].x, points[0].y);
 
148
    for (i = 1; i < n; i++)
 
149
        cairo_line_to(cr, points[i].x, points[i].y);
 
150
    cairo_close_path(cr);
 
151
    cairo_fill(cr);
 
152
    cairo_destroy(cr);
 
153
    cairo_surface_flush(surface);
 
154
    m_refData = new wxRegionRefData;
 
155
    M_REGIONDATA->m_region = gdk_cairo_region_create_from_surface(surface);
 
156
    cairo_surface_destroy(surface);
 
157
#else
 
158
    GdkPoint *gdkpoints = new GdkPoint[n];
 
159
    for ( size_t i = 0 ; i < n ; i++ )
 
160
    {
 
161
        gdkpoints[i].x = points[i].x;
 
162
        gdkpoints[i].y = points[i].y;
 
163
    }
 
164
 
 
165
    m_refData = new wxRegionRefData();
 
166
 
 
167
    GdkRegion* reg = gdk_region_polygon
 
168
                     (
 
169
                        gdkpoints,
 
170
                        n,
 
171
                        fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
 
172
                                                    : GDK_EVEN_ODD_RULE
 
173
                     );
 
174
 
 
175
    M_REGIONDATA->m_region = reg;
 
176
 
 
177
    delete [] gdkpoints;
 
178
#endif
 
179
}
 
180
 
 
181
wxRegion::~wxRegion()
 
182
{
 
183
    // m_refData unrefed in ~wxObject
 
184
}
 
185
 
 
186
wxGDIRefData *wxRegion::CreateGDIRefData() const
 
187
{
 
188
    // should never be called
 
189
    wxFAIL;
 
190
    return NULL;
 
191
}
 
192
 
 
193
wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
 
194
{
 
195
    return new wxRegionRefData(*static_cast<const wxRegionRefData*>(data));
 
196
}
 
197
 
 
198
// ----------------------------------------------------------------------------
 
199
// wxRegion comparison
 
200
// ----------------------------------------------------------------------------
 
201
 
 
202
bool wxRegion::DoIsEqual(const wxRegion& region) const
 
203
{
 
204
#ifdef __WXGTK3__
 
205
    return cairo_region_equal(
 
206
        M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region);
 
207
#else
 
208
    return gdk_region_equal(M_REGIONDATA->m_region,
 
209
                            M_REGIONDATA_OF(region)->m_region) != 0;
 
210
#endif
 
211
}
 
212
 
 
213
// ----------------------------------------------------------------------------
 
214
// wxRegion operations
 
215
// ----------------------------------------------------------------------------
 
216
 
 
217
void wxRegion::Clear()
 
218
{
 
219
    UnRef();
 
220
}
 
221
 
 
222
bool wxRegion::DoUnionWithRect(const wxRect& r)
 
223
{
 
224
    // workaround for a strange GTK/X11 bug: taking union with an empty
 
225
    // rectangle results in an empty region which is definitely not what we
 
226
    // want
 
227
    if ( r.IsEmpty() )
 
228
        return true;
 
229
 
 
230
    if ( !m_refData )
 
231
    {
 
232
        InitRect(r.x, r.y, r.width, r.height);
 
233
    }
 
234
    else
 
235
    {
 
236
        AllocExclusive();
 
237
 
 
238
        GdkRectangle rect;
 
239
        rect.x = r.x;
 
240
        rect.y = r.y;
 
241
        rect.width = r.width;
 
242
        rect.height = r.height;
 
243
 
 
244
#ifdef __WXGTK3__
 
245
        cairo_region_union_rectangle(M_REGIONDATA->m_region, &rect);
 
246
#else
 
247
        gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
 
248
#endif
 
249
    }
 
250
 
 
251
    return true;
 
252
}
 
253
 
 
254
bool wxRegion::DoUnionWithRegion( const wxRegion& region )
 
255
{
 
256
    if (region.m_refData == NULL)
 
257
        { }
 
258
    else if (m_refData == NULL)
 
259
    {
 
260
        m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
 
261
    }
 
262
    else
 
263
    {
 
264
        AllocExclusive();
 
265
#ifdef __WXGTK3__
 
266
        cairo_region_union(M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region);
 
267
#else
 
268
        gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
 
269
#endif
 
270
    }
 
271
 
 
272
    return true;
 
273
}
 
274
 
 
275
bool wxRegion::DoIntersect( const wxRegion& region )
 
276
{
 
277
    if (region.m_refData == NULL || m_refData == NULL)
 
278
        return false;
 
279
 
 
280
    AllocExclusive();
 
281
 
 
282
#ifdef __WXGTK3__
 
283
    cairo_region_intersect(M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region);
 
284
#else
 
285
    gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
 
286
#endif
 
287
 
 
288
    return true;
 
289
}
 
290
 
 
291
bool wxRegion::DoSubtract( const wxRegion& region )
 
292
{
 
293
    if (region.m_refData == NULL || m_refData == NULL)
 
294
        return false;
 
295
 
 
296
    AllocExclusive();
 
297
 
 
298
#ifdef __WXGTK3__
 
299
    cairo_region_subtract(M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region);
 
300
#else
 
301
    gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
 
302
#endif
 
303
 
 
304
    return true;
 
305
}
 
306
 
 
307
bool wxRegion::DoXor( const wxRegion& region )
 
308
{
 
309
    if (region.m_refData == NULL)
 
310
        { }
 
311
    else if (m_refData == NULL)
 
312
    {
 
313
        // XOR-ing with an invalid region is the same as XOR-ing with an empty
 
314
        // one, i.e. it is simply a copy.
 
315
        m_refData = new wxRegionRefData(*M_REGIONDATA_OF(region));
 
316
    }
 
317
    else
 
318
    {
 
319
        AllocExclusive();
 
320
 
 
321
#ifdef __WXGTK3__
 
322
        cairo_region_xor(M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region);
 
323
#else
 
324
        gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
 
325
#endif
 
326
    }
 
327
 
 
328
    return true;
 
329
}
 
330
 
 
331
bool wxRegion::DoOffset( wxCoord x, wxCoord y )
 
332
{
 
333
    wxCHECK_MSG( m_refData, false, wxS("invalid region") );
 
334
 
 
335
    AllocExclusive();
 
336
 
 
337
#ifdef __WXGTK3__
 
338
    cairo_region_translate(M_REGIONDATA->m_region, x, y);
 
339
#else
 
340
    gdk_region_offset( M_REGIONDATA->m_region, x, y );
 
341
#endif
 
342
 
 
343
    return true;
 
344
}
 
345
 
 
346
// ----------------------------------------------------------------------------
 
347
// wxRegion tests
 
348
// ----------------------------------------------------------------------------
 
349
 
 
350
bool wxRegion::DoGetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
 
351
{
 
352
    if ( m_refData )
 
353
    {
 
354
        GdkRectangle rect;
 
355
#ifdef __WXGTK3__
 
356
        cairo_region_get_extents(M_REGIONDATA->m_region, &rect);
 
357
#else
 
358
        gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
 
359
#endif
 
360
        x = rect.x;
 
361
        y = rect.y;
 
362
        w = rect.width;
 
363
        h = rect.height;
 
364
 
 
365
        return true;
 
366
    }
 
367
    else
 
368
    {
 
369
        x = 0;
 
370
        y = 0;
 
371
        w = -1;
 
372
        h = -1;
 
373
 
 
374
        return false;
 
375
    }
 
376
}
 
377
 
 
378
bool wxRegion::IsEmpty() const
 
379
{
 
380
#ifdef __WXGTK3__
 
381
    return m_refData == NULL || cairo_region_is_empty(M_REGIONDATA->m_region);
 
382
#else
 
383
    return m_refData == NULL || gdk_region_empty(M_REGIONDATA->m_region);
 
384
#endif
 
385
}
 
386
 
 
387
wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
 
388
{
 
389
#ifdef __WXGTK3__
 
390
    if (m_refData == NULL || !cairo_region_contains_point(M_REGIONDATA->m_region, x, y))
 
391
#else
 
392
    if (m_refData == NULL || !gdk_region_point_in(M_REGIONDATA->m_region, x, y))
 
393
#endif
 
394
        return wxOutRegion;
 
395
 
 
396
    return wxInRegion;
 
397
}
 
398
 
 
399
wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
 
400
{
 
401
    if (!m_refData)
 
402
        return wxOutRegion;
 
403
 
 
404
    GdkRectangle rect;
 
405
    rect.x = r.x;
 
406
    rect.y = r.y;
 
407
    rect.width = r.width;
 
408
    rect.height = r.height;
 
409
#ifdef __WXGTK3__
 
410
    switch (cairo_region_contains_rectangle(M_REGIONDATA->m_region, &rect))
 
411
    {
 
412
        case CAIRO_REGION_OVERLAP_IN:   return wxInRegion;
 
413
        case CAIRO_REGION_OVERLAP_PART: return wxPartRegion;
 
414
        default: break;
 
415
    }
 
416
#else
 
417
    GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
 
418
    switch (res)
 
419
    {
 
420
        case GDK_OVERLAP_RECTANGLE_IN:   return wxInRegion;
 
421
        case GDK_OVERLAP_RECTANGLE_OUT:  return wxOutRegion;
 
422
        case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
 
423
    }
 
424
#endif
 
425
    return wxOutRegion;
 
426
}
 
427
 
 
428
#ifdef __WXGTK3__
 
429
cairo_region_t* wxRegion::GetRegion() const
 
430
#else
 
431
GdkRegion *wxRegion::GetRegion() const
 
432
#endif
 
433
{
 
434
    if (!m_refData)
 
435
        return NULL;
 
436
 
 
437
    return M_REGIONDATA->m_region;
 
438
}
 
439
 
 
440
// ----------------------------------------------------------------------------
 
441
// wxRegionIterator
 
442
// ----------------------------------------------------------------------------
 
443
 
 
444
wxRegionIterator::wxRegionIterator()
 
445
{
 
446
    Init();
 
447
    Reset();
 
448
}
 
449
 
 
450
wxRegionIterator::wxRegionIterator( const wxRegion& region )
 
451
{
 
452
    Init();
 
453
    Reset(region);
 
454
}
 
455
 
 
456
void wxRegionIterator::Init()
 
457
{
 
458
    m_rects = NULL;
 
459
    m_numRects = 0;
 
460
}
 
461
 
 
462
wxRegionIterator::~wxRegionIterator()
 
463
{
 
464
    wxDELETEA(m_rects);
 
465
}
 
466
 
 
467
void wxRegionIterator::CreateRects( const wxRegion& region )
 
468
{
 
469
    wxDELETEA(m_rects);
 
470
    m_numRects = 0;
 
471
 
 
472
#ifdef __WXGTK3__
 
473
    cairo_region_t* cairoRegion = region.GetRegion();
 
474
    if (cairoRegion == NULL)
 
475
        return;
 
476
    m_numRects = cairo_region_num_rectangles(cairoRegion);
 
477
     
 
478
    if (m_numRects)
 
479
    {
 
480
        m_rects = new wxRect[m_numRects];
 
481
        for (int i = 0; i < m_numRects; i++)
 
482
        {
 
483
            GdkRectangle gr;
 
484
            cairo_region_get_rectangle(cairoRegion, i, &gr);
 
485
            wxRect &wr = m_rects[i];
 
486
            wr.x = gr.x;
 
487
            wr.y = gr.y;
 
488
            wr.width = gr.width;
 
489
            wr.height = gr.height;
 
490
        }
 
491
    }
 
492
#else
 
493
    GdkRegion *gdkregion = region.GetRegion();
 
494
    if (!gdkregion)
 
495
        return;
 
496
 
 
497
    GdkRectangle* gdkrects;
 
498
    gdk_region_get_rectangles(gdkregion, &gdkrects, &m_numRects);
 
499
 
 
500
    if (m_numRects)
 
501
    {
 
502
        m_rects = new wxRect[m_numRects];
 
503
        for (int i = 0; i < m_numRects; ++i)
 
504
        {
 
505
            GdkRectangle &gr = gdkrects[i];
 
506
            wxRect &wr = m_rects[i];
 
507
            wr.x = gr.x;
 
508
            wr.y = gr.y;
 
509
            wr.width = gr.width;
 
510
            wr.height = gr.height;
 
511
        }
 
512
    }
 
513
    g_free( gdkrects );
 
514
#endif
 
515
}
 
516
 
 
517
void wxRegionIterator::Reset( const wxRegion& region )
 
518
{
 
519
    m_region = region;
 
520
    CreateRects(region);
 
521
    Reset();
 
522
}
 
523
 
 
524
bool wxRegionIterator::HaveRects() const
 
525
{
 
526
    return m_current < m_numRects;
 
527
}
 
528
 
 
529
wxRegionIterator& wxRegionIterator::operator ++ ()
 
530
{
 
531
    if (HaveRects())
 
532
        ++m_current;
 
533
 
 
534
    return *this;
 
535
}
 
536
 
 
537
wxRegionIterator wxRegionIterator::operator ++ (int)
 
538
{
 
539
    wxRegionIterator tmp = *this;
 
540
 
 
541
    if (HaveRects())
 
542
        ++m_current;
 
543
 
 
544
    return tmp;
 
545
}
 
546
 
 
547
wxCoord wxRegionIterator::GetX() const
 
548
{
 
549
    wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
 
550
 
 
551
    return m_rects[m_current].x;
 
552
}
 
553
 
 
554
wxCoord wxRegionIterator::GetY() const
 
555
{
 
556
    wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
 
557
 
 
558
    return m_rects[m_current].y;
 
559
}
 
560
 
 
561
wxCoord wxRegionIterator::GetW() const
 
562
{
 
563
    wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
 
564
 
 
565
    return m_rects[m_current].width;
 
566
}
 
567
 
 
568
wxCoord wxRegionIterator::GetH() const
 
569
{
 
570
    wxCHECK_MSG( HaveRects(), 0, wxT("invalid wxRegionIterator") );
 
571
 
 
572
    return m_rects[m_current].height;
 
573
}
 
574
 
 
575
wxRect wxRegionIterator::GetRect() const
 
576
{
 
577
    wxRect r;
 
578
    if( HaveRects() )
 
579
        r = m_rects[m_current];
 
580
 
 
581
    return r;
 
582
}
 
583
 
 
584
wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
 
585
{
 
586
    if (this != &ri)
 
587
    {
 
588
        wxDELETEA(m_rects);
 
589
 
 
590
        m_current = ri.m_current;
 
591
        m_numRects = ri.m_numRects;
 
592
        if ( m_numRects )
 
593
        {
 
594
            m_rects = new wxRect[m_numRects];
 
595
            memcpy(m_rects, ri.m_rects, m_numRects * sizeof m_rects[0]);
 
596
        }
 
597
    }
 
598
    return *this;
 
599
}