~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/gfx/src/xprint/nsRenderingContextXlib.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
5
 * The contents of this file are subject to the Netscape Public License
 
6
 * Version 1.1 (the "License"); you may not use this file except in
 
7
 * compliance with the License. You may obtain a copy of the License at
 
8
 * http://www.mozilla.org/NPL/
 
9
 *
 
10
 * Software distributed under the License is distributed on an "AS IS" basis,
 
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
12
 * for the specific language governing rights and limitations under the
 
13
 * License.
 
14
 *
 
15
 * The Original Code is mozilla.org code.
 
16
 *
 
17
 * The Initial Developer of the Original Code is 
 
18
 * Netscape Communications Corporation.
 
19
 * Portions created by the Initial Developer are Copyright (C) 1998
 
20
 * the Initial Developer. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Peter Hartshorn <peter@igelaus.com.au>
 
24
 *   Ken Faulkner <faulkner@igelaus.com.au>
 
25
 *   Tony Tsui <tony@igelaus.com.au>
 
26
 *   Tomi Leppikangas <tomi.leppikangas@oulu.fi>
 
27
 *   Tim Copperfield <timecop@network.email.ne.jp>
 
28
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 
29
 *
 
30
 *
 
31
 * Alternatively, the contents of this file may be used under the terms of
 
32
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
33
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
34
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
35
 * of those above. If you wish to allow use of your version of this file only
 
36
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
37
 * use your version of this file under the terms of the NPL, indicate your
 
38
 * decision by deleting the provisions above and replace them with the notice
 
39
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
40
 * the provisions above, a recipient may use your version of this file under
 
41
 * the terms of any one of the NPL, the GPL or the LGPL.
 
42
 *
 
43
 * ***** END LICENSE BLOCK ***** */
 
44
 
 
45
#include "nsRenderingContextXlib.h"
 
46
#include "nsFontMetricsXlib.h"
 
47
#include "nsCompressedCharMap.h"
 
48
#include "xlibrgb.h"
 
49
#include "prprf.h"
 
50
#include "prmem.h"
 
51
#include "prlog.h"
 
52
#include "prenv.h"
 
53
#include "nsGCCache.h"
 
54
#include "imgIContainer.h"
 
55
#include "gfxIImageFrame.h"
 
56
#include "nsIInterfaceRequestor.h"
 
57
#include "nsIInterfaceRequestorUtils.h"
 
58
 
 
59
#define NS_TO_XLIBRGB_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff)
 
60
 
 
61
NS_IMPL_ISUPPORTS1(nsRenderingContextXlib, nsIRenderingContext)
 
62
 
 
63
#ifdef PR_LOGGING 
 
64
static PRLogModuleInfo * RenderingContextXlibLM = PR_NewLogModule("RenderingContextXlib");
 
65
#endif /* PR_LOGGING */ 
 
66
 
 
67
/* Handle drawing 8 bit data with a 16 bit font */
 
68
static void Widen8To16AndDraw(Drawable    drawable,
 
69
                              nsXFont     *font,
 
70
                              GC           gc,
 
71
                              int          x,
 
72
                              int          y,
 
73
                              const char  *text,
 
74
                              int          text_length);
 
75
 
 
76
 
 
77
class nsRenderingContextXlibContext
 
78
{
 
79
public:
 
80
  nsGCCacheXlib mGcCache;
 
81
};
 
82
 
 
83
nsresult CreateRenderingContextXlibContext(nsIDeviceContext *aDevice, nsRenderingContextXlibContext **aContext)
 
84
{
 
85
  nsRenderingContextXlibContext *rcctx;
 
86
  
 
87
  *aContext = nsnull;
 
88
  
 
89
  rcctx = new nsRenderingContextXlibContext();
 
90
  if (!rcctx)
 
91
    return NS_ERROR_OUT_OF_MEMORY;
 
92
  
 
93
  /* No |Init()|-function to call (yet) */ 
 
94
  *aContext = rcctx;
 
95
  
 
96
  return NS_OK;
 
97
}
 
98
 
 
99
void DeleteRenderingContextXlibContext(nsRenderingContextXlibContext *aContext)
 
100
{
 
101
  if (aContext) {
 
102
    delete aContext;
 
103
  }
 
104
}
 
105
 
 
106
class GraphicsState
 
107
{
 
108
public:
 
109
  GraphicsState();
 
110
  ~GraphicsState();
 
111
 
 
112
  nsTransform2D           *mMatrix;
 
113
  nsCOMPtr<nsIRegion>      mClipRegion;
 
114
  nscolor                  mColor;
 
115
  nsLineStyle              mLineStyle;
 
116
  nsCOMPtr<nsIFontMetrics> mFontMetrics;
 
117
};
 
118
 
 
119
MOZ_DECL_CTOR_COUNTER(GraphicsState)
 
120
 
 
121
GraphicsState::GraphicsState() :
 
122
  mMatrix(nsnull),
 
123
  mColor(NS_RGB(0, 0, 0)),
 
124
  mLineStyle(nsLineStyle_kSolid),
 
125
  mFontMetrics(nsnull)
 
126
{
 
127
  MOZ_COUNT_CTOR(GraphicsState);
 
128
 
 
129
}
 
130
 
 
131
GraphicsState::~GraphicsState()
 
132
{
 
133
  MOZ_COUNT_DTOR(GraphicsState);
 
134
}
 
135
 
 
136
 
 
137
nsRenderingContextXlib::nsRenderingContextXlib() :
 
138
  nsRenderingContextImpl(),
 
139
  mP2T(1.0f),
 
140
  mGC(nsnull),
 
141
  mFunction(GXcopy),
 
142
  mCurrentColor(NS_RGB(0, 0, 0)), /* X11 intial bg color is always _black_...
 
143
                                   * ...but we should query that from 
 
144
                                   * Xserver instead of guessing that...
 
145
                                   */
 
146
  mCurrentFont(nsnull),
 
147
  mCurrentLineStyle(nsLineStyle_kSolid)
 
148
{
 
149
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::nsRenderingContextXlib()\n"));
 
150
 
 
151
  PushState();
 
152
}
 
153
 
 
154
nsRenderingContextXlib::~nsRenderingContextXlib()
 
155
{
 
156
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::~nsRenderingContextXlib()\n"));
 
157
  /* Destroy the State Machine */
 
158
  PRInt32 cnt = mStateCache.Count();
 
159
 
 
160
  while (--cnt >= 0) {
 
161
    PRBool clipstate;
 
162
    PopState(clipstate);
 
163
  }
 
164
 
 
165
  if (mTranMatrix)
 
166
    delete mTranMatrix;
 
167
  
 
168
  if (mGC)
 
169
    mGC->Release();
 
170
}
 
171
 
 
172
NS_IMETHODIMP
 
173
nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsIWidget *aWindow)
 
174
{
 
175
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Init(DeviceContext, Widget)\n"));
 
176
  nsDrawingSurfaceXlibImpl *surf; // saves some cast stunts
 
177
 
 
178
  NS_ENSURE_TRUE(aContext != nsnull, NS_ERROR_NULL_POINTER);
 
179
  NS_ENSURE_TRUE(aWindow  != nsnull, NS_ERROR_NULL_POINTER);
 
180
  mContext = aContext;
 
181
  
 
182
  nsIDeviceContext *dc = mContext;     
 
183
  NS_STATIC_CAST(nsDeviceContextX *, dc)->GetXlibRgbHandle(mXlibRgbHandle);
 
184
  mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
 
185
 
 
186
  surf = new nsDrawingSurfaceXlibImpl();
 
187
 
 
188
  if (surf) {
 
189
    Drawable  win = (Drawable)aWindow->GetNativeData(NS_NATIVE_WINDOW);
 
190
    xGC      *gc  = (xGC *)aWindow->GetNativeData(NS_NATIVE_GRAPHIC);
 
191
 
 
192
    surf->Init(mXlibRgbHandle, 
 
193
               win, 
 
194
               gc);
 
195
 
 
196
    mOffscreenSurface = mSurface = surf;
 
197
    /* aWindow->GetNativeData() ref'd the gc */
 
198
    gc->Release();
 
199
  }
 
200
 
 
201
  return CommonInit();
 
202
}
 
203
 
 
204
NS_IMETHODIMP
 
205
nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsDrawingSurface aSurface)
 
206
{
 
207
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContxtXlib::Init(DeviceContext, DrawingSurface)\n"));
 
208
 
 
209
  NS_ENSURE_TRUE(nsnull != aContext, NS_ERROR_NULL_POINTER);
 
210
  mContext = aContext;
 
211
  
 
212
  nsIDeviceContext *dc = mContext;     
 
213
  NS_STATIC_CAST(nsDeviceContextX *, dc)->GetXlibRgbHandle(mXlibRgbHandle);
 
214
  mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
 
215
 
 
216
  mSurface = (nsIDrawingSurfaceXlib *)aSurface;
 
217
  mOffscreenSurface = mSurface;
 
218
 
 
219
  return CommonInit();
 
220
}
 
221
 
 
222
nsresult nsRenderingContextXlib::CommonInit(void)
 
223
{
 
224
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContxtXlib::CommonInit()\n"));
 
225
  // put common stuff in here.
 
226
  int x, y;
 
227
  unsigned int width, height, border, depth;
 
228
  Window root_win;
 
229
 
 
230
  Drawable drawable; mSurface->GetDrawable(drawable);
 
231
 
 
232
  ::XGetGeometry(mDisplay, 
 
233
                 drawable, 
 
234
                 &root_win,
 
235
                 &x, 
 
236
                 &y, 
 
237
                 &width, 
 
238
                 &height, 
 
239
                 &border, 
 
240
                 &depth);
 
241
 
 
242
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, 
 
243
         ("XGetGeometry(display=%lx,drawable=%lx) ="
 
244
         " {root_win=%lx, x=%d, y=%d, width=%d, height=%d. border=%d, depth=%d}\n",
 
245
         (long)mDisplay, (long)drawable,
 
246
         (long)root_win, (int)x, (int)y, (int)width, (int)height, (int)border, (int)depth));
 
247
 
 
248
  mClipRegion = new nsRegionXlib();
 
249
  if (!mClipRegion)
 
250
    return NS_ERROR_OUT_OF_MEMORY;
 
251
  mClipRegion->Init();
 
252
  mClipRegion->SetTo(0, 0, width, height);
 
253
 
 
254
  mP2T = mContext->DevUnitsToAppUnits();
 
255
  float app2dev;
 
256
  app2dev = mContext->AppUnitsToDevUnits();
 
257
  mTranMatrix->AddScale(app2dev, app2dev);
 
258
  return NS_OK;
 
259
}
 
260
 
 
261
 
 
262
NS_IMETHODIMP
 
263
nsRenderingContextXlib::GetHints(PRUint32& aResult)
 
264
{
 
265
  PRUint32 result = 0;
 
266
 
 
267
  // Most X servers implement 8 bit text rendering alot faster than
 
268
  // XChar2b rendering. In addition, we can avoid the PRUnichar to
 
269
  // XChar2b conversion. So we set this bit...
 
270
  result |= NS_RENDERING_HINT_FAST_8BIT_TEXT;
 
271
  
 
272
/* We can't enable fast text measuring (yet) on platforms
 
273
 * which force natural alignment of datatypes (see 
 
274
 * http://bugzilla.mozilla.org/show_bug.cgi?id=36146#c46) ... ;-(
 
275
 */
 
276
#ifndef CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT
 
277
#if defined(__i386)
 
278
#define CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT 1
 
279
#endif /* __i386 */
 
280
#endif /* !CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT */
 
281
 
 
282
  static PRBool enable_fast_measure;
 
283
  static PRBool getenv_done = PR_FALSE;
 
284
 
 
285
  /* Check for the env vars "MOZILLA_GFX_ENABLE_FAST_MEASURE" and
 
286
   * "MOZILLA_GFX_DISABLE_FAST_MEASURE" to enable/disable fast text
 
287
   * measuring (for debugging the feature and doing regression tests).
 
288
   * This code will be removed one all issues around this new feature have
 
289
   * been fixed. */
 
290
  if (!getenv_done)
 
291
  {
 
292
#ifdef CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT
 
293
    enable_fast_measure = PR_TRUE;
 
294
#else
 
295
    enable_fast_measure = PR_FALSE;
 
296
#endif /* CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT */
 
297
 
 
298
    if (PR_GetEnv("MOZILLA_GFX_ENABLE_FAST_MEASURE"))
 
299
    {
 
300
      enable_fast_measure = PR_TRUE;
 
301
    }
 
302
 
 
303
    if (PR_GetEnv("MOZILLA_GFX_DISABLE_FAST_MEASURE"))
 
304
    {
 
305
      enable_fast_measure = PR_FALSE;
 
306
    }
 
307
        
 
308
    getenv_done = PR_TRUE;
 
309
  } 
 
310
 
 
311
  if (enable_fast_measure) {
 
312
    // We have GetTextDimensions()
 
313
    result |= NS_RENDERING_HINT_FAST_MEASURE;
 
314
  }
 
315
 
 
316
  // XXX see if we are rendering to the local display or to a remote
 
317
  // dispaly and set the NS_RENDERING_HINT_REMOTE_RENDERING accordingly
 
318
 
 
319
  aResult = result;
 
320
  return NS_OK;
 
321
}
 
322
 
 
323
NS_IMETHODIMP
 
324
nsRenderingContextXlib::LockDrawingSurface(PRInt32 aX, PRInt32 aY,
 
325
                                           PRUint32 aWidth, PRUint32 aHeight,
 
326
                                           void **aBits, PRInt32 *aStride,
 
327
                                           PRInt32 *aWidthBytes, PRUint32 aFlags)
 
328
{
 
329
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::LockDrawingSurface()\n"));
 
330
  PushState();
 
331
 
 
332
  return mSurface->Lock(aX, aY, aWidth, aHeight,
 
333
                        aBits, aStride, aWidthBytes, aFlags);
 
334
}
 
335
 
 
336
NS_IMETHODIMP
 
337
nsRenderingContextXlib::UnlockDrawingSurface(void)
 
338
{
 
339
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::UnlockDrawingSurface()\n"));
 
340
  PRBool clipstate;
 
341
  PopState(clipstate);
 
342
 
 
343
  mSurface->Unlock();
 
344
  
 
345
  return NS_OK;
 
346
}
 
347
 
 
348
NS_IMETHODIMP
 
349
nsRenderingContextXlib::SelectOffScreenDrawingSurface(nsDrawingSurface aSurface)
 
350
{
 
351
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SelectOffScreenDrawingSurface()\n"));
 
352
  if (nsnull == aSurface)
 
353
    mSurface = mOffscreenSurface;
 
354
  else
 
355
    mSurface = (nsIDrawingSurfaceXlib *)aSurface;
 
356
 
 
357
  return NS_OK;
 
358
}
 
359
 
 
360
NS_IMETHODIMP
 
361
nsRenderingContextXlib::GetDrawingSurface(nsDrawingSurface *aSurface)
 
362
{
 
363
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetDrawingSurface()\n"));
 
364
  *aSurface = mSurface;
 
365
  return NS_OK;
 
366
}
 
367
 
 
368
NS_IMETHODIMP
 
369
nsRenderingContextXlib::Reset()
 
370
{
 
371
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Reset()\n"));
 
372
  return NS_OK;
 
373
}
 
374
 
 
375
NS_IMETHODIMP nsRenderingContextXlib::GetDeviceContext(nsIDeviceContext *&aContext)
 
376
{
 
377
  aContext = mContext;
 
378
  NS_IF_ADDREF(aContext);
 
379
  return NS_OK;
 
380
}
 
381
 
 
382
NS_IMETHODIMP
 
383
nsRenderingContextXlib::PushState(void)
 
384
{
 
385
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::PushState()\n"));
 
386
  GraphicsState *state = new GraphicsState();
 
387
 
 
388
  if (!state)
 
389
    return NS_ERROR_OUT_OF_MEMORY;
 
390
 
 
391
  state->mMatrix = mTranMatrix;
 
392
  
 
393
  mStateCache.AppendElement(state);
 
394
  
 
395
  if (nsnull == mTranMatrix)
 
396
    mTranMatrix = new nsTransform2D();
 
397
  else
 
398
    mTranMatrix = new nsTransform2D(mTranMatrix);
 
399
  
 
400
  if (mClipRegion) {
 
401
    state->mClipRegion = mClipRegion;
 
402
    mClipRegion = new nsRegionXlib();
 
403
    if (!mClipRegion)
 
404
      return NS_ERROR_OUT_OF_MEMORY;
 
405
    mClipRegion->Init();
 
406
    mClipRegion->SetTo(*state->mClipRegion);
 
407
  }
 
408
  
 
409
  state->mFontMetrics = mFontMetrics;
 
410
  state->mColor       = mCurrentColor;
 
411
  state->mLineStyle   = mCurrentLineStyle;
 
412
  
 
413
  return NS_OK;
 
414
}
 
415
 
 
416
NS_IMETHODIMP
 
417
nsRenderingContextXlib::PopState(PRBool &aClipState)
 
418
{
 
419
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::PopState()\n"));
 
420
 
 
421
  PRUint32 cnt = mStateCache.Count();
 
422
  GraphicsState *state;
 
423
  
 
424
  if (cnt > 0) {
 
425
    state = (GraphicsState *)mStateCache.ElementAt(cnt - 1);
 
426
    mStateCache.RemoveElementAt(cnt - 1);
 
427
    
 
428
    if (mTranMatrix)
 
429
      delete mTranMatrix;
 
430
    mTranMatrix = state->mMatrix;
 
431
    
 
432
    mClipRegion = state->mClipRegion;
 
433
    if (mFontMetrics != state->mFontMetrics)
 
434
      SetFont(state->mFontMetrics);
 
435
 
 
436
    if (state->mColor != mCurrentColor)
 
437
      SetColor(state->mColor);
 
438
    if (state->mLineStyle != mCurrentLineStyle)
 
439
      SetLineStyle(state->mLineStyle);
 
440
 
 
441
    delete state;
 
442
  }
 
443
 
 
444
  if (mClipRegion)
 
445
    aClipState = mClipRegion->IsEmpty();
 
446
  else 
 
447
    aClipState = PR_TRUE;
 
448
 
 
449
  return NS_OK;
 
450
}
 
451
 
 
452
#ifdef DEBUG
 
453
#undef TRACE_SET_CLIP
 
454
#endif
 
455
 
 
456
#ifdef TRACE_SET_CLIP
 
457
static char *
 
458
nsClipCombine_to_string(nsClipCombine aCombine)
 
459
{
 
460
#ifdef TRACE_SET_CLIP
 
461
  printf("nsRenderingContextXlib::SetClipRect(x=%d,y=%d,w=%d,h=%d,%s)\n",
 
462
         trect.x,
 
463
         trect.y,
 
464
         trect.width,
 
465
         trect.height,
 
466
         nsClipCombine_to_string(aCombine));
 
467
#endif // TRACE_SET_CLIP
 
468
 
 
469
  switch(aCombine)
 
470
  {
 
471
    case nsClipCombine_kIntersect:
 
472
      return "nsClipCombine_kIntersect";
 
473
      break;
 
474
 
 
475
    case nsClipCombine_kUnion:
 
476
      return "nsClipCombine_kUnion";
 
477
      break;
 
478
 
 
479
    case nsClipCombine_kSubtract:
 
480
      return "nsClipCombine_kSubtract";
 
481
      break;
 
482
 
 
483
    case nsClipCombine_kReplace:
 
484
      return "nsClipCombine_kReplace";
 
485
      break;
 
486
  }
 
487
 
 
488
  return "something got screwed";
 
489
}
 
490
#endif // TRACE_SET_CLIP
 
491
 
 
492
NS_IMETHODIMP
 
493
nsRenderingContextXlib::IsVisibleRect(const nsRect& aRect, PRBool &aVisible)
 
494
{
 
495
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::IsVisibleRect()\n"));
 
496
  aVisible = PR_TRUE;
 
497
  return NS_OK;
 
498
}
 
499
 
 
500
NS_IMETHODIMP 
 
501
nsRenderingContextXlib::SetClipRect(const nsRect& aRect,
 
502
                                    nsClipCombine aCombine,
 
503
                                    PRBool &aClipEmpty)
 
504
{
 
505
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetClipRect()\n"));
 
506
  nsRect trect = aRect;
 
507
  mTranMatrix->TransformCoord(&trect.x, &trect.y,
 
508
                              &trect.width, &trect.height);
 
509
  SetClipRectInPixels(trect, aCombine, aClipEmpty);
 
510
  return NS_OK;
 
511
}
 
512
 
 
513
void nsRenderingContextXlib::SetClipRectInPixels(const nsRect& aRect,
 
514
                                                 nsClipCombine aCombine,
 
515
                                                 PRBool &aClipEmpty)
 
516
{
 
517
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetClipRectInPixels()\n"));
 
518
 
 
519
  switch(aCombine)
 
520
  {
 
521
    case nsClipCombine_kIntersect:
 
522
      mClipRegion->Intersect(aRect.x,aRect.y,aRect.width,aRect.height);
 
523
      break;
 
524
    case nsClipCombine_kUnion:
 
525
      mClipRegion->Union(aRect.x,aRect.y,aRect.width,aRect.height);
 
526
      break;
 
527
    case nsClipCombine_kSubtract:
 
528
      mClipRegion->Subtract(aRect.x,aRect.y,aRect.width,aRect.height);
 
529
      break;
 
530
    case nsClipCombine_kReplace:
 
531
      mClipRegion->SetTo(aRect.x,aRect.y,aRect.width,aRect.height);
 
532
      break;
 
533
  }
 
534
  
 
535
  aClipEmpty = mClipRegion->IsEmpty();
 
536
}
 
537
 
 
538
NS_IMETHODIMP
 
539
nsRenderingContextXlib::GetClipRect(nsRect &aRect, PRBool &aClipState)
 
540
{
 
541
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetClipRext()\n"));
 
542
  PRInt32 x, y, w, h;
 
543
  if (!mClipRegion->IsEmpty()) {
 
544
    mClipRegion->GetBoundingBox(&x,&y,&w,&h);
 
545
    aRect.SetRect(x,y,w,h);
 
546
    aClipState = PR_TRUE;
 
547
  } else {
 
548
    aRect.SetRect(0,0,0,0);
 
549
    aClipState = PR_FALSE;
 
550
  }
 
551
  return NS_OK;
 
552
}
 
553
 
 
554
NS_IMETHODIMP
 
555
nsRenderingContextXlib::SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine, PRBool &aClipState)
 
556
{
 
557
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetClipRegion()\n"));
 
558
  switch(aCombine)
 
559
  {
 
560
    case nsClipCombine_kIntersect:
 
561
      mClipRegion->Intersect(aRegion);
 
562
      break;
 
563
    case nsClipCombine_kUnion:
 
564
      mClipRegion->Union(aRegion);
 
565
      break;
 
566
    case nsClipCombine_kSubtract:
 
567
      mClipRegion->Subtract(aRegion);
 
568
      break;
 
569
    case nsClipCombine_kReplace:
 
570
      mClipRegion->SetTo(aRegion);
 
571
      break;
 
572
  }
 
573
 
 
574
  aClipState = mClipRegion->IsEmpty();
 
575
 
 
576
  return NS_OK;
 
577
}
 
578
 
 
579
NS_IMETHODIMP
 
580
nsRenderingContextXlib::CopyClipRegion(nsIRegion &aRegion)
 
581
{
 
582
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CopyClipRegion()\n"));
 
583
  aRegion.SetTo(*mClipRegion);
 
584
  return NS_OK;
 
585
}
 
586
 
 
587
NS_IMETHODIMP
 
588
nsRenderingContextXlib::GetClipRegion(nsIRegion **aRegion)
 
589
{
 
590
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetClipRegion()\n"));
 
591
  nsresult  rv = NS_OK;
 
592
  
 
593
  NS_ASSERTION(!(nsnull == aRegion), "no region ptr");
 
594
  
 
595
  if (*aRegion) {
 
596
    (*aRegion)->SetTo(*mClipRegion);
 
597
  }
 
598
  return rv;
 
599
}
 
600
 
 
601
void nsRenderingContextXlib::UpdateGC()
 
602
{
 
603
   PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::UpdateGC()\n"));
 
604
   XGCValues     values;
 
605
   unsigned long valuesMask = 0;
 
606
 
 
607
   Drawable drawable; mSurface->GetDrawable(drawable);
 
608
 
 
609
   if (mGC)
 
610
     mGC->Release();
 
611
 
 
612
   memset(&values, 0, sizeof(XGCValues));
 
613
 
 
614
   unsigned long color;
 
615
   color = xxlib_rgb_xpixel_from_rgb (mXlibRgbHandle,
 
616
                                      NS_RGB(NS_GET_B(mCurrentColor),
 
617
                                             NS_GET_G(mCurrentColor),
 
618
                                             NS_GET_R(mCurrentColor)));
 
619
   values.foreground = color;
 
620
   valuesMask |= GCForeground;
 
621
 
 
622
   if (mCurrentFont && mCurrentFont->GetXFontStruct()) {
 
623
     valuesMask |= GCFont;
 
624
     values.font = mCurrentFont->GetXFontStruct()->fid;
 
625
   }
 
626
 
 
627
   values.line_style = mLineStyle;
 
628
   valuesMask |= GCLineStyle;
 
629
 
 
630
   values.function = mFunction;
 
631
   valuesMask |= GCFunction;
 
632
 
 
633
   Region rgn = nsnull;
 
634
   if (mClipRegion) { 
 
635
     mClipRegion->GetNativeRegion((void*&)rgn);
 
636
   }
 
637
 
 
638
   nsRenderingContextXlibContext *rcContext;
 
639
   nsIDeviceContext *dc = mContext;
 
640
   NS_STATIC_CAST(nsDeviceContextX *, dc)->GetRCContext(rcContext);
 
641
   
 
642
   mGC = rcContext->mGcCache.GetGC(mDisplay, drawable,
 
643
                                  valuesMask, &values, rgn);
 
644
}
 
645
 
 
646
NS_IMETHODIMP
 
647
nsRenderingContextXlib::SetColor(nscolor aColor)
 
648
{
 
649
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetColor(nscolor)\n"));
 
650
  NS_ENSURE_TRUE(mContext != nsnull, NS_ERROR_FAILURE);
 
651
 
 
652
  mCurrentColor = aColor;
 
653
 
 
654
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("Setting color to %d %d %d\n", NS_GET_R(aColor), NS_GET_G(aColor), NS_GET_B(aColor)));
 
655
  return NS_OK;
 
656
}
 
657
 
 
658
NS_IMETHODIMP
 
659
nsRenderingContextXlib::GetColor(nscolor &aColor) const
 
660
{
 
661
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetColor()\n"));
 
662
 
 
663
  aColor = mCurrentColor;
 
664
  return NS_OK;
 
665
}
 
666
 
 
667
NS_IMETHODIMP
 
668
nsRenderingContextXlib::SetFont(const nsFont& aFont, nsIAtom* aLangGroup)
 
669
{
 
670
  nsCOMPtr<nsIFontMetrics> newMetrics;
 
671
  nsresult rv = mContext->GetMetricsFor( aFont, aLangGroup, *getter_AddRefs(newMetrics) );
 
672
 
 
673
  if (NS_SUCCEEDED(rv)) {
 
674
    rv = SetFont(newMetrics);
 
675
  }
 
676
  return rv;
 
677
}
 
678
 
 
679
NS_IMETHODIMP
 
680
nsRenderingContextXlib::SetFont(nsIFontMetrics *aFontMetrics)
 
681
{
 
682
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetFont()\n"));
 
683
 
 
684
  mFontMetrics = aFontMetrics;
 
685
 
 
686
  if (mFontMetrics)
 
687
  {
 
688
    nsFontHandle  fontHandle;
 
689
    mFontMetrics->GetFontHandle(fontHandle);
 
690
    mCurrentFont = (nsFontXlib *)fontHandle;
 
691
  }
 
692
 
 
693
  return NS_OK;
 
694
}
 
695
 
 
696
NS_IMETHODIMP
 
697
nsRenderingContextXlib::SetLineStyle(nsLineStyle aLineStyle)
 
698
{
 
699
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetLineStyle()\n"));
 
700
 
 
701
  if (aLineStyle != mCurrentLineStyle) {
 
702
    /* XXX this isnt done in gtk, copy from there when ready
 
703
    switch(aLineStyle)
 
704
      { 
 
705
      case nsLineStyle_kSolid:
 
706
        mLineStyle = LineSolid;
 
707
        mDashes = 0;
 
708
        break;
 
709
      case nsLineStyle_kDashed:
 
710
          static char dashed[2] = {4,4};
 
711
        mDashList = dashed;
 
712
        mDashes = 2;
 
713
        break;
 
714
      case nsLineStyle_kDotted:
 
715
          static char dotted[2] = {3,1};
 
716
        mDashList = dotted;
 
717
        mDashes = 2;
 
718
        break;
 
719
    default:
 
720
        break;
 
721
 
 
722
    }
 
723
    */
 
724
    mCurrentLineStyle = aLineStyle ;
 
725
  }
 
726
  return NS_OK;
 
727
}
 
728
 
 
729
NS_IMETHODIMP
 
730
nsRenderingContextXlib::GetLineStyle(nsLineStyle &aLineStyle)
 
731
{
 
732
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetLineStyle()\n"));
 
733
  aLineStyle = mCurrentLineStyle;
 
734
  return NS_OK;
 
735
}
 
736
 
 
737
NS_IMETHODIMP
 
738
nsRenderingContextXlib::GetFontMetrics(nsIFontMetrics *&aFontMetrics)
 
739
{
 
740
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetFontMetrics()\n"));
 
741
 
 
742
  aFontMetrics = mFontMetrics;
 
743
  NS_IF_ADDREF(aFontMetrics);
 
744
  return NS_OK;
 
745
}
 
746
 
 
747
// add the passed in translation to the current translation
 
748
NS_IMETHODIMP
 
749
nsRenderingContextXlib::Translate(nscoord aX, nscoord aY)
 
750
{
 
751
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Translate()\n"));
 
752
  mTranMatrix->AddTranslation((float)aX,(float)aY);
 
753
  return NS_OK;
 
754
}
 
755
 
 
756
// add the passed in scale to the current scale
 
757
NS_IMETHODIMP
 
758
nsRenderingContextXlib::Scale(float aSx, float aSy)
 
759
{
 
760
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Scale()\n"));
 
761
  mTranMatrix->AddScale(aSx, aSy);
 
762
  return NS_OK;
 
763
}
 
764
 
 
765
NS_IMETHODIMP
 
766
nsRenderingContextXlib::GetCurrentTransform(nsTransform2D *&aTransform)
 
767
{
 
768
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetCurrentTransform()\n"));
 
769
  aTransform = mTranMatrix;
 
770
  return NS_OK;
 
771
}
 
772
 
 
773
NS_IMETHODIMP
 
774
nsRenderingContextXlib::CreateDrawingSurface(const nsRect& aBounds,
 
775
                                             PRUint32 aSurfFlags,
 
776
                                             nsDrawingSurface &aSurface)
 
777
{
 
778
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CreateDrawingSurface()\n"));
 
779
 
 
780
  if (nsnull == mSurface) {
 
781
    aSurface = nsnull;
 
782
    return NS_ERROR_FAILURE;
 
783
  }
 
784
 
 
785
  NS_ENSURE_TRUE((aBounds.width > 0) && (aBounds.height > 0), NS_ERROR_FAILURE);
 
786
 
 
787
  nsresult rv = NS_ERROR_FAILURE;
 
788
  nsDrawingSurfaceXlibImpl *surf = new nsDrawingSurfaceXlibImpl();
 
789
 
 
790
  if (surf)
 
791
  {
 
792
    NS_ADDREF(surf);
 
793
    UpdateGC();
 
794
    rv = surf->Init(mXlibRgbHandle, mGC, aBounds.width, aBounds.height, aSurfFlags);    
 
795
  }
 
796
 
 
797
  aSurface = (nsDrawingSurface)surf;
 
798
 
 
799
  return rv;
 
800
}
 
801
 
 
802
NS_IMETHODIMP
 
803
nsRenderingContextXlib::DestroyDrawingSurface(nsDrawingSurface aDS)
 
804
{
 
805
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DestroyDrawingSurface()\n"));
 
806
  nsIDrawingSurfaceXlib *surf = NS_STATIC_CAST(nsIDrawingSurfaceXlib *, aDS);;
 
807
 
 
808
  NS_ENSURE_TRUE(surf != nsnull, NS_ERROR_FAILURE);
 
809
 
 
810
  NS_IF_RELEASE(surf);
 
811
 
 
812
  return NS_OK;
 
813
}
 
814
 
 
815
NS_IMETHODIMP
 
816
nsRenderingContextXlib::DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
 
817
{
 
818
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawLine()\n"));
 
819
 
 
820
  nscoord diffX, diffY;
 
821
 
 
822
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
823
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
824
 
 
825
  mTranMatrix->TransformCoord(&aX0,&aY0);
 
826
  mTranMatrix->TransformCoord(&aX1,&aY1);
 
827
  
 
828
  diffX = aX1-aX0;
 
829
  diffY = aY1-aY0;
 
830
 
 
831
  if (0!=diffX) {
 
832
    diffX = (diffX>0?1:-1);
 
833
  }
 
834
  if (0!=diffY) {
 
835
    diffY = (diffY>0?1:-1);
 
836
  }
 
837
 
 
838
  UpdateGC();
 
839
  Drawable drawable; mSurface->GetDrawable(drawable);
 
840
  ::XDrawLine(mDisplay, drawable,
 
841
              *mGC, aX0, aY0, aX1 - diffX, aY1 - diffY);
 
842
 
 
843
  return NS_OK;
 
844
}
 
845
 
 
846
NS_IMETHODIMP
 
847
nsRenderingContextXlib::DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
 
848
{
 
849
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawStdLine()\n"));
 
850
 
 
851
  nscoord diffX, diffY;
 
852
 
 
853
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
854
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
855
 
 
856
  mTranMatrix->TransformCoord(&aX0,&aY0);
 
857
  mTranMatrix->TransformCoord(&aX1,&aY1);
 
858
  
 
859
  diffX = aX1-aX0;
 
860
  diffY = aY1-aY0;
 
861
 
 
862
  if (0!=diffX) {
 
863
    diffX = (diffX>0?1:-1);
 
864
  }
 
865
  if (0!=diffY) {
 
866
    diffY = (diffY>0?1:-1);
 
867
  }
 
868
 
 
869
  UpdateGC();
 
870
  Drawable drawable; mSurface->GetDrawable(drawable);
 
871
  ::XDrawLine(mDisplay, drawable,
 
872
              *mGC, aX0, aY0, aX1 - diffX, aY1 - diffY);
 
873
 
 
874
  return NS_OK;
 
875
}
 
876
 
 
877
NS_IMETHODIMP
 
878
nsRenderingContextXlib::DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints)
 
879
{
 
880
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawPolyLine()\n"));
 
881
 
 
882
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
883
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
884
 
 
885
  PRInt32  i;
 
886
  XPoint * xpoints;
 
887
  XPoint * thispoint;
 
888
 
 
889
  xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
 
890
  NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
 
891
 
 
892
  for (i = 0; i < aNumPoints; i++){
 
893
    thispoint = (xpoints+i);
 
894
    thispoint->x = aPoints[i].x;
 
895
    thispoint->y = aPoints[i].y;
 
896
    mTranMatrix->TransformCoord((PRInt32*)&thispoint->x,(PRInt32*)&thispoint->y);
 
897
  }
 
898
 
 
899
  UpdateGC();
 
900
  Drawable drawable; mSurface->GetDrawable(drawable);
 
901
  ::XDrawLines(mDisplay,
 
902
               drawable,
 
903
               *mGC,
 
904
               xpoints, aNumPoints, CoordModeOrigin);
 
905
 
 
906
  free((void *)xpoints);
 
907
 
 
908
  return NS_OK;
 
909
}
 
910
 
 
911
NS_IMETHODIMP
 
912
nsRenderingContextXlib::DrawRect(const nsRect& aRect)
 
913
{
 
914
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawRext(const nsRect& aRect)\n"));
 
915
  return DrawRect(aRect.x, aRect.y, aRect.width, aRect.height);
 
916
}
 
917
 
 
918
NS_IMETHODIMP
 
919
nsRenderingContextXlib::DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
 
920
{
 
921
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawRect(aX, aY, aWidth, aHeight)\n"));
 
922
 
 
923
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
924
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
925
 
 
926
  nscoord x, y, w, h; 
 
927
  
 
928
  x = aX;
 
929
  y = aY; 
 
930
  w = aWidth;
 
931
  h = aHeight;
 
932
    
 
933
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
934
    
 
935
  // After the transform, if the numbers are huge, chop them, because
 
936
  // they're going to be converted from 32 bit to 16 bit.
 
937
  // It's all way off the screen anyway.
 
938
  ConditionRect(x,y,w,h);
 
939
   
 
940
  // Don't draw empty rectangles; also, w/h are adjusted down by one
 
941
  // so that the right number of pixels are drawn.
 
942
  if (w && h) 
 
943
  {
 
944
    UpdateGC();
 
945
    Drawable drawable; mSurface->GetDrawable(drawable);
 
946
    ::XDrawRectangle(mDisplay,
 
947
                     drawable,
 
948
                     *mGC,
 
949
                     x,
 
950
                     y,
 
951
                     w-1,
 
952
                     h-1);
 
953
  }
 
954
 
 
955
  return NS_OK;
 
956
}
 
957
 
 
958
 
 
959
NS_IMETHODIMP
 
960
nsRenderingContextXlib::FillRect(const nsRect& aRect)
 
961
{
 
962
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillRect()\n"));
 
963
  return FillRect(aRect.x, aRect.y, aRect.width, aRect.height);
 
964
}
 
965
 
 
966
NS_IMETHODIMP
 
967
nsRenderingContextXlib::FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
 
968
{
 
969
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillRect()\n"));
 
970
 
 
971
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
972
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
973
 
 
974
  nscoord x,y,w,h;
 
975
  x = aX;
 
976
  y = aY;
 
977
  w = aWidth;
 
978
  h = aHeight;
 
979
 
 
980
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
981
 
 
982
  // After the transform, if the numbers are huge, chop them, because
 
983
  // they're going to be converted from 32 bit to 16 bit.
 
984
  // It's all way off the screen anyway.
 
985
  ConditionRect(x,y,w,h);
 
986
 
 
987
  Drawable drawable; mSurface->GetDrawable(drawable);
 
988
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("About to fill window 0x%lxd with rect %d %d %d %d\n",
 
989
                                                drawable, x, y, w, h));
 
990
  UpdateGC();
 
991
  ::XFillRectangle(mDisplay,
 
992
                   drawable,
 
993
                   *mGC,
 
994
                   x,y,w,h);
 
995
  
 
996
  return NS_OK;
 
997
}
 
998
 
 
999
NS_IMETHODIMP
 
1000
nsRenderingContextXlib::InvertRect(const nsRect& aRect)
 
1001
{
 
1002
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::InvertRect()\n"));
 
1003
  return InvertRect(aRect.x, aRect.y, aRect.width, aRect.height);
 
1004
}
 
1005
 
 
1006
NS_IMETHODIMP 
 
1007
nsRenderingContextXlib::InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
 
1008
{
 
1009
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::InvertRect()\n"));
 
1010
 
 
1011
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1012
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1013
  
 
1014
  nscoord x,y,w,h;
 
1015
 
 
1016
  x = aX;
 
1017
  y = aY;
 
1018
  w = aWidth;
 
1019
  h = aHeight;
 
1020
 
 
1021
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
1022
 
 
1023
  // After the transform, if the numbers are huge, chop them, because
 
1024
  // they're going to be converted from 32 bit to 16 bit.
 
1025
  // It's all way off the screen anyway.
 
1026
  ConditionRect(x,y,w,h);
 
1027
 
 
1028
  mFunction = GXxor;
 
1029
  
 
1030
  UpdateGC();
 
1031
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1032
  ::XFillRectangle(mDisplay,
 
1033
                   drawable,
 
1034
                   *mGC,
 
1035
                   x,
 
1036
                   y,
 
1037
                   w,
 
1038
                   h);
 
1039
  
 
1040
  mFunction = GXcopy;
 
1041
 
 
1042
  return NS_OK;
 
1043
}
 
1044
 
 
1045
NS_IMETHODIMP
 
1046
nsRenderingContextXlib::DrawPolygon(const nsPoint aPoints[], PRInt32 aNumPoints)
 
1047
{
 
1048
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawPolygon()\n"));
 
1049
 
 
1050
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1051
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1052
 
 
1053
  PRInt32 i ;
 
1054
  XPoint * xpoints;
 
1055
  XPoint * thispoint;
 
1056
  
 
1057
  xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
 
1058
  NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
 
1059
  
 
1060
  for (i = 0; i < aNumPoints; i++){
 
1061
    thispoint = (xpoints+i);
 
1062
    thispoint->x = aPoints[i].x;
 
1063
    thispoint->y = aPoints[i].y;
 
1064
    mTranMatrix->TransformCoord((PRInt32*)&thispoint->x,(PRInt32*)&thispoint->y);
 
1065
  }
 
1066
  
 
1067
  UpdateGC();
 
1068
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1069
  ::XDrawLines(mDisplay,
 
1070
               drawable,
 
1071
               *mGC,
 
1072
               xpoints, aNumPoints, CoordModeOrigin);
 
1073
 
 
1074
  free((void *)xpoints);
 
1075
  
 
1076
  return NS_OK;    
 
1077
}
 
1078
 
 
1079
NS_IMETHODIMP
 
1080
nsRenderingContextXlib::FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints)
 
1081
{
 
1082
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillPolygon()\n"));
 
1083
 
 
1084
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1085
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1086
 
 
1087
  PRInt32 i ;
 
1088
  XPoint * xpoints;
 
1089
   
 
1090
  xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
 
1091
  NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
 
1092
  
 
1093
  for (i = 0; i < aNumPoints; ++i) {
 
1094
    nsPoint p = aPoints[i];
 
1095
    mTranMatrix->TransformCoord(&p.x, &p.y);
 
1096
    xpoints[i].x = p.x;
 
1097
    xpoints[i].y = p.y;
 
1098
  } 
 
1099
    
 
1100
  UpdateGC();
 
1101
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1102
  ::XFillPolygon(mDisplay,
 
1103
                 drawable,
 
1104
                 *mGC,
 
1105
                 xpoints, aNumPoints, Complex, CoordModeOrigin);
 
1106
               
 
1107
  free((void *)xpoints);
 
1108
 
 
1109
  return NS_OK; 
 
1110
}
 
1111
 
 
1112
NS_IMETHODIMP
 
1113
nsRenderingContextXlib::DrawEllipse(const nsRect& aRect)
 
1114
{
 
1115
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawEllipse(const nsRect& aRect)\n"));
 
1116
  return DrawEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
 
1117
}
 
1118
 
 
1119
NS_IMETHODIMP
 
1120
nsRenderingContextXlib::DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
 
1121
{
 
1122
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawEllipse(aX, aY, aWidth, aHeight)\n"));
 
1123
 
 
1124
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1125
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1126
 
 
1127
  nscoord x, y, w, h;
 
1128
   
 
1129
  x = aX; 
 
1130
  y = aY;
 
1131
  w = aWidth; 
 
1132
  h = aHeight;
 
1133
    
 
1134
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
1135
    
 
1136
  UpdateGC();
 
1137
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1138
  ::XDrawArc(mDisplay,
 
1139
             drawable,
 
1140
             *mGC,
 
1141
             x, y, w, h, 0, 360*64);
 
1142
  
 
1143
  return NS_OK;  
 
1144
}
 
1145
 
 
1146
NS_IMETHODIMP
 
1147
nsRenderingContextXlib::FillEllipse(const nsRect& aRect)
 
1148
{
 
1149
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillEllipse()\n"));
 
1150
  return FillEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
 
1151
}
 
1152
 
 
1153
NS_IMETHODIMP
 
1154
nsRenderingContextXlib::FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
 
1155
{
 
1156
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillEllipse()\n"));
 
1157
 
 
1158
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1159
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1160
 
 
1161
  nscoord x,y,w,h;
 
1162
   
 
1163
  x = aX; 
 
1164
  y = aY;
 
1165
  w = aWidth; 
 
1166
  h = aHeight;
 
1167
    
 
1168
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
1169
    
 
1170
  UpdateGC();
 
1171
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1172
  if (w < 16 || h < 16) {
 
1173
    /* Fix for bug 91816 ("bullets are not displayed correctly on certain text zooms")
 
1174
     * De-uglify bullets on some X servers:
 
1175
     * 1st: Draw... */
 
1176
    ::XDrawArc(mDisplay,
 
1177
               drawable,
 
1178
               *mGC,
 
1179
               x, y, w, h, 0, 360*64);
 
1180
    /*  ...then fill. */
 
1181
  }
 
1182
  ::XFillArc(mDisplay,
 
1183
             drawable,
 
1184
             *mGC,
 
1185
             x, y, w, h, 0, 360*64);
 
1186
  
 
1187
  return NS_OK;  
 
1188
}
 
1189
 
 
1190
NS_IMETHODIMP
 
1191
nsRenderingContextXlib::DrawArc(const nsRect& aRect,
 
1192
                                float aStartAngle, float aEndAngle)
 
1193
{
 
1194
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawArc()\n"));
 
1195
  return DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle); 
 
1196
}
 
1197
 
 
1198
NS_IMETHODIMP
 
1199
nsRenderingContextXlib::DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
 
1200
                                float aStartAngle, float aEndAngle)
 
1201
{
 
1202
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawArc()\n"));
 
1203
 
 
1204
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1205
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1206
 
 
1207
  nscoord x, y, w, h;
 
1208
   
 
1209
  x = aX; 
 
1210
  y = aY;
 
1211
  w = aWidth; 
 
1212
  h = aHeight;
 
1213
    
 
1214
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
1215
    
 
1216
  UpdateGC();
 
1217
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1218
  ::XDrawArc(mDisplay,
 
1219
             drawable,
 
1220
             *mGC,
 
1221
             x,y,w,h, NSToIntRound(aStartAngle * 64.0f),
 
1222
             NSToIntRound(aEndAngle * 64.0f));
 
1223
  
 
1224
  return NS_OK;  
 
1225
}
 
1226
 
 
1227
NS_IMETHODIMP
 
1228
nsRenderingContextXlib::FillArc(const nsRect& aRect,
 
1229
                                float aStartAngle, float aEndAngle)
 
1230
{
 
1231
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillArc()\n"));
 
1232
  return FillArc(aRect.x, aRect.y, aRect.width, aRect.height, aStartAngle, aEndAngle);
 
1233
}
 
1234
 
 
1235
NS_IMETHODIMP
 
1236
nsRenderingContextXlib::FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
 
1237
                                float aStartAngle, float aEndAngle)
 
1238
{
 
1239
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillArc()\n"));
 
1240
 
 
1241
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
1242
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
1243
 
 
1244
  nscoord x,y,w,h;
 
1245
   
 
1246
  x = aX; 
 
1247
  y = aY;
 
1248
  w = aWidth; 
 
1249
  h = aHeight;
 
1250
    
 
1251
  mTranMatrix->TransformCoord(&x,&y,&w,&h);
 
1252
    
 
1253
  UpdateGC();
 
1254
  Drawable drawable; mSurface->GetDrawable(drawable);
 
1255
  ::XFillArc(mDisplay,
 
1256
             drawable,
 
1257
             *mGC,
 
1258
             x,y,w,h, NSToIntRound(aStartAngle * 64.0f),
 
1259
             NSToIntRound(aEndAngle * 64.0f));
 
1260
  
 
1261
  return NS_OK;  
 
1262
}
 
1263
 
 
1264
// do the 8 to 16 bit conversion on the stack
 
1265
// if the data is less than this size
 
1266
#define WIDEN_8_TO_16_BUF_SIZE (1024)
 
1267
 
 
1268
// handle 8 bit data with a 16 bit font
 
1269
static
 
1270
int Widen8To16AndMove(const char *char_p, 
 
1271
                      int char_len, 
 
1272
                      XChar2b *xchar2b_p)
 
1273
{
 
1274
  int i;
 
1275
  for (i=0; i<char_len; i++) {
 
1276
    (xchar2b_p)->byte1 = 0;
 
1277
    (xchar2b_p++)->byte2 = *char_p++;
 
1278
  }
 
1279
  return(char_len*2);
 
1280
}
 
1281
 
 
1282
// handle 8 bit data with a 16 bit font
 
1283
static
 
1284
int Widen8To16AndGetWidth(nsXFont    *xFont,
 
1285
                          const char *text,
 
1286
                          int         text_length)
 
1287
{
 
1288
  NS_ASSERTION(!xFont->IsSingleByte(), "Widen8To16AndGetWidth: wrong string/font size");
 
1289
  XChar2b  buf[WIDEN_8_TO_16_BUF_SIZE];
 
1290
  XChar2b *p = buf;
 
1291
  int uchar_size;
 
1292
  int rawWidth;
 
1293
 
 
1294
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
1295
    p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
 
1296
    if (!p)
 
1297
      return(0); // handle malloc failure
 
1298
  }
 
1299
 
 
1300
  uchar_size = Widen8To16AndMove(text, text_length, p);
 
1301
  rawWidth = xFont->TextWidth16(p, uchar_size/2);
 
1302
 
 
1303
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
1304
    free((char*)p);
 
1305
  }
 
1306
  return(rawWidth);
 
1307
}
 
1308
 
 
1309
static 
 
1310
void Widen8To16AndDraw(Drawable     drawable,
 
1311
                       nsXFont     *xFont,
 
1312
                       GC           gc,
 
1313
                       int          x,
 
1314
                       int          y,
 
1315
                       const char  *text,
 
1316
                       int          text_length)
 
1317
{
 
1318
  NS_ASSERTION(!xFont->IsSingleByte(), "Widen8To16AndDraw: wrong string/font size");
 
1319
  XChar2b buf[WIDEN_8_TO_16_BUF_SIZE];
 
1320
  XChar2b *p = buf;
 
1321
  int uchar_size;
 
1322
 
 
1323
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
1324
    p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
 
1325
    if (!p)
 
1326
      return; // handle malloc failure
 
1327
  }
 
1328
 
 
1329
  uchar_size = Widen8To16AndMove(text, text_length, p);
 
1330
  xFont->DrawText16(drawable, gc, x, y, p, uchar_size/2);
 
1331
 
 
1332
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
1333
    free((char*)p);
 
1334
  }
 
1335
}
 
1336
 
 
1337
NS_IMETHODIMP
 
1338
nsRenderingContextXlib::GetWidth(char aC, nscoord &aWidth)
 
1339
{
 
1340
  // Check for the very common case of trying to get the width of a single
 
1341
  // space.
 
1342
  if ((aC == ' ') && (nsnull != mFontMetrics)) {
 
1343
    return mFontMetrics->GetSpaceWidth(aWidth);
 
1344
  }
 
1345
  return GetWidth(&aC, 1, aWidth);
 
1346
}
 
1347
 
 
1348
NS_IMETHODIMP
 
1349
nsRenderingContextXlib::GetWidth(PRUnichar aC, nscoord& aWidth,
 
1350
                                PRInt32* aFontID)
 
1351
{
 
1352
  return GetWidth(&aC, 1, aWidth, aFontID);
 
1353
}
 
1354
 
 
1355
NS_IMETHODIMP
 
1356
nsRenderingContextXlib::GetWidth(const nsString& aString,
 
1357
                                 nscoord& aWidth, PRInt32* aFontID)
 
1358
{
 
1359
  return GetWidth(aString.get(), aString.Length(), aWidth, aFontID);
 
1360
}
 
1361
 
 
1362
NS_IMETHODIMP
 
1363
nsRenderingContextXlib::GetWidth(const char* aString, nscoord& aWidth)
 
1364
{
 
1365
  return GetWidth(aString, strlen(aString), aWidth);
 
1366
}
 
1367
 
 
1368
NS_IMETHODIMP
 
1369
nsRenderingContextXlib::GetWidth(const char* aString, PRUint32 aLength,
 
1370
                                 nscoord& aWidth)
 
1371
{
 
1372
  if (0 == aLength) {
 
1373
    aWidth = 0;
 
1374
  }
 
1375
  else {
 
1376
    NS_ENSURE_TRUE(aString      != nsnull, NS_ERROR_FAILURE);
 
1377
    NS_ENSURE_TRUE(mCurrentFont != nsnull, NS_ERROR_FAILURE);
 
1378
    int rawWidth;
 
1379
    nsXFont *xFont = mCurrentFont->GetXFont();
 
1380
#ifdef USE_FREETYPE
 
1381
    if (mCurrentFont->IsFreeTypeFont()) {
 
1382
      PRUnichar unichars[WIDEN_8_TO_16_BUF_SIZE];
 
1383
      // need to fix this for long strings
 
1384
      PRUint32 len = PR_MIN(aLength, WIDEN_8_TO_16_BUF_SIZE);
 
1385
      // convert 7 bit data to unicode
 
1386
      // this function is only supposed to be called for ascii data
 
1387
      for (PRUint32 i=0; i<len; i++) {
 
1388
        unichars[i] = (PRUnichar)((unsigned char)aString[i]);
 
1389
      }
 
1390
      rawWidth = mCurrentFont->GetWidth(unichars, len);
 
1391
    }
 
1392
    else
 
1393
#endif /* USE_FREETYPE */
 
1394
    if (!mCurrentFont->GetXFontIs10646()) {
 
1395
      NS_ASSERTION(xFont->IsSingleByte(), "wrong string/font size");
 
1396
      // 8 bit data with an 8 bit font
 
1397
      rawWidth = xFont->TextWidth8(aString, aLength);
 
1398
    }
 
1399
    else {
 
1400
      NS_ASSERTION(!xFont->IsSingleByte(), "wrong string/font size");
 
1401
      // we have 8 bit data but a 16 bit font
 
1402
      rawWidth = Widen8To16AndGetWidth (mCurrentFont->GetXFont(), aString, aLength);
 
1403
    }
 
1404
    aWidth = NSToCoordRound(rawWidth * mP2T);
 
1405
  }
 
1406
  return NS_OK;
 
1407
}
 
1408
 
 
1409
NS_IMETHODIMP
 
1410
nsRenderingContextXlib::GetWidth(const PRUnichar* aString, PRUint32 aLength,
 
1411
                                 nscoord& aWidth, PRInt32* aFontID)
 
1412
{
 
1413
  if (0 == aLength) {
 
1414
    aWidth = 0;
 
1415
  }
 
1416
  else {
 
1417
    NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
 
1418
 
 
1419
    nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
 
1420
 
 
1421
    NS_ENSURE_TRUE(metrics != nsnull, NS_ERROR_FAILURE);
 
1422
 
 
1423
    nsFontXlib *prevFont = nsnull;
 
1424
    int rawWidth = 0;
 
1425
    PRUint32 start = 0;
 
1426
    PRUint32 i;
 
1427
    for (i = 0; i < aLength; i++) {
 
1428
      PRUnichar c = aString[i];
 
1429
      nsFontXlib  *currFont = nsnull;
 
1430
      nsFontXlib **font = metrics->mLoadedFonts;
 
1431
      nsFontXlib **end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
 
1432
      while (font < end) {
 
1433
        if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
 
1434
          currFont = *font;
 
1435
          goto FoundFont; // for speed -- avoid "if" statement
 
1436
        }
 
1437
        font++;
 
1438
      }
 
1439
      currFont = metrics->FindFont(c);
 
1440
FoundFont:
 
1441
      // XXX avoid this test by duplicating code -- erik
 
1442
      if (prevFont) {
 
1443
        if (currFont != prevFont) {
 
1444
          rawWidth += prevFont->GetWidth(&aString[start], i - start);
 
1445
          prevFont = currFont;
 
1446
          start = i;
 
1447
        }
 
1448
      }
 
1449
      else {
 
1450
        prevFont = currFont;
 
1451
        start = i;
 
1452
      }
 
1453
    }
 
1454
 
 
1455
    if (prevFont) {
 
1456
      rawWidth += prevFont->GetWidth(&aString[start], i - start);
 
1457
    }
 
1458
 
 
1459
    aWidth = NSToCoordRound(rawWidth * mP2T);
 
1460
  }
 
1461
  if (nsnull != aFontID)
 
1462
    *aFontID = 0;
 
1463
 
 
1464
  return NS_OK;
 
1465
}
 
1466
 
 
1467
NS_IMETHODIMP
 
1468
nsRenderingContextXlib::GetTextDimensions(const char*       aString,
 
1469
                                          PRInt32           aLength,
 
1470
                                          PRInt32           aAvailWidth,
 
1471
                                          PRInt32*          aBreaks,
 
1472
                                          PRInt32           aNumBreaks,
 
1473
                                          nsTextDimensions& aDimensions,
 
1474
                                          PRInt32&          aNumCharsFit,
 
1475
                                          nsTextDimensions& aLastWordDimensions,
 
1476
                                          PRInt32*          aFontID)
 
1477
{
 
1478
  NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
 
1479
 
 
1480
  if (nsnull != mFontMetrics) {
 
1481
    // If we need to back up this state represents the last place we could
 
1482
    // break. We can use this to avoid remeasuring text
 
1483
    PRInt32 prevBreakState_BreakIndex = -1; // not known (hasn't been computed)
 
1484
    nscoord prevBreakState_Width = 0; // accumulated width to this point
 
1485
 
 
1486
    // Initialize OUT parameters
 
1487
    mFontMetrics->GetMaxAscent(aLastWordDimensions.ascent);
 
1488
    mFontMetrics->GetMaxDescent(aLastWordDimensions.descent);
 
1489
    aLastWordDimensions.width = -1;
 
1490
    aNumCharsFit = 0;
 
1491
 
 
1492
    // Iterate each character in the string and determine which font to use
 
1493
    nscoord width = 0;
 
1494
    PRInt32 start = 0;
 
1495
    nscoord aveCharWidth;
 
1496
    mFontMetrics->GetAveCharWidth(aveCharWidth);
 
1497
 
 
1498
    while (start < aLength) {
 
1499
      // Estimate how many characters will fit. Do that by diving the available
 
1500
      // space by the average character width. Make sure the estimated number
 
1501
      // of characters is at least 1
 
1502
      PRInt32 estimatedNumChars = 0;
 
1503
      if (aveCharWidth > 0) {
 
1504
        estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
 
1505
      }
 
1506
      if (estimatedNumChars < 1) {
 
1507
        estimatedNumChars = 1;
 
1508
      }
 
1509
 
 
1510
      // Find the nearest break offset
 
1511
      PRInt32 estimatedBreakOffset = start + estimatedNumChars;
 
1512
      PRInt32 breakIndex;
 
1513
      nscoord numChars;
 
1514
 
 
1515
      // Find the nearest place to break that is less than or equal to
 
1516
      // the estimated break offset
 
1517
      if (aLength <= estimatedBreakOffset) {
 
1518
        // All the characters should fit
 
1519
        numChars = aLength - start;
 
1520
        breakIndex = aNumBreaks - 1;
 
1521
      } 
 
1522
      else {
 
1523
        breakIndex = prevBreakState_BreakIndex;
 
1524
        while (((breakIndex + 1) < aNumBreaks) &&
 
1525
               (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
 
1526
          ++breakIndex;
 
1527
        }
 
1528
        if (breakIndex == prevBreakState_BreakIndex) {
 
1529
          ++breakIndex; // make sure we advanced past the previous break index
 
1530
        }
 
1531
        numChars = aBreaks[breakIndex] - start;
 
1532
      }
 
1533
 
 
1534
      // Measure the text
 
1535
      nscoord twWidth = 0;
 
1536
      if ((1 == numChars) && (aString[start] == ' ')) {
 
1537
        mFontMetrics->GetSpaceWidth(twWidth);
 
1538
      } 
 
1539
      else if (numChars > 0)
 
1540
        GetWidth( &aString[start], numChars, twWidth);
 
1541
 
 
1542
      // See if the text fits
 
1543
      PRBool  textFits = (twWidth + width) <= aAvailWidth;
 
1544
 
 
1545
      // If the text fits then update the width and the number of
 
1546
      // characters that fit
 
1547
      if (textFits) {
 
1548
        aNumCharsFit += numChars;
 
1549
        width += twWidth;
 
1550
        start += numChars;
 
1551
 
 
1552
        // This is a good spot to back up to if we need to so remember
 
1553
        // this state
 
1554
        prevBreakState_BreakIndex = breakIndex;
 
1555
        prevBreakState_Width = width;
 
1556
      }
 
1557
      else {
 
1558
        // See if we can just back up to the previous saved state and not
 
1559
        // have to measure any text
 
1560
        if (prevBreakState_BreakIndex > 0) {
 
1561
          // If the previous break index is just before the current break index
 
1562
          // then we can use it
 
1563
          if (prevBreakState_BreakIndex == (breakIndex - 1)) {
 
1564
            aNumCharsFit = aBreaks[prevBreakState_BreakIndex];
 
1565
            width = prevBreakState_Width;
 
1566
            break;
 
1567
          }
 
1568
        }
 
1569
 
 
1570
        // We can't just revert to the previous break state
 
1571
        if (0 == breakIndex) {
 
1572
          // There's no place to back up to, so even though the text doesn't fit
 
1573
          // return it anyway
 
1574
          aNumCharsFit += numChars;
 
1575
          width += twWidth;
 
1576
          break;
 
1577
        }
 
1578
 
 
1579
        // Repeatedly back up until we get to where the text fits or we're all
 
1580
        // the way back to the first word
 
1581
        width += twWidth;
 
1582
        while ((breakIndex >= 1) && (width > aAvailWidth)) {
 
1583
          twWidth = 0;
 
1584
          start = aBreaks[breakIndex - 1];
 
1585
          numChars = aBreaks[breakIndex] - start;
 
1586
          
 
1587
          if ((1 == numChars) && (aString[start] == ' ')) {
 
1588
            mFontMetrics->GetSpaceWidth(twWidth);
 
1589
          } 
 
1590
          else if (numChars > 0)
 
1591
            GetWidth( &aString[start], numChars, twWidth);
 
1592
 
 
1593
          width -= twWidth;
 
1594
          aNumCharsFit = start;
 
1595
          breakIndex--;
 
1596
        }
 
1597
        break;
 
1598
      }
 
1599
    }
 
1600
 
 
1601
    aDimensions.width = width;
 
1602
    mFontMetrics->GetMaxAscent(aDimensions.ascent);
 
1603
    mFontMetrics->GetMaxDescent(aDimensions.descent);
 
1604
 
 
1605
    return NS_OK;
 
1606
  }
 
1607
 
 
1608
  return NS_ERROR_FAILURE;
 
1609
}
 
1610
 
 
1611
struct BreakGetTextDimensionsData {
 
1612
  float    mP2T;               // IN
 
1613
  PRInt32  mAvailWidth;        // IN
 
1614
  PRInt32* mBreaks;            // IN
 
1615
  PRInt32  mNumBreaks;         // IN
 
1616
  nscoord  mSpaceWidth;        // IN
 
1617
  nscoord  mAveCharWidth;      // IN
 
1618
  PRInt32  mEstimatedNumChars; // IN (running -- to handle the edge case of one word)
 
1619
 
 
1620
  PRInt32  mNumCharsFit;  // IN/OUT -- accumulated number of chars that fit so far
 
1621
  nscoord  mWidth;        // IN/OUT -- accumulated width so far
 
1622
 
 
1623
  // If we need to back up, this state represents the last place
 
1624
  // we could break. We can use this to avoid remeasuring text
 
1625
  PRInt32 mPrevBreakState_BreakIndex; // IN/OUT, initialized as -1, i.e., not yet computed
 
1626
  nscoord mPrevBreakState_Width;      // IN/OUT, initialized as  0
 
1627
 
 
1628
  // Remember the fonts that we use so that we can deal with
 
1629
  // line-breaking in-between fonts later. mOffsets[0] is also used
 
1630
  // to initialize the current offset from where to start measuring
 
1631
  nsVoidArray* mFonts;   // OUT
 
1632
  nsVoidArray* mOffsets; // IN/OUT
 
1633
};
 
1634
 
 
1635
static PRBool PR_CALLBACK
 
1636
do_BreakGetTextDimensions(const nsFontSwitchXlib *aFontSwitch,
 
1637
                          const PRUnichar*        aSubstring,
 
1638
                          PRUint32                aSubstringLength,
 
1639
                          void*                   aData)
 
1640
{
 
1641
  nsFontXlib *fontXlib = aFontSwitch->mFontXlib;
 
1642
 
 
1643
  // Make sure the font is selected
 
1644
  BreakGetTextDimensionsData* data = (BreakGetTextDimensionsData*)aData;
 
1645
 
 
1646
  // Our current state relative to the _full_ string...
 
1647
  // This allows emulation of the previous code...
 
1648
  const PRUnichar* pstr = (const PRUnichar*)data->mOffsets->ElementAt(0);
 
1649
  PRInt32 numCharsFit = data->mNumCharsFit;
 
1650
  nscoord width = data->mWidth;
 
1651
  PRInt32 start = (PRInt32)(aSubstring - pstr);
 
1652
  PRInt32 i = start + aSubstringLength;
 
1653
  PRBool allDone = PR_FALSE;
 
1654
 
 
1655
  while (start < i) {
 
1656
    // Estimate how many characters will fit. Do that by dividing the
 
1657
    // available space by the average character width
 
1658
    PRInt32 estimatedNumChars = data->mEstimatedNumChars;
 
1659
    if (!estimatedNumChars && data->mAveCharWidth > 0) {
 
1660
      estimatedNumChars = (data->mAvailWidth - width) / data->mAveCharWidth;
 
1661
    }
 
1662
    // Make sure the estimated number of characters is at least 1
 
1663
    if (estimatedNumChars < 1) {
 
1664
      estimatedNumChars = 1;
 
1665
    }
 
1666
 
 
1667
    // Find the nearest break offset
 
1668
    PRInt32 estimatedBreakOffset = start + estimatedNumChars;
 
1669
    PRInt32 breakIndex = -1; // not yet computed
 
1670
    PRBool  inMiddleOfSegment = PR_FALSE;
 
1671
    nscoord numChars;
 
1672
 
 
1673
    // Avoid scanning the break array in the case where we think all
 
1674
    // the text should fit
 
1675
    if (i <= estimatedBreakOffset) {
 
1676
      // Everything should fit
 
1677
      numChars = i - start;
 
1678
    }
 
1679
    else {
 
1680
      // Find the nearest place to break that is less than or equal to
 
1681
      // the estimated break offset
 
1682
      breakIndex = data->mPrevBreakState_BreakIndex;
 
1683
      while (breakIndex + 1 < data->mNumBreaks &&
 
1684
             data->mBreaks[breakIndex + 1] <= estimatedBreakOffset) {
 
1685
        ++breakIndex;
 
1686
      }
 
1687
 
 
1688
      if (breakIndex == -1)
 
1689
        breakIndex = 0;
 
1690
 
 
1691
      // We found a place to break that is before the estimated break
 
1692
      // offset. Where we break depends on whether the text crosses a
 
1693
      // segment boundary
 
1694
      if (start < data->mBreaks[breakIndex]) {
 
1695
        // The text crosses at least one segment boundary so measure to the
 
1696
        // break point just before the estimated break offset
 
1697
        numChars = PR_MIN(data->mBreaks[breakIndex] - start, (PRInt32)aSubstringLength);
 
1698
      } 
 
1699
      else {
 
1700
        // See whether there is another segment boundary between this one
 
1701
        // and the end of the text
 
1702
        if ((breakIndex < (data->mNumBreaks - 1)) && (data->mBreaks[breakIndex] < i)) {
 
1703
          ++breakIndex;
 
1704
          numChars = PR_MIN(data->mBreaks[breakIndex] - start, (PRInt32)aSubstringLength);
 
1705
        }
 
1706
        else {
 
1707
          NS_ASSERTION(i != data->mBreaks[breakIndex], "don't expect to be at segment boundary");
 
1708
 
 
1709
          // The text is all within the same segment
 
1710
          numChars = i - start;
 
1711
 
 
1712
          // Remember we're in the middle of a segment and not between
 
1713
          // two segments
 
1714
          inMiddleOfSegment = PR_TRUE;
 
1715
        }
 
1716
      }
 
1717
    }
 
1718
 
 
1719
    // Measure the text
 
1720
    nscoord twWidth, pxWidth;
 
1721
    if ((1 == numChars) && (pstr[start] == ' ')) {
 
1722
      twWidth = data->mSpaceWidth;
 
1723
    }
 
1724
    else {
 
1725
      pxWidth = fontXlib->GetWidth(&pstr[start], numChars);
 
1726
      twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);
 
1727
    }
 
1728
 
 
1729
    // See if the text fits
 
1730
    PRBool textFits = (twWidth + width) <= data->mAvailWidth;
 
1731
 
 
1732
    // If the text fits then update the width and the number of
 
1733
    // characters that fit
 
1734
    if (textFits) {
 
1735
      numCharsFit += numChars;
 
1736
      width += twWidth;
 
1737
 
 
1738
      // If we computed the break index and we're not in the middle
 
1739
      // of a segment then this is a spot that we can back up to if
 
1740
      // we need to, so remember this state
 
1741
      if ((breakIndex != -1) && !inMiddleOfSegment) {
 
1742
        data->mPrevBreakState_BreakIndex = breakIndex;
 
1743
        data->mPrevBreakState_Width = width;
 
1744
      }
 
1745
    }
 
1746
    else {
 
1747
      // The text didn't fit. If we're out of room then we're all done
 
1748
      allDone = PR_TRUE;
 
1749
 
 
1750
      // See if we can just back up to the previous saved state and not
 
1751
      // have to measure any text
 
1752
      if (data->mPrevBreakState_BreakIndex != -1) {
 
1753
        PRBool canBackup;
 
1754
 
 
1755
        // If we're in the middle of a word then the break index
 
1756
        // must be the same if we can use it. If we're at a segment
 
1757
        // boundary, then if the saved state is for the previous
 
1758
        // break index then we can use it
 
1759
        if (inMiddleOfSegment) {
 
1760
          canBackup = data->mPrevBreakState_BreakIndex == breakIndex;
 
1761
        } else {
 
1762
          canBackup = data->mPrevBreakState_BreakIndex == (breakIndex - 1);
 
1763
        }
 
1764
 
 
1765
        if (canBackup) {
 
1766
          numCharsFit = data->mBreaks[data->mPrevBreakState_BreakIndex];
 
1767
          width = data->mPrevBreakState_Width;
 
1768
          break;
 
1769
        }
 
1770
      }
 
1771
 
 
1772
      // We can't just revert to the previous break state. Find the break
 
1773
      // index just before the end of the text
 
1774
      i = start + numChars;
 
1775
      if (breakIndex == -1) {
 
1776
        breakIndex = 0;
 
1777
        if (data->mBreaks[breakIndex] < i) {
 
1778
          while ((breakIndex + 1 < data->mNumBreaks) && (data->mBreaks[breakIndex + 1] < i)) {
 
1779
            ++breakIndex;
 
1780
          }
 
1781
        }
 
1782
      }
 
1783
 
 
1784
      if ((0 == breakIndex) && (i <= data->mBreaks[0])) {
 
1785
        // There's no place to back up to, so even though the text doesn't fit
 
1786
        // return it anyway
 
1787
        numCharsFit += numChars;
 
1788
        width += twWidth;
 
1789
 
 
1790
        // Edge case of one word: it could be that we just measured a fragment of the
 
1791
        // first word and its remainder involves other fonts, so we want to keep going
 
1792
        // until we at least measure the entire first word
 
1793
        if (numCharsFit < data->mBreaks[0]) {
 
1794
          allDone = PR_FALSE;
 
1795
          // From now on we don't care anymore what is the _real_ estimated
 
1796
          // number of characters that fits. Rather, we have no where to break
 
1797
          // and have to measure one word fully, but the real estimate is less
 
1798
          // than that one word. However, since the other bits of code rely on
 
1799
          // what is in "data->mEstimatedNumChars", we want to override
 
1800
          // "data->mEstimatedNumChars" and pass in what _has_ to be measured
 
1801
          // so that it is transparent to the other bits that depend on it.
 
1802
          data->mEstimatedNumChars = data->mBreaks[0] - numCharsFit;
 
1803
          start += numChars;
 
1804
        }
 
1805
 
 
1806
        break;
 
1807
      }
 
1808
 
 
1809
      // Repeatedly back up until we get to where the text fits or we're
 
1810
      // all the way back to the first word
 
1811
      width += twWidth;
 
1812
      while ((breakIndex >= 0) && (width > data->mAvailWidth)) {
 
1813
        twWidth = 0;
 
1814
        start = data->mBreaks[breakIndex];
 
1815
        numChars = i - start;
 
1816
        if ((1 == numChars) && (pstr[start] == ' ')) {
 
1817
          twWidth = data->mSpaceWidth;
 
1818
        }
 
1819
        else if (numChars > 0) {
 
1820
          pxWidth = fontXlib->GetWidth(&pstr[start], numChars);
 
1821
          twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);
 
1822
        }
 
1823
 
 
1824
        width -= twWidth;
 
1825
        numCharsFit = start;
 
1826
        --breakIndex;
 
1827
        i = start;
 
1828
      }
 
1829
    }
 
1830
 
 
1831
    start += numChars;
 
1832
  }
 
1833
 
 
1834
#ifdef DEBUG_rbs
 
1835
  NS_ASSERTION(allDone || start == i, "internal error");
 
1836
  NS_ASSERTION(allDone || data->mNumCharsFit != numCharsFit, "internal error");
 
1837
#endif /* DEBUG_rbs */
 
1838
 
 
1839
  if (data->mNumCharsFit != numCharsFit) {
 
1840
    // some text was actually retained
 
1841
    data->mWidth = width;
 
1842
    data->mNumCharsFit = numCharsFit;
 
1843
    data->mFonts->AppendElement(fontXlib);
 
1844
    data->mOffsets->AppendElement((void*)&pstr[numCharsFit]);
 
1845
  }
 
1846
 
 
1847
  if (allDone) {
 
1848
    // stop now
 
1849
    return PR_FALSE;
 
1850
  }
 
1851
 
 
1852
  return PR_TRUE; // don't stop if we still need to measure more characters
 
1853
}
 
1854
 
 
1855
NS_IMETHODIMP
 
1856
nsRenderingContextXlib::GetTextDimensions(const PRUnichar*  aString,
 
1857
                                          PRInt32           aLength,
 
1858
                                          PRInt32           aAvailWidth,
 
1859
                                          PRInt32*          aBreaks,
 
1860
                                          PRInt32           aNumBreaks,
 
1861
                                          nsTextDimensions& aDimensions,
 
1862
                                          PRInt32&          aNumCharsFit,
 
1863
                                          nsTextDimensions& aLastWordDimensions,
 
1864
                                          PRInt32*          aFontID)
 
1865
{
 
1866
  if (!mFontMetrics)
 
1867
    return NS_ERROR_FAILURE;
 
1868
 
 
1869
  nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
 
1870
 
 
1871
  nscoord spaceWidth, aveCharWidth;
 
1872
  metrics->GetSpaceWidth(spaceWidth);
 
1873
  metrics->GetAveCharWidth(aveCharWidth);
 
1874
 
 
1875
  // Note: aBreaks[] is supplied to us so that the first word is located
 
1876
  // at aString[0 .. aBreaks[0]-1] and more generally, the k-th word is
 
1877
  // located at aString[aBreaks[k-1] .. aBreaks[k]-1]. Whitespace can
 
1878
  // be included and each of them counts as a word in its own right.
 
1879
 
 
1880
  // Upon completion of glyph resolution, characters that can be
 
1881
  // represented with fonts[i] are at offsets[i] .. offsets[i+1]-1
 
1882
 
 
1883
  nsAutoVoidArray fonts, offsets;
 
1884
  offsets.AppendElement((void*)aString);
 
1885
 
 
1886
  BreakGetTextDimensionsData data = { mP2T, aAvailWidth, aBreaks, aNumBreaks,
 
1887
    spaceWidth, aveCharWidth, 0, 0, 0, -1, 0, &fonts, &offsets 
 
1888
  };
 
1889
 
 
1890
  metrics->ResolveForwards(aString, aLength, do_BreakGetTextDimensions, &data);
 
1891
 
 
1892
  if (aFontID) *aFontID = 0;
 
1893
 
 
1894
  aNumCharsFit = data.mNumCharsFit;
 
1895
  aDimensions.width = data.mWidth;
 
1896
 
 
1897
  ///////////////////
 
1898
  // Post-processing for the ascent and descent:
 
1899
  //
 
1900
  // The width of the last word is included in the final width, but its
 
1901
  // ascent and descent are kept aside for the moment. The problem is that
 
1902
  // line-breaking may occur _before_ the last word, and we don't want its
 
1903
  // ascent and descent to interfere. We can re-measure the last word and
 
1904
  // substract its width later. However, we need a special care for the ascent
 
1905
  // and descent at the break-point. The idea is to keep the ascent and descent
 
1906
  // of the last word separate, and let layout consider them later when it has
 
1907
  // determined that line-breaking doesn't occur before the last word.
 
1908
  //
 
1909
  // Therefore, there are two things to do:
 
1910
  // 1. Determine the ascent and descent up to where line-breaking may occur.
 
1911
  // 2. Determine the ascent and descent of the remainder.
 
1912
  //    For efficiency however, it is okay to bail out early if there is only
 
1913
  //    one font (in this case, the height of the last word has no special
 
1914
  //    effect on the total height).
 
1915
 
 
1916
  // aLastWordDimensions.width should be set to -1 to reply that we don't
 
1917
  // know the width of the last word since we measure multiple words
 
1918
  aLastWordDimensions.Clear();
 
1919
  aLastWordDimensions.width = -1;
 
1920
 
 
1921
  PRInt32 count = fonts.Count();
 
1922
  if (!count)
 
1923
    return NS_OK;
 
1924
  nsFontXlib *fontXlib = (nsFontXlib *)fonts[0];
 
1925
  NS_ASSERTION(fontXlib, "internal error in do_BreakGetTextDimensions");
 
1926
  aDimensions.ascent = fontXlib->mMaxAscent;
 
1927
  aDimensions.descent = fontXlib->mMaxDescent;
 
1928
 
 
1929
  // fast path - normal case, quick return if there is only one font
 
1930
  if (count == 1)
 
1931
    return NS_OK;
 
1932
 
 
1933
  // get the last break index.
 
1934
  // If there is only one word, we end up with lastBreakIndex = 0. We don't
 
1935
  // need to worry about aLastWordDimensions in this case too. But if we didn't
 
1936
  // return earlier, it would mean that the unique word needs several fonts
 
1937
  // and we will still have to loop over the fonts to return the final height
 
1938
  PRInt32 lastBreakIndex = 0;
 
1939
  while (aBreaks[lastBreakIndex] < aNumCharsFit)
 
1940
    ++lastBreakIndex;
 
1941
 
 
1942
  const PRUnichar* lastWord = (lastBreakIndex > 0) 
 
1943
    ? aString + aBreaks[lastBreakIndex-1]
 
1944
    : aString + aNumCharsFit; // let it point outside to play nice with the loop
 
1945
 
 
1946
  // now get the desired ascent and descent information... this is however
 
1947
  // a very fast loop of the order of the number of additional fonts
 
1948
 
 
1949
  PRInt32 currFont = 0;
 
1950
  const PRUnichar* pstr = aString;
 
1951
  const PRUnichar* last = aString + aNumCharsFit;
 
1952
 
 
1953
  while (pstr < last) {
 
1954
    fontXlib = (nsFontXlib*)fonts[currFont];
 
1955
    PRUnichar* nextOffset = (PRUnichar*)offsets[++currFont]; 
 
1956
 
 
1957
    // For consistent word-wrapping, we are going to handle the whitespace
 
1958
    // character with special care because a whitespace character can come
 
1959
    // from a font different from that of the previous word. If 'x', 'y', 'z',
 
1960
    // are Unicode points that require different fonts, we want 'xyz <br>'
 
1961
    // and 'xyz<br>' to have the same height because it gives a more stable
 
1962
    // rendering, especially when the window is resized at the edge of the word.
 
1963
    // If we don't do this, a 'tall' trailing whitespace, i.e., if the whitespace
 
1964
    // happens to come from a font with a bigger ascent and/or descent than all
 
1965
    // current fonts on the line, this can cause the next lines to be shifted
 
1966
    // down when the window is slowly resized to fit that whitespace.
 
1967
    if (*pstr == ' ') {
 
1968
      // skip pass the whitespace to ignore the height that it may contribute
 
1969
      ++pstr;
 
1970
      // get out if we reached the end
 
1971
      if (pstr == last) {
 
1972
        break;
 
1973
      }
 
1974
      // switch to the next font if we just passed the current font 
 
1975
      if (pstr == nextOffset) {
 
1976
        fontXlib = (nsFontXlib*)fonts[currFont];
 
1977
        nextOffset = (PRUnichar*)offsets[++currFont];
 
1978
      } 
 
1979
    }
 
1980
 
 
1981
    // see if the last word intersects with the current font
 
1982
    // (we are testing for 'nextOffset-1 >= lastWord' since the
 
1983
    // current font ends at nextOffset-1)
 
1984
    if (nextOffset > lastWord) {
 
1985
      if (aLastWordDimensions.ascent < fontXlib->mMaxAscent) {
 
1986
        aLastWordDimensions.ascent = fontXlib->mMaxAscent;
 
1987
      }
 
1988
      if (aLastWordDimensions.descent < fontXlib->mMaxDescent) {
 
1989
        aLastWordDimensions.descent = fontXlib->mMaxDescent;
 
1990
      }
 
1991
    }
 
1992
 
 
1993
    // see if we have not reached the last word yet
 
1994
    if (pstr < lastWord) {
 
1995
      if (aDimensions.ascent < fontXlib->mMaxAscent) {
 
1996
        aDimensions.ascent = fontXlib->mMaxAscent;
 
1997
      }
 
1998
      if (aDimensions.descent < fontXlib->mMaxDescent) {
 
1999
        aDimensions.descent = fontXlib->mMaxDescent;
 
2000
      }
 
2001
    }
 
2002
 
 
2003
    // advance to where the next font starts
 
2004
    pstr = nextOffset;
 
2005
  }
 
2006
 
 
2007
  return NS_OK;
 
2008
}
 
2009
 
 
2010
NS_IMETHODIMP
 
2011
nsRenderingContextXlib::GetTextDimensions(const char* aString, PRUint32 aLength,
 
2012
                                          nsTextDimensions& aDimensions)
 
2013
{
 
2014
  mFontMetrics->GetMaxAscent(aDimensions.ascent);
 
2015
  mFontMetrics->GetMaxDescent(aDimensions.descent);
 
2016
  return GetWidth(aString, aLength, aDimensions.width);
 
2017
}
 
2018
 
 
2019
NS_IMETHODIMP
 
2020
nsRenderingContextXlib::GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
 
2021
                                          nsTextDimensions& aDimensions, PRInt32* aFontID)
 
2022
{
 
2023
  aDimensions.Clear();
 
2024
  if (0 < aLength) {
 
2025
    NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
 
2026
 
 
2027
    nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
 
2028
 
 
2029
    NS_ENSURE_TRUE(metrics != nsnull, NS_ERROR_FAILURE);
 
2030
 
 
2031
    nsFontXlib* prevFont = nsnull;
 
2032
    int rawWidth = 0, rawAscent = 0, rawDescent = 0;
 
2033
    PRUint32 start = 0;
 
2034
    PRUint32 i;
 
2035
    for (i = 0; i < aLength; i++) {
 
2036
      PRUnichar c = aString[i];
 
2037
      nsFontXlib  *currFont = nsnull;
 
2038
      nsFontXlib **font = metrics->mLoadedFonts;
 
2039
      nsFontXlib **end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
 
2040
      while (font < end) {
 
2041
        if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
 
2042
          currFont = *font;
 
2043
          goto FoundFont; // for speed -- avoid "if" statement
 
2044
        }
 
2045
        font++;
 
2046
      }
 
2047
      currFont = metrics->FindFont(c);
 
2048
FoundFont:
 
2049
      // XXX avoid this test by duplicating code -- erik
 
2050
      if (prevFont) {
 
2051
        if (currFont != prevFont) {
 
2052
          rawWidth += prevFont->GetWidth(&aString[start], i - start);
 
2053
          if (rawAscent < prevFont->mMaxAscent)
 
2054
            rawAscent = prevFont->mMaxAscent;
 
2055
          if (rawDescent < prevFont->mMaxDescent)
 
2056
            rawDescent = prevFont->mMaxDescent;
 
2057
          prevFont = currFont;
 
2058
          start = i;
 
2059
        }
 
2060
      }
 
2061
      else {
 
2062
        prevFont = currFont;
 
2063
        start = i;
 
2064
      }
 
2065
    }
 
2066
 
 
2067
    if (prevFont) {
 
2068
      rawWidth += prevFont->GetWidth(&aString[start], i - start);
 
2069
      if (rawAscent < prevFont->mMaxAscent)
 
2070
        rawAscent = prevFont->mMaxAscent;
 
2071
      if (rawDescent < prevFont->mMaxDescent)
 
2072
        rawDescent = prevFont->mMaxDescent;
 
2073
    }
 
2074
 
 
2075
    aDimensions.width = NSToCoordRound(rawWidth * mP2T);
 
2076
    aDimensions.ascent = NSToCoordRound(rawAscent * mP2T);
 
2077
    aDimensions.descent = NSToCoordRound(rawDescent * mP2T);
 
2078
  }
 
2079
  if (nsnull != aFontID)
 
2080
    *aFontID = 0;
 
2081
 
 
2082
  return NS_OK;
 
2083
}
 
2084
 
 
2085
NS_IMETHODIMP
 
2086
nsRenderingContextXlib::DrawString(const char *aString, PRUint32 aLength,
 
2087
                                   nscoord aX, nscoord aY,
 
2088
                                   const nscoord* aSpacing)
 
2089
{
 
2090
  nsresult res = NS_OK;
 
2091
 
 
2092
  if (aLength) {
 
2093
    NS_ENSURE_TRUE(mTranMatrix  != nsnull, NS_ERROR_FAILURE);
 
2094
    NS_ENSURE_TRUE(mSurface     != nsnull, NS_ERROR_FAILURE);
 
2095
    NS_ENSURE_TRUE(aString      != nsnull, NS_ERROR_FAILURE);
 
2096
    NS_ENSURE_TRUE(mCurrentFont != nsnull, NS_ERROR_FAILURE);
 
2097
 
 
2098
    nscoord x = aX;
 
2099
    nscoord y = aY;
 
2100
 
 
2101
    UpdateGC();
 
2102
 
 
2103
    nsXFont *xFont = mCurrentFont->GetXFont();
 
2104
    if (nsnull != aSpacing) {
 
2105
      // Render the string, one character at a time...
 
2106
      const char* end = aString + aLength;
 
2107
      while (aString < end) {
 
2108
        char ch = *aString++;
 
2109
        nscoord xx = x;
 
2110
        nscoord yy = y;
 
2111
        mTranMatrix->TransformCoord(&xx, &yy);
 
2112
#ifdef USE_FREETYPE
 
2113
        if (mCurrentFont->IsFreeTypeFont()) {
 
2114
          PRUnichar unichars[WIDEN_8_TO_16_BUF_SIZE];
 
2115
          // need to fix this for long strings
 
2116
          PRUint32 len = PR_MIN(aLength, WIDEN_8_TO_16_BUF_SIZE);
 
2117
          // convert 7 bit data to unicode
 
2118
          // this function is only supposed to be called for ascii data
 
2119
          for (PRUint32 i=0; i<len; i++) {
 
2120
            unichars[i] = (PRUnichar)((unsigned char)aString[i]);
 
2121
          }
 
2122
          res = mCurrentFont->DrawString(this, mSurface, xx, yy,
 
2123
                                         unichars, len);
 
2124
        }
 
2125
        else
 
2126
#endif /* USE_FREETYPE */
 
2127
        if (!mCurrentFont->GetXFontIs10646()) {
 
2128
          // 8 bit data with an 8 bit font
 
2129
          NS_ASSERTION(xFont->IsSingleByte(),"wrong string/font size");
 
2130
          xFont->DrawText8(mSurface->GetDrawable(), *mGC, xx, yy, &ch, 1);
 
2131
        }
 
2132
        else {
 
2133
          // we have 8 bit data but a 16 bit font
 
2134
          NS_ASSERTION(!xFont->IsSingleByte(),"wrong string/font size");
 
2135
          Widen8To16AndDraw(mSurface->GetDrawable(), xFont, *mGC,
 
2136
                                                xx, yy, &ch, 1);
 
2137
        }
 
2138
        x += *aSpacing++;
 
2139
      }
 
2140
    }
 
2141
    else {
 
2142
      mTranMatrix->TransformCoord(&x, &y);
 
2143
#ifdef USE_FREETYPE
 
2144
      if (mCurrentFont->IsFreeTypeFont()) {
 
2145
        PRUnichar unichars[WIDEN_8_TO_16_BUF_SIZE];
 
2146
        // need to fix this for long strings
 
2147
        PRUint32 len = PR_MIN(aLength, WIDEN_8_TO_16_BUF_SIZE);
 
2148
        // convert 7 bit data to unicode
 
2149
        // this function is only supposed to be called for ascii data
 
2150
        for (PRUint32 i=0; i<len; i++) {
 
2151
          unichars[i] = (PRUnichar)((unsigned char)aString[i]);
 
2152
        }
 
2153
        res = mCurrentFont->DrawString(this, mSurface, x, y,
 
2154
                                       unichars, len);
 
2155
      }
 
2156
      else
 
2157
#endif /* USE_FREETYPE */
 
2158
      if (!mCurrentFont->GetXFontIs10646()) { // keep 8 bit path fast
 
2159
        // 8 bit data with an 8 bit font
 
2160
        NS_ASSERTION(xFont->IsSingleByte(),"wrong string/font size");
 
2161
        xFont->DrawText8(mSurface->GetDrawable(), *mGC, x, y, aString, aLength);
 
2162
      }
 
2163
      else {
 
2164
        // we have 8 bit data but a 16 bit font
 
2165
        NS_ASSERTION(!xFont->IsSingleByte(),"wrong string/font size");
 
2166
        Widen8To16AndDraw(mSurface->GetDrawable(), xFont, *mGC,
 
2167
                                             x, y, aString, aLength);
 
2168
      }
 
2169
    }
 
2170
  }
 
2171
 
 
2172
#ifdef DISABLED_FOR_NOW
 
2173
  //this is no longer to be done by this API, but another
 
2174
  //will take it's place that will need this code again. MMP
 
2175
  if (mFontMetrics)
 
2176
  {
 
2177
    const nsFont *font;
 
2178
    mFontMetrics->GetFont(font);
 
2179
    PRUint8 deco = font->decorations;
 
2180
 
 
2181
    if (deco & NS_FONT_DECORATION_OVERLINE)
 
2182
      DrawLine(aX, aY, aX + aWidth, aY);
 
2183
 
 
2184
    if (deco & NS_FONT_DECORATION_UNDERLINE)
 
2185
    {
 
2186
      nscoord ascent,descent;
 
2187
 
 
2188
      mFontMetrics->GetMaxAscent(ascent);
 
2189
      mFontMetrics->GetMaxDescent(descent);
 
2190
 
 
2191
      DrawLine(aX, aY + ascent + (descent >> 1),
 
2192
               aX + aWidth, aY + ascent + (descent >> 1));
 
2193
    }
 
2194
 
 
2195
    if (deco & NS_FONT_DECORATION_LINE_THROUGH)
 
2196
    {
 
2197
      nscoord height;
 
2198
 
 
2199
      mFontMetrics->GetHeight(height);
 
2200
 
 
2201
      DrawLine(aX, aY + (height >> 1), aX + aWidth, aY + (height >> 1));
 
2202
    }
 
2203
  }
 
2204
#endif /* DISABLED_FOR_NOW */
 
2205
 
 
2206
  return res;
 
2207
}
 
2208
 
 
2209
NS_IMETHODIMP
 
2210
nsRenderingContextXlib::DrawString(const PRUnichar* aString, PRUint32 aLength,
 
2211
                                   nscoord aX, nscoord aY,
 
2212
                                   PRInt32 aFontID,
 
2213
                                   const nscoord* aSpacing)
 
2214
{
 
2215
  if (aLength && mFontMetrics) {
 
2216
    NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
2217
    NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
2218
    NS_ENSURE_TRUE(aString     != nsnull, NS_ERROR_FAILURE);
 
2219
 
 
2220
    nscoord x = aX;
 
2221
    nscoord y = aY;
 
2222
 
 
2223
    mTranMatrix->TransformCoord(&x, &y);
 
2224
 
 
2225
    nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
 
2226
    nsFontXlib *prevFont = nsnull;
 
2227
    PRUint32 start = 0;
 
2228
    PRUint32 i;
 
2229
    for (i = 0; i < aLength; i++) {
 
2230
      PRUnichar c = aString[i];
 
2231
      nsFontXlib* currFont = nsnull;
 
2232
      nsFontXlib** font = metrics->mLoadedFonts;
 
2233
      nsFontXlib** lastFont = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
 
2234
      while (font < lastFont) {
 
2235
        if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
 
2236
          currFont = *font;
 
2237
          goto FoundFont; // for speed -- avoid "if" statement
 
2238
        }
 
2239
        font++;
 
2240
      }
 
2241
      currFont = metrics->FindFont(c);
 
2242
FoundFont:
 
2243
      // XXX avoid this test by duplicating code -- erik
 
2244
      if (prevFont) {
 
2245
        if (currFont != prevFont) {
 
2246
          if (aSpacing) {
 
2247
            const PRUnichar* str = &aString[start];
 
2248
            const PRUnichar* end = &aString[i];
 
2249
 
 
2250
            // save off mCurrentFont and set it so that we cache the GC's font correctly
 
2251
            nsFontXlib *oldFont = mCurrentFont;
 
2252
            mCurrentFont = prevFont;
 
2253
            UpdateGC();
 
2254
 
 
2255
            while (str < end) {
 
2256
              x = aX;
 
2257
              y = aY;
 
2258
              mTranMatrix->TransformCoord(&x, &y);
 
2259
              prevFont->DrawString(this, mSurface, x, y, str, 1);
 
2260
              aX += *aSpacing++;
 
2261
              str++;
 
2262
            }
 
2263
            mCurrentFont = oldFont;
 
2264
          }
 
2265
          else {
 
2266
            nsFontXlib *oldFont = mCurrentFont;
 
2267
            mCurrentFont = prevFont;
 
2268
            UpdateGC();
 
2269
            x += prevFont->DrawString(this, mSurface, x, y, &aString[start],
 
2270
                                      i - start);
 
2271
            mCurrentFont = oldFont;
 
2272
          }
 
2273
          prevFont = currFont;
 
2274
          start = i;
 
2275
        }
 
2276
      }
 
2277
      else {
 
2278
        prevFont = currFont;
 
2279
        start = i;
 
2280
      }
 
2281
    }
 
2282
 
 
2283
    if (prevFont) {
 
2284
      nsFontXlib *oldFont = mCurrentFont;
 
2285
      mCurrentFont = prevFont;
 
2286
      UpdateGC();
 
2287
    
 
2288
      if (aSpacing) {
 
2289
        const PRUnichar* str = &aString[start];
 
2290
        const PRUnichar* end = &aString[i];
 
2291
        while (str < end) {
 
2292
          x = aX;
 
2293
          y = aY;
 
2294
          mTranMatrix->TransformCoord(&x, &y);
 
2295
          prevFont->DrawString(this, mSurface, x, y, str, 1);
 
2296
          aX += *aSpacing++;
 
2297
          str++;
 
2298
        }
 
2299
      }
 
2300
      else {
 
2301
        prevFont->DrawString(this, mSurface, x, y, &aString[start], i - start);
 
2302
      }
 
2303
 
 
2304
      mCurrentFont = oldFont;
 
2305
    }
 
2306
  }
 
2307
 
 
2308
  return NS_OK;
 
2309
}
 
2310
 
 
2311
NS_IMETHODIMP
 
2312
nsRenderingContextXlib::DrawString(const nsString& aString,
 
2313
                                   nscoord aX, nscoord aY,
 
2314
                                   PRInt32 aFontID,
 
2315
                                   const nscoord* aSpacing)
 
2316
{
 
2317
  return DrawString(aString.get(), aString.Length(),
 
2318
                    aX, aY, aFontID, aSpacing);
 
2319
}
 
2320
 
 
2321
NS_IMETHODIMP
 
2322
nsRenderingContextXlib::CopyOffScreenBits(nsDrawingSurface aSrcSurf, PRInt32 aSrcX, PRInt32 aSrcY,
 
2323
                                          const nsRect &aDestBounds, PRUint32 aCopyFlags)
 
2324
{
 
2325
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CopyOffScreenBits()\n"));
 
2326
 
 
2327
  PRInt32                 srcX = aSrcX;
 
2328
  PRInt32                 srcY = aSrcY;
 
2329
  nsRect                  drect = aDestBounds;
 
2330
  nsIDrawingSurfaceXlib  *destsurf;
 
2331
 
 
2332
  NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
 
2333
  NS_ENSURE_TRUE(mSurface    != nsnull, NS_ERROR_FAILURE);
 
2334
  NS_ENSURE_TRUE(aSrcSurf    != nsnull, NS_ERROR_FAILURE);
 
2335
    
 
2336
  if (aCopyFlags & NS_COPYBITS_TO_BACK_BUFFER) {
 
2337
    destsurf = mSurface;
 
2338
  }
 
2339
  else
 
2340
  {
 
2341
    NS_ENSURE_TRUE(mOffscreenSurface != nsnull, NS_ERROR_FAILURE);
 
2342
    destsurf = mOffscreenSurface;
 
2343
  }
 
2344
  
 
2345
  if (aCopyFlags & NS_COPYBITS_XFORM_SOURCE_VALUES)
 
2346
    mTranMatrix->TransformCoord(&srcX, &srcY);
 
2347
  
 
2348
  if (aCopyFlags & NS_COPYBITS_XFORM_DEST_VALUES)
 
2349
    mTranMatrix->TransformCoord(&drect.x, &drect.y, &drect.width, &drect.height);
 
2350
  
 
2351
  //XXX flags are unused. that would seem to mean that there is
 
2352
  //inefficiency somewhere... MMP
 
2353
 
 
2354
  UpdateGC();
 
2355
  Drawable destdrawable; destsurf->GetDrawable(destdrawable);
 
2356
  Drawable srcdrawable; ((nsIDrawingSurfaceXlib *)aSrcSurf)->GetDrawable(srcdrawable);
 
2357
 
 
2358
  ::XCopyArea(mDisplay,
 
2359
              srcdrawable,
 
2360
              destdrawable,
 
2361
              *mGC,
 
2362
              srcX, srcY,
 
2363
              drect.width, drect.height,
 
2364
              drect.x, drect.y);
 
2365
 
 
2366
  return NS_OK;
 
2367
}
 
2368
 
 
2369
NS_IMETHODIMP
 
2370
nsRenderingContextXlib::RetrieveCurrentNativeGraphicData(PRUint32 * ngd)
 
2371
{
 
2372
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::RetrieveCurrentNativeGraphicData()\n"));
 
2373
  return NS_OK;
 
2374
}
 
2375
 
 
2376
#ifdef MOZ_MATHML
 
2377
static
 
2378
void Widen8To16AndGetTextExtents(nsXFont    *xFont,  
 
2379
                                 const char *text,
 
2380
                                 int         text_length,
 
2381
                                 int        *lbearing,
 
2382
                                 int        *rbearing,
 
2383
                                 int        *width,
 
2384
                                 int        *ascent,
 
2385
                                 int        *descent)
 
2386
{
 
2387
  NS_ASSERTION(!xFont->IsSingleByte(),"wrong string/font size");
 
2388
  XChar2b buf[WIDEN_8_TO_16_BUF_SIZE];
 
2389
  XChar2b *p = buf;
 
2390
  int uchar_size;
 
2391
 
 
2392
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
2393
    p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
 
2394
    if (!p) { // handle malloc failure
 
2395
      *lbearing = 0;
 
2396
      *rbearing = 0;
 
2397
      *width    = 0;
 
2398
      *ascent   = 0;
 
2399
      *descent  = 0;
 
2400
      return;
 
2401
    }
 
2402
  }
 
2403
 
 
2404
  uchar_size = Widen8To16AndMove(text, text_length, p);
 
2405
  xFont->TextExtents16(p, uchar_size/2,
 
2406
                       lbearing, 
 
2407
                       rbearing, 
 
2408
                       width, 
 
2409
                       ascent, 
 
2410
                       descent);
 
2411
 
 
2412
  if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
 
2413
    free((char*)p);
 
2414
  }
 
2415
}
 
2416
 
 
2417
NS_IMETHODIMP
 
2418
nsRenderingContextXlib::GetBoundingMetrics(const char*        aString, 
 
2419
                                           PRUint32           aLength,
 
2420
                                           nsBoundingMetrics& aBoundingMetrics)
 
2421
{
 
2422
  nsresult res = NS_OK;
 
2423
  aBoundingMetrics.Clear();
 
2424
  if (aString && 0 < aLength) {
 
2425
    NS_ENSURE_TRUE(mCurrentFont != nsnull, NS_ERROR_FAILURE);
 
2426
    nsXFont *xFont = mCurrentFont->GetXFont();
 
2427
#ifdef USE_FREETYPE
 
2428
    if (mCurrentFont->IsFreeTypeFont()) {
 
2429
      PRUnichar unichars[WIDEN_8_TO_16_BUF_SIZE];
 
2430
      // need to fix this for long strings
 
2431
      PRUint32 len = PR_MIN(aLength, WIDEN_8_TO_16_BUF_SIZE);
 
2432
      // convert 7 bit data to unicode
 
2433
      // this function is only supposed to be called for ascii data
 
2434
      for (PRUint32 i=0; i<len; i++) {
 
2435
        unichars[i] = (PRUnichar)((unsigned char)aString[i]);
 
2436
      }
 
2437
      res = mCurrentFont->GetBoundingMetrics(unichars, len,
 
2438
                                            aBoundingMetrics);
 
2439
    }
 
2440
    else
 
2441
#endif /* USE_FREETYPE */
 
2442
    if (!mCurrentFont->GetXFontIs10646()) {
 
2443
        // 8 bit data with an 8 bit font
 
2444
        NS_ASSERTION(xFont->IsSingleByte(), "GetBoundingMetrics: wrong string/font size");
 
2445
        xFont->TextExtents8(aString, aLength,
 
2446
                            &aBoundingMetrics.leftBearing, 
 
2447
                            &aBoundingMetrics.rightBearing, 
 
2448
                            &aBoundingMetrics.width, 
 
2449
                            &aBoundingMetrics.ascent, 
 
2450
                            &aBoundingMetrics.descent);
 
2451
    }
 
2452
    else {
 
2453
        // we have 8 bit data but a 16 bit font
 
2454
        NS_ASSERTION(!xFont->IsSingleByte(), "GetBoundingMetrics: wrong string/font size");
 
2455
        Widen8To16AndGetTextExtents(mCurrentFont->GetXFont(), aString, aLength,
 
2456
                                    &aBoundingMetrics.leftBearing, 
 
2457
                                    &aBoundingMetrics.rightBearing, 
 
2458
                                    &aBoundingMetrics.width, 
 
2459
                                    &aBoundingMetrics.ascent, 
 
2460
                                    &aBoundingMetrics.descent);
 
2461
    }
 
2462
 
 
2463
    aBoundingMetrics.leftBearing = NSToCoordRound(aBoundingMetrics.leftBearing * mP2T);
 
2464
    aBoundingMetrics.rightBearing = NSToCoordRound(aBoundingMetrics.rightBearing * mP2T);
 
2465
    aBoundingMetrics.width = NSToCoordRound(aBoundingMetrics.width * mP2T);
 
2466
    aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * mP2T);
 
2467
    aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * mP2T);
 
2468
  }
 
2469
 
 
2470
  return res;
 
2471
}
 
2472
 
 
2473
NS_IMETHODIMP
 
2474
nsRenderingContextXlib::GetBoundingMetrics(const PRUnichar*   aString, 
 
2475
                                           PRUint32           aLength,
 
2476
                                           nsBoundingMetrics& aBoundingMetrics,
 
2477
                                           PRInt32*           aFontID)
 
2478
{
 
2479
  aBoundingMetrics.Clear(); 
 
2480
  if (0 < aLength) {
 
2481
    NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
 
2482
 
 
2483
    nsFontMetricsXlib *metrics  = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
 
2484
    nsFontXlib        *prevFont = nsnull;
 
2485
 
 
2486
    nsBoundingMetrics rawbm;
 
2487
    PRBool firstTime = PR_TRUE;
 
2488
    PRUint32 start = 0;
 
2489
    PRUint32 i;
 
2490
    for (i = 0; i < aLength; i++) {
 
2491
      PRUnichar c = aString[i];
 
2492
      nsFontXlib  *currFont = nsnull;
 
2493
      nsFontXlib **font = metrics->mLoadedFonts;
 
2494
      nsFontXlib **end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
 
2495
      while (font < end) {
 
2496
        if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
 
2497
          currFont = *font;
 
2498
          goto FoundFont; // for speed -- avoid "if" statement
 
2499
        }
 
2500
        font++;
 
2501
      }
 
2502
      currFont = metrics->FindFont(c);
 
2503
  FoundFont:
 
2504
      // XXX avoid this test by duplicating code -- erik
 
2505
      if (prevFont) {
 
2506
        if (currFont != prevFont) {
 
2507
          prevFont->GetBoundingMetrics((const PRUnichar*) &aString[start],
 
2508
                                       i - start, rawbm);
 
2509
          if (firstTime) {
 
2510
            firstTime = PR_FALSE;
 
2511
            aBoundingMetrics = rawbm;
 
2512
          } 
 
2513
          else {
 
2514
            aBoundingMetrics += rawbm;
 
2515
          }
 
2516
          prevFont = currFont;
 
2517
          start = i;
 
2518
        }
 
2519
      }
 
2520
      else {
 
2521
        prevFont = currFont;
 
2522
        start = i;
 
2523
      }
 
2524
    }
 
2525
    
 
2526
    if (prevFont) {
 
2527
      prevFont->GetBoundingMetrics((const PRUnichar*) &aString[start],
 
2528
                                   i - start, rawbm);
 
2529
      if (firstTime) {
 
2530
        aBoundingMetrics = rawbm;
 
2531
      }
 
2532
      else {
 
2533
        aBoundingMetrics += rawbm;
 
2534
      }
 
2535
    }
 
2536
    // convert to app units
 
2537
    aBoundingMetrics.leftBearing = NSToCoordRound(aBoundingMetrics.leftBearing * mP2T);
 
2538
    aBoundingMetrics.rightBearing = NSToCoordRound(aBoundingMetrics.rightBearing * mP2T);
 
2539
    aBoundingMetrics.width = NSToCoordRound(aBoundingMetrics.width * mP2T);
 
2540
    aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * mP2T);
 
2541
    aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * mP2T);
 
2542
  }
 
2543
  if (nsnull != aFontID)
 
2544
    *aFontID = 0;
 
2545
 
 
2546
  return NS_OK;
 
2547
}
 
2548
#endif /* MOZ_MATHML */
 
2549
 
 
2550
NS_IMETHODIMP
 
2551
nsRenderingContextXlib::DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint)
 
2552
{
 
2553
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawImage()\n"));
 
2554
  UpdateGC();
 
2555
  return nsRenderingContextImpl::DrawImage(aImage, aSrcRect, aDestPoint);
 
2556
}
 
2557
 
 
2558
NS_IMETHODIMP
 
2559
nsRenderingContextXlib::DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect)
 
2560
{
 
2561
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawScaledImage()\n"));
 
2562
  UpdateGC();
 
2563
  return nsRenderingContextImpl::DrawScaledImage(aImage, aSrcRect, aDestRect);
 
2564
}
 
2565
 
 
2566
NS_IMETHODIMP
 
2567
nsRenderingContextXlib::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
 
2568
{
 
2569
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetBackbuffer()\n"));
 
2570
  /* Do not cache the backbuffer. On X11 it is more efficient to allocate
 
2571
   * the backbuffer as needed and it doesn't cause a performance hit. @see bug 95952 */
 
2572
  return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE);
 
2573
}
 
2574
 
 
2575
NS_IMETHODIMP
 
2576
nsRenderingContextXlib::ReleaseBackbuffer(void) 
 
2577
{
 
2578
  PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::ReleaseBackbuffer()\n"));
 
2579
  /* Do not cache the backbuffer. On X11 it is more efficient to allocate
 
2580
   * the backbuffer as needed and it doesn't cause a performance hit. @see bug 95952 */
 
2581
  return DestroyCachedBackbuffer();
 
2582
}
 
2583