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
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/
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
15
* The Original Code is mozilla.org code.
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.
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>
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.
43
* ***** END LICENSE BLOCK ***** */
45
#include "nsRenderingContextXlib.h"
46
#include "nsFontMetricsXlib.h"
47
#include "nsCompressedCharMap.h"
53
#include "nsGCCache.h"
54
#include "imgIContainer.h"
55
#include "gfxIImageFrame.h"
56
#include "nsIInterfaceRequestor.h"
57
#include "nsIInterfaceRequestorUtils.h"
59
#define NS_TO_XLIBRGB_RGB(ns) (ns & 0xff) << 16 | (ns & 0xff00) | ((ns >> 16) & 0xff)
61
NS_IMPL_ISUPPORTS1(nsRenderingContextXlib, nsIRenderingContext)
64
static PRLogModuleInfo * RenderingContextXlibLM = PR_NewLogModule("RenderingContextXlib");
65
#endif /* PR_LOGGING */
67
/* Handle drawing 8 bit data with a 16 bit font */
68
static void Widen8To16AndDraw(Drawable drawable,
77
class nsRenderingContextXlibContext
80
nsGCCacheXlib mGcCache;
83
nsresult CreateRenderingContextXlibContext(nsIDeviceContext *aDevice, nsRenderingContextXlibContext **aContext)
85
nsRenderingContextXlibContext *rcctx;
89
rcctx = new nsRenderingContextXlibContext();
91
return NS_ERROR_OUT_OF_MEMORY;
93
/* No |Init()|-function to call (yet) */
99
void DeleteRenderingContextXlibContext(nsRenderingContextXlibContext *aContext)
112
nsTransform2D *mMatrix;
113
nsCOMPtr<nsIRegion> mClipRegion;
115
nsLineStyle mLineStyle;
116
nsCOMPtr<nsIFontMetrics> mFontMetrics;
119
MOZ_DECL_CTOR_COUNTER(GraphicsState)
121
GraphicsState::GraphicsState() :
123
mColor(NS_RGB(0, 0, 0)),
124
mLineStyle(nsLineStyle_kSolid),
127
MOZ_COUNT_CTOR(GraphicsState);
131
GraphicsState::~GraphicsState()
133
MOZ_COUNT_DTOR(GraphicsState);
137
nsRenderingContextXlib::nsRenderingContextXlib() :
138
nsRenderingContextImpl(),
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...
146
mCurrentFont(nsnull),
147
mCurrentLineStyle(nsLineStyle_kSolid)
149
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::nsRenderingContextXlib()\n"));
154
nsRenderingContextXlib::~nsRenderingContextXlib()
156
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::~nsRenderingContextXlib()\n"));
157
/* Destroy the State Machine */
158
PRInt32 cnt = mStateCache.Count();
173
nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsIWidget *aWindow)
175
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Init(DeviceContext, Widget)\n"));
176
nsDrawingSurfaceXlibImpl *surf; // saves some cast stunts
178
NS_ENSURE_TRUE(aContext != nsnull, NS_ERROR_NULL_POINTER);
179
NS_ENSURE_TRUE(aWindow != nsnull, NS_ERROR_NULL_POINTER);
182
nsIDeviceContext *dc = mContext;
183
NS_STATIC_CAST(nsDeviceContextX *, dc)->GetXlibRgbHandle(mXlibRgbHandle);
184
mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
186
surf = new nsDrawingSurfaceXlibImpl();
189
Drawable win = (Drawable)aWindow->GetNativeData(NS_NATIVE_WINDOW);
190
xGC *gc = (xGC *)aWindow->GetNativeData(NS_NATIVE_GRAPHIC);
192
surf->Init(mXlibRgbHandle,
196
mOffscreenSurface = mSurface = surf;
197
/* aWindow->GetNativeData() ref'd the gc */
205
nsRenderingContextXlib::Init(nsIDeviceContext* aContext, nsDrawingSurface aSurface)
207
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContxtXlib::Init(DeviceContext, DrawingSurface)\n"));
209
NS_ENSURE_TRUE(nsnull != aContext, NS_ERROR_NULL_POINTER);
212
nsIDeviceContext *dc = mContext;
213
NS_STATIC_CAST(nsDeviceContextX *, dc)->GetXlibRgbHandle(mXlibRgbHandle);
214
mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
216
mSurface = (nsIDrawingSurfaceXlib *)aSurface;
217
mOffscreenSurface = mSurface;
222
nsresult nsRenderingContextXlib::CommonInit(void)
224
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContxtXlib::CommonInit()\n"));
225
// put common stuff in here.
227
unsigned int width, height, border, depth;
230
Drawable drawable; mSurface->GetDrawable(drawable);
232
::XGetGeometry(mDisplay,
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));
248
mClipRegion = new nsRegionXlib();
250
return NS_ERROR_OUT_OF_MEMORY;
252
mClipRegion->SetTo(0, 0, width, height);
254
mP2T = mContext->DevUnitsToAppUnits();
256
app2dev = mContext->AppUnitsToDevUnits();
257
mTranMatrix->AddScale(app2dev, app2dev);
263
nsRenderingContextXlib::GetHints(PRUint32& aResult)
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;
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) ... ;-(
276
#ifndef CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT
278
#define CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT 1
280
#endif /* !CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT */
282
static PRBool enable_fast_measure;
283
static PRBool getenv_done = PR_FALSE;
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
292
#ifdef CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT
293
enable_fast_measure = PR_TRUE;
295
enable_fast_measure = PR_FALSE;
296
#endif /* CPU_DOES_NOT_REQUIRE_NATURAL_ALIGNMENT */
298
if (PR_GetEnv("MOZILLA_GFX_ENABLE_FAST_MEASURE"))
300
enable_fast_measure = PR_TRUE;
303
if (PR_GetEnv("MOZILLA_GFX_DISABLE_FAST_MEASURE"))
305
enable_fast_measure = PR_FALSE;
308
getenv_done = PR_TRUE;
311
if (enable_fast_measure) {
312
// We have GetTextDimensions()
313
result |= NS_RENDERING_HINT_FAST_MEASURE;
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
324
nsRenderingContextXlib::LockDrawingSurface(PRInt32 aX, PRInt32 aY,
325
PRUint32 aWidth, PRUint32 aHeight,
326
void **aBits, PRInt32 *aStride,
327
PRInt32 *aWidthBytes, PRUint32 aFlags)
329
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::LockDrawingSurface()\n"));
332
return mSurface->Lock(aX, aY, aWidth, aHeight,
333
aBits, aStride, aWidthBytes, aFlags);
337
nsRenderingContextXlib::UnlockDrawingSurface(void)
339
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::UnlockDrawingSurface()\n"));
349
nsRenderingContextXlib::SelectOffScreenDrawingSurface(nsDrawingSurface aSurface)
351
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SelectOffScreenDrawingSurface()\n"));
352
if (nsnull == aSurface)
353
mSurface = mOffscreenSurface;
355
mSurface = (nsIDrawingSurfaceXlib *)aSurface;
361
nsRenderingContextXlib::GetDrawingSurface(nsDrawingSurface *aSurface)
363
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetDrawingSurface()\n"));
364
*aSurface = mSurface;
369
nsRenderingContextXlib::Reset()
371
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Reset()\n"));
375
NS_IMETHODIMP nsRenderingContextXlib::GetDeviceContext(nsIDeviceContext *&aContext)
378
NS_IF_ADDREF(aContext);
383
nsRenderingContextXlib::PushState(void)
385
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::PushState()\n"));
386
GraphicsState *state = new GraphicsState();
389
return NS_ERROR_OUT_OF_MEMORY;
391
state->mMatrix = mTranMatrix;
393
mStateCache.AppendElement(state);
395
if (nsnull == mTranMatrix)
396
mTranMatrix = new nsTransform2D();
398
mTranMatrix = new nsTransform2D(mTranMatrix);
401
state->mClipRegion = mClipRegion;
402
mClipRegion = new nsRegionXlib();
404
return NS_ERROR_OUT_OF_MEMORY;
406
mClipRegion->SetTo(*state->mClipRegion);
409
state->mFontMetrics = mFontMetrics;
410
state->mColor = mCurrentColor;
411
state->mLineStyle = mCurrentLineStyle;
417
nsRenderingContextXlib::PopState(PRBool &aClipState)
419
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::PopState()\n"));
421
PRUint32 cnt = mStateCache.Count();
422
GraphicsState *state;
425
state = (GraphicsState *)mStateCache.ElementAt(cnt - 1);
426
mStateCache.RemoveElementAt(cnt - 1);
430
mTranMatrix = state->mMatrix;
432
mClipRegion = state->mClipRegion;
433
if (mFontMetrics != state->mFontMetrics)
434
SetFont(state->mFontMetrics);
436
if (state->mColor != mCurrentColor)
437
SetColor(state->mColor);
438
if (state->mLineStyle != mCurrentLineStyle)
439
SetLineStyle(state->mLineStyle);
445
aClipState = mClipRegion->IsEmpty();
447
aClipState = PR_TRUE;
453
#undef TRACE_SET_CLIP
456
#ifdef TRACE_SET_CLIP
458
nsClipCombine_to_string(nsClipCombine aCombine)
460
#ifdef TRACE_SET_CLIP
461
printf("nsRenderingContextXlib::SetClipRect(x=%d,y=%d,w=%d,h=%d,%s)\n",
466
nsClipCombine_to_string(aCombine));
467
#endif // TRACE_SET_CLIP
471
case nsClipCombine_kIntersect:
472
return "nsClipCombine_kIntersect";
475
case nsClipCombine_kUnion:
476
return "nsClipCombine_kUnion";
479
case nsClipCombine_kSubtract:
480
return "nsClipCombine_kSubtract";
483
case nsClipCombine_kReplace:
484
return "nsClipCombine_kReplace";
488
return "something got screwed";
490
#endif // TRACE_SET_CLIP
493
nsRenderingContextXlib::IsVisibleRect(const nsRect& aRect, PRBool &aVisible)
495
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::IsVisibleRect()\n"));
501
nsRenderingContextXlib::SetClipRect(const nsRect& aRect,
502
nsClipCombine aCombine,
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);
513
void nsRenderingContextXlib::SetClipRectInPixels(const nsRect& aRect,
514
nsClipCombine aCombine,
517
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetClipRectInPixels()\n"));
521
case nsClipCombine_kIntersect:
522
mClipRegion->Intersect(aRect.x,aRect.y,aRect.width,aRect.height);
524
case nsClipCombine_kUnion:
525
mClipRegion->Union(aRect.x,aRect.y,aRect.width,aRect.height);
527
case nsClipCombine_kSubtract:
528
mClipRegion->Subtract(aRect.x,aRect.y,aRect.width,aRect.height);
530
case nsClipCombine_kReplace:
531
mClipRegion->SetTo(aRect.x,aRect.y,aRect.width,aRect.height);
535
aClipEmpty = mClipRegion->IsEmpty();
539
nsRenderingContextXlib::GetClipRect(nsRect &aRect, PRBool &aClipState)
541
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetClipRext()\n"));
543
if (!mClipRegion->IsEmpty()) {
544
mClipRegion->GetBoundingBox(&x,&y,&w,&h);
545
aRect.SetRect(x,y,w,h);
546
aClipState = PR_TRUE;
548
aRect.SetRect(0,0,0,0);
549
aClipState = PR_FALSE;
555
nsRenderingContextXlib::SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine, PRBool &aClipState)
557
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetClipRegion()\n"));
560
case nsClipCombine_kIntersect:
561
mClipRegion->Intersect(aRegion);
563
case nsClipCombine_kUnion:
564
mClipRegion->Union(aRegion);
566
case nsClipCombine_kSubtract:
567
mClipRegion->Subtract(aRegion);
569
case nsClipCombine_kReplace:
570
mClipRegion->SetTo(aRegion);
574
aClipState = mClipRegion->IsEmpty();
580
nsRenderingContextXlib::CopyClipRegion(nsIRegion &aRegion)
582
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CopyClipRegion()\n"));
583
aRegion.SetTo(*mClipRegion);
588
nsRenderingContextXlib::GetClipRegion(nsIRegion **aRegion)
590
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetClipRegion()\n"));
593
NS_ASSERTION(!(nsnull == aRegion), "no region ptr");
596
(*aRegion)->SetTo(*mClipRegion);
601
void nsRenderingContextXlib::UpdateGC()
603
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::UpdateGC()\n"));
605
unsigned long valuesMask = 0;
607
Drawable drawable; mSurface->GetDrawable(drawable);
612
memset(&values, 0, sizeof(XGCValues));
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;
622
if (mCurrentFont && mCurrentFont->GetXFontStruct()) {
623
valuesMask |= GCFont;
624
values.font = mCurrentFont->GetXFontStruct()->fid;
627
values.line_style = mLineStyle;
628
valuesMask |= GCLineStyle;
630
values.function = mFunction;
631
valuesMask |= GCFunction;
635
mClipRegion->GetNativeRegion((void*&)rgn);
638
nsRenderingContextXlibContext *rcContext;
639
nsIDeviceContext *dc = mContext;
640
NS_STATIC_CAST(nsDeviceContextX *, dc)->GetRCContext(rcContext);
642
mGC = rcContext->mGcCache.GetGC(mDisplay, drawable,
643
valuesMask, &values, rgn);
647
nsRenderingContextXlib::SetColor(nscolor aColor)
649
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetColor(nscolor)\n"));
650
NS_ENSURE_TRUE(mContext != nsnull, NS_ERROR_FAILURE);
652
mCurrentColor = aColor;
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)));
659
nsRenderingContextXlib::GetColor(nscolor &aColor) const
661
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetColor()\n"));
663
aColor = mCurrentColor;
668
nsRenderingContextXlib::SetFont(const nsFont& aFont, nsIAtom* aLangGroup)
670
nsCOMPtr<nsIFontMetrics> newMetrics;
671
nsresult rv = mContext->GetMetricsFor( aFont, aLangGroup, *getter_AddRefs(newMetrics) );
673
if (NS_SUCCEEDED(rv)) {
674
rv = SetFont(newMetrics);
680
nsRenderingContextXlib::SetFont(nsIFontMetrics *aFontMetrics)
682
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetFont()\n"));
684
mFontMetrics = aFontMetrics;
688
nsFontHandle fontHandle;
689
mFontMetrics->GetFontHandle(fontHandle);
690
mCurrentFont = (nsFontXlib *)fontHandle;
697
nsRenderingContextXlib::SetLineStyle(nsLineStyle aLineStyle)
699
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::SetLineStyle()\n"));
701
if (aLineStyle != mCurrentLineStyle) {
702
/* XXX this isnt done in gtk, copy from there when ready
705
case nsLineStyle_kSolid:
706
mLineStyle = LineSolid;
709
case nsLineStyle_kDashed:
710
static char dashed[2] = {4,4};
714
case nsLineStyle_kDotted:
715
static char dotted[2] = {3,1};
724
mCurrentLineStyle = aLineStyle ;
730
nsRenderingContextXlib::GetLineStyle(nsLineStyle &aLineStyle)
732
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetLineStyle()\n"));
733
aLineStyle = mCurrentLineStyle;
738
nsRenderingContextXlib::GetFontMetrics(nsIFontMetrics *&aFontMetrics)
740
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetFontMetrics()\n"));
742
aFontMetrics = mFontMetrics;
743
NS_IF_ADDREF(aFontMetrics);
747
// add the passed in translation to the current translation
749
nsRenderingContextXlib::Translate(nscoord aX, nscoord aY)
751
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Translate()\n"));
752
mTranMatrix->AddTranslation((float)aX,(float)aY);
756
// add the passed in scale to the current scale
758
nsRenderingContextXlib::Scale(float aSx, float aSy)
760
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::Scale()\n"));
761
mTranMatrix->AddScale(aSx, aSy);
766
nsRenderingContextXlib::GetCurrentTransform(nsTransform2D *&aTransform)
768
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::GetCurrentTransform()\n"));
769
aTransform = mTranMatrix;
774
nsRenderingContextXlib::CreateDrawingSurface(const nsRect& aBounds,
776
nsDrawingSurface &aSurface)
778
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CreateDrawingSurface()\n"));
780
if (nsnull == mSurface) {
782
return NS_ERROR_FAILURE;
785
NS_ENSURE_TRUE((aBounds.width > 0) && (aBounds.height > 0), NS_ERROR_FAILURE);
787
nsresult rv = NS_ERROR_FAILURE;
788
nsDrawingSurfaceXlibImpl *surf = new nsDrawingSurfaceXlibImpl();
794
rv = surf->Init(mXlibRgbHandle, mGC, aBounds.width, aBounds.height, aSurfFlags);
797
aSurface = (nsDrawingSurface)surf;
803
nsRenderingContextXlib::DestroyDrawingSurface(nsDrawingSurface aDS)
805
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DestroyDrawingSurface()\n"));
806
nsIDrawingSurfaceXlib *surf = NS_STATIC_CAST(nsIDrawingSurfaceXlib *, aDS);;
808
NS_ENSURE_TRUE(surf != nsnull, NS_ERROR_FAILURE);
816
nsRenderingContextXlib::DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
818
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawLine()\n"));
820
nscoord diffX, diffY;
822
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
823
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
825
mTranMatrix->TransformCoord(&aX0,&aY0);
826
mTranMatrix->TransformCoord(&aX1,&aY1);
832
diffX = (diffX>0?1:-1);
835
diffY = (diffY>0?1:-1);
839
Drawable drawable; mSurface->GetDrawable(drawable);
840
::XDrawLine(mDisplay, drawable,
841
*mGC, aX0, aY0, aX1 - diffX, aY1 - diffY);
847
nsRenderingContextXlib::DrawStdLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
849
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawStdLine()\n"));
851
nscoord diffX, diffY;
853
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
854
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
856
mTranMatrix->TransformCoord(&aX0,&aY0);
857
mTranMatrix->TransformCoord(&aX1,&aY1);
863
diffX = (diffX>0?1:-1);
866
diffY = (diffY>0?1:-1);
870
Drawable drawable; mSurface->GetDrawable(drawable);
871
::XDrawLine(mDisplay, drawable,
872
*mGC, aX0, aY0, aX1 - diffX, aY1 - diffY);
878
nsRenderingContextXlib::DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints)
880
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawPolyLine()\n"));
882
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
883
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
889
xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
890
NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
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);
900
Drawable drawable; mSurface->GetDrawable(drawable);
901
::XDrawLines(mDisplay,
904
xpoints, aNumPoints, CoordModeOrigin);
906
free((void *)xpoints);
912
nsRenderingContextXlib::DrawRect(const nsRect& aRect)
914
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawRext(const nsRect& aRect)\n"));
915
return DrawRect(aRect.x, aRect.y, aRect.width, aRect.height);
919
nsRenderingContextXlib::DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
921
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawRect(aX, aY, aWidth, aHeight)\n"));
923
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
924
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
933
mTranMatrix->TransformCoord(&x,&y,&w,&h);
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);
940
// Don't draw empty rectangles; also, w/h are adjusted down by one
941
// so that the right number of pixels are drawn.
945
Drawable drawable; mSurface->GetDrawable(drawable);
946
::XDrawRectangle(mDisplay,
960
nsRenderingContextXlib::FillRect(const nsRect& aRect)
962
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillRect()\n"));
963
return FillRect(aRect.x, aRect.y, aRect.width, aRect.height);
967
nsRenderingContextXlib::FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
969
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillRect()\n"));
971
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
972
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
980
mTranMatrix->TransformCoord(&x,&y,&w,&h);
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);
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));
991
::XFillRectangle(mDisplay,
1000
nsRenderingContextXlib::InvertRect(const nsRect& aRect)
1002
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::InvertRect()\n"));
1003
return InvertRect(aRect.x, aRect.y, aRect.width, aRect.height);
1007
nsRenderingContextXlib::InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
1009
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::InvertRect()\n"));
1011
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1012
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1021
mTranMatrix->TransformCoord(&x,&y,&w,&h);
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);
1031
Drawable drawable; mSurface->GetDrawable(drawable);
1032
::XFillRectangle(mDisplay,
1046
nsRenderingContextXlib::DrawPolygon(const nsPoint aPoints[], PRInt32 aNumPoints)
1048
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawPolygon()\n"));
1050
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1051
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1057
xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
1058
NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
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);
1068
Drawable drawable; mSurface->GetDrawable(drawable);
1069
::XDrawLines(mDisplay,
1072
xpoints, aNumPoints, CoordModeOrigin);
1074
free((void *)xpoints);
1080
nsRenderingContextXlib::FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints)
1082
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillPolygon()\n"));
1084
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1085
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1090
xpoints = (XPoint *) malloc(sizeof(XPoint) * aNumPoints);
1091
NS_ENSURE_TRUE(xpoints != nsnull, NS_ERROR_OUT_OF_MEMORY);
1093
for (i = 0; i < aNumPoints; ++i) {
1094
nsPoint p = aPoints[i];
1095
mTranMatrix->TransformCoord(&p.x, &p.y);
1101
Drawable drawable; mSurface->GetDrawable(drawable);
1102
::XFillPolygon(mDisplay,
1105
xpoints, aNumPoints, Complex, CoordModeOrigin);
1107
free((void *)xpoints);
1113
nsRenderingContextXlib::DrawEllipse(const nsRect& aRect)
1115
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawEllipse(const nsRect& aRect)\n"));
1116
return DrawEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
1120
nsRenderingContextXlib::DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
1122
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawEllipse(aX, aY, aWidth, aHeight)\n"));
1124
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1125
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1134
mTranMatrix->TransformCoord(&x,&y,&w,&h);
1137
Drawable drawable; mSurface->GetDrawable(drawable);
1138
::XDrawArc(mDisplay,
1141
x, y, w, h, 0, 360*64);
1147
nsRenderingContextXlib::FillEllipse(const nsRect& aRect)
1149
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillEllipse()\n"));
1150
return FillEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
1154
nsRenderingContextXlib::FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
1156
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillEllipse()\n"));
1158
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1159
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1168
mTranMatrix->TransformCoord(&x,&y,&w,&h);
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:
1176
::XDrawArc(mDisplay,
1179
x, y, w, h, 0, 360*64);
1182
::XFillArc(mDisplay,
1185
x, y, w, h, 0, 360*64);
1191
nsRenderingContextXlib::DrawArc(const nsRect& aRect,
1192
float aStartAngle, float aEndAngle)
1194
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawArc()\n"));
1195
return DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle);
1199
nsRenderingContextXlib::DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
1200
float aStartAngle, float aEndAngle)
1202
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawArc()\n"));
1204
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1205
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1214
mTranMatrix->TransformCoord(&x,&y,&w,&h);
1217
Drawable drawable; mSurface->GetDrawable(drawable);
1218
::XDrawArc(mDisplay,
1221
x,y,w,h, NSToIntRound(aStartAngle * 64.0f),
1222
NSToIntRound(aEndAngle * 64.0f));
1228
nsRenderingContextXlib::FillArc(const nsRect& aRect,
1229
float aStartAngle, float aEndAngle)
1231
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillArc()\n"));
1232
return FillArc(aRect.x, aRect.y, aRect.width, aRect.height, aStartAngle, aEndAngle);
1236
nsRenderingContextXlib::FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
1237
float aStartAngle, float aEndAngle)
1239
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::FillArc()\n"));
1241
NS_ENSURE_TRUE(mTranMatrix != nsnull, NS_ERROR_FAILURE);
1242
NS_ENSURE_TRUE(mSurface != nsnull, NS_ERROR_FAILURE);
1251
mTranMatrix->TransformCoord(&x,&y,&w,&h);
1254
Drawable drawable; mSurface->GetDrawable(drawable);
1255
::XFillArc(mDisplay,
1258
x,y,w,h, NSToIntRound(aStartAngle * 64.0f),
1259
NSToIntRound(aEndAngle * 64.0f));
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)
1268
// handle 8 bit data with a 16 bit font
1270
int Widen8To16AndMove(const char *char_p,
1275
for (i=0; i<char_len; i++) {
1276
(xchar2b_p)->byte1 = 0;
1277
(xchar2b_p++)->byte2 = *char_p++;
1282
// handle 8 bit data with a 16 bit font
1284
int Widen8To16AndGetWidth(nsXFont *xFont,
1288
NS_ASSERTION(!xFont->IsSingleByte(), "Widen8To16AndGetWidth: wrong string/font size");
1289
XChar2b buf[WIDEN_8_TO_16_BUF_SIZE];
1294
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
1295
p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
1297
return(0); // handle malloc failure
1300
uchar_size = Widen8To16AndMove(text, text_length, p);
1301
rawWidth = xFont->TextWidth16(p, uchar_size/2);
1303
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
1310
void Widen8To16AndDraw(Drawable drawable,
1318
NS_ASSERTION(!xFont->IsSingleByte(), "Widen8To16AndDraw: wrong string/font size");
1319
XChar2b buf[WIDEN_8_TO_16_BUF_SIZE];
1323
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
1324
p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
1326
return; // handle malloc failure
1329
uchar_size = Widen8To16AndMove(text, text_length, p);
1330
xFont->DrawText16(drawable, gc, x, y, p, uchar_size/2);
1332
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
1338
nsRenderingContextXlib::GetWidth(char aC, nscoord &aWidth)
1340
// Check for the very common case of trying to get the width of a single
1342
if ((aC == ' ') && (nsnull != mFontMetrics)) {
1343
return mFontMetrics->GetSpaceWidth(aWidth);
1345
return GetWidth(&aC, 1, aWidth);
1349
nsRenderingContextXlib::GetWidth(PRUnichar aC, nscoord& aWidth,
1352
return GetWidth(&aC, 1, aWidth, aFontID);
1356
nsRenderingContextXlib::GetWidth(const nsString& aString,
1357
nscoord& aWidth, PRInt32* aFontID)
1359
return GetWidth(aString.get(), aString.Length(), aWidth, aFontID);
1363
nsRenderingContextXlib::GetWidth(const char* aString, nscoord& aWidth)
1365
return GetWidth(aString, strlen(aString), aWidth);
1369
nsRenderingContextXlib::GetWidth(const char* aString, PRUint32 aLength,
1376
NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
1377
NS_ENSURE_TRUE(mCurrentFont != nsnull, NS_ERROR_FAILURE);
1379
nsXFont *xFont = mCurrentFont->GetXFont();
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]);
1390
rawWidth = mCurrentFont->GetWidth(unichars, len);
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);
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);
1404
aWidth = NSToCoordRound(rawWidth * mP2T);
1410
nsRenderingContextXlib::GetWidth(const PRUnichar* aString, PRUint32 aLength,
1411
nscoord& aWidth, PRInt32* aFontID)
1417
NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
1419
nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
1421
NS_ENSURE_TRUE(metrics != nsnull, NS_ERROR_FAILURE);
1423
nsFontXlib *prevFont = nsnull;
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)) {
1435
goto FoundFont; // for speed -- avoid "if" statement
1439
currFont = metrics->FindFont(c);
1441
// XXX avoid this test by duplicating code -- erik
1443
if (currFont != prevFont) {
1444
rawWidth += prevFont->GetWidth(&aString[start], i - start);
1445
prevFont = currFont;
1450
prevFont = currFont;
1456
rawWidth += prevFont->GetWidth(&aString[start], i - start);
1459
aWidth = NSToCoordRound(rawWidth * mP2T);
1461
if (nsnull != aFontID)
1468
nsRenderingContextXlib::GetTextDimensions(const char* aString,
1470
PRInt32 aAvailWidth,
1473
nsTextDimensions& aDimensions,
1474
PRInt32& aNumCharsFit,
1475
nsTextDimensions& aLastWordDimensions,
1478
NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
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
1486
// Initialize OUT parameters
1487
mFontMetrics->GetMaxAscent(aLastWordDimensions.ascent);
1488
mFontMetrics->GetMaxDescent(aLastWordDimensions.descent);
1489
aLastWordDimensions.width = -1;
1492
// Iterate each character in the string and determine which font to use
1495
nscoord aveCharWidth;
1496
mFontMetrics->GetAveCharWidth(aveCharWidth);
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;
1506
if (estimatedNumChars < 1) {
1507
estimatedNumChars = 1;
1510
// Find the nearest break offset
1511
PRInt32 estimatedBreakOffset = start + estimatedNumChars;
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;
1523
breakIndex = prevBreakState_BreakIndex;
1524
while (((breakIndex + 1) < aNumBreaks) &&
1525
(aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
1528
if (breakIndex == prevBreakState_BreakIndex) {
1529
++breakIndex; // make sure we advanced past the previous break index
1531
numChars = aBreaks[breakIndex] - start;
1535
nscoord twWidth = 0;
1536
if ((1 == numChars) && (aString[start] == ' ')) {
1537
mFontMetrics->GetSpaceWidth(twWidth);
1539
else if (numChars > 0)
1540
GetWidth( &aString[start], numChars, twWidth);
1542
// See if the text fits
1543
PRBool textFits = (twWidth + width) <= aAvailWidth;
1545
// If the text fits then update the width and the number of
1546
// characters that fit
1548
aNumCharsFit += numChars;
1552
// This is a good spot to back up to if we need to so remember
1554
prevBreakState_BreakIndex = breakIndex;
1555
prevBreakState_Width = width;
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;
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
1574
aNumCharsFit += numChars;
1579
// Repeatedly back up until we get to where the text fits or we're all
1580
// the way back to the first word
1582
while ((breakIndex >= 1) && (width > aAvailWidth)) {
1584
start = aBreaks[breakIndex - 1];
1585
numChars = aBreaks[breakIndex] - start;
1587
if ((1 == numChars) && (aString[start] == ' ')) {
1588
mFontMetrics->GetSpaceWidth(twWidth);
1590
else if (numChars > 0)
1591
GetWidth( &aString[start], numChars, twWidth);
1594
aNumCharsFit = start;
1601
aDimensions.width = width;
1602
mFontMetrics->GetMaxAscent(aDimensions.ascent);
1603
mFontMetrics->GetMaxDescent(aDimensions.descent);
1608
return NS_ERROR_FAILURE;
1611
struct BreakGetTextDimensionsData {
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)
1620
PRInt32 mNumCharsFit; // IN/OUT -- accumulated number of chars that fit so far
1621
nscoord mWidth; // IN/OUT -- accumulated width so far
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
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
1635
static PRBool PR_CALLBACK
1636
do_BreakGetTextDimensions(const nsFontSwitchXlib *aFontSwitch,
1637
const PRUnichar* aSubstring,
1638
PRUint32 aSubstringLength,
1641
nsFontXlib *fontXlib = aFontSwitch->mFontXlib;
1643
// Make sure the font is selected
1644
BreakGetTextDimensionsData* data = (BreakGetTextDimensionsData*)aData;
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;
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;
1662
// Make sure the estimated number of characters is at least 1
1663
if (estimatedNumChars < 1) {
1664
estimatedNumChars = 1;
1667
// Find the nearest break offset
1668
PRInt32 estimatedBreakOffset = start + estimatedNumChars;
1669
PRInt32 breakIndex = -1; // not yet computed
1670
PRBool inMiddleOfSegment = PR_FALSE;
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;
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) {
1688
if (breakIndex == -1)
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
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);
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)) {
1704
numChars = PR_MIN(data->mBreaks[breakIndex] - start, (PRInt32)aSubstringLength);
1707
NS_ASSERTION(i != data->mBreaks[breakIndex], "don't expect to be at segment boundary");
1709
// The text is all within the same segment
1710
numChars = i - start;
1712
// Remember we're in the middle of a segment and not between
1714
inMiddleOfSegment = PR_TRUE;
1720
nscoord twWidth, pxWidth;
1721
if ((1 == numChars) && (pstr[start] == ' ')) {
1722
twWidth = data->mSpaceWidth;
1725
pxWidth = fontXlib->GetWidth(&pstr[start], numChars);
1726
twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);
1729
// See if the text fits
1730
PRBool textFits = (twWidth + width) <= data->mAvailWidth;
1732
// If the text fits then update the width and the number of
1733
// characters that fit
1735
numCharsFit += numChars;
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;
1747
// The text didn't fit. If we're out of room then we're all done
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) {
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;
1762
canBackup = data->mPrevBreakState_BreakIndex == (breakIndex - 1);
1766
numCharsFit = data->mBreaks[data->mPrevBreakState_BreakIndex];
1767
width = data->mPrevBreakState_Width;
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) {
1777
if (data->mBreaks[breakIndex] < i) {
1778
while ((breakIndex + 1 < data->mNumBreaks) && (data->mBreaks[breakIndex + 1] < i)) {
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
1787
numCharsFit += numChars;
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]) {
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;
1809
// Repeatedly back up until we get to where the text fits or we're
1810
// all the way back to the first word
1812
while ((breakIndex >= 0) && (width > data->mAvailWidth)) {
1814
start = data->mBreaks[breakIndex];
1815
numChars = i - start;
1816
if ((1 == numChars) && (pstr[start] == ' ')) {
1817
twWidth = data->mSpaceWidth;
1819
else if (numChars > 0) {
1820
pxWidth = fontXlib->GetWidth(&pstr[start], numChars);
1821
twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);
1825
numCharsFit = start;
1835
NS_ASSERTION(allDone || start == i, "internal error");
1836
NS_ASSERTION(allDone || data->mNumCharsFit != numCharsFit, "internal error");
1837
#endif /* DEBUG_rbs */
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]);
1852
return PR_TRUE; // don't stop if we still need to measure more characters
1856
nsRenderingContextXlib::GetTextDimensions(const PRUnichar* aString,
1858
PRInt32 aAvailWidth,
1861
nsTextDimensions& aDimensions,
1862
PRInt32& aNumCharsFit,
1863
nsTextDimensions& aLastWordDimensions,
1867
return NS_ERROR_FAILURE;
1869
nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
1871
nscoord spaceWidth, aveCharWidth;
1872
metrics->GetSpaceWidth(spaceWidth);
1873
metrics->GetAveCharWidth(aveCharWidth);
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.
1880
// Upon completion of glyph resolution, characters that can be
1881
// represented with fonts[i] are at offsets[i] .. offsets[i+1]-1
1883
nsAutoVoidArray fonts, offsets;
1884
offsets.AppendElement((void*)aString);
1886
BreakGetTextDimensionsData data = { mP2T, aAvailWidth, aBreaks, aNumBreaks,
1887
spaceWidth, aveCharWidth, 0, 0, 0, -1, 0, &fonts, &offsets
1890
metrics->ResolveForwards(aString, aLength, do_BreakGetTextDimensions, &data);
1892
if (aFontID) *aFontID = 0;
1894
aNumCharsFit = data.mNumCharsFit;
1895
aDimensions.width = data.mWidth;
1898
// Post-processing for the ascent and descent:
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.
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).
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;
1921
PRInt32 count = fonts.Count();
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;
1929
// fast path - normal case, quick return if there is only one font
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)
1942
const PRUnichar* lastWord = (lastBreakIndex > 0)
1943
? aString + aBreaks[lastBreakIndex-1]
1944
: aString + aNumCharsFit; // let it point outside to play nice with the loop
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
1949
PRInt32 currFont = 0;
1950
const PRUnichar* pstr = aString;
1951
const PRUnichar* last = aString + aNumCharsFit;
1953
while (pstr < last) {
1954
fontXlib = (nsFontXlib*)fonts[currFont];
1955
PRUnichar* nextOffset = (PRUnichar*)offsets[++currFont];
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.
1968
// skip pass the whitespace to ignore the height that it may contribute
1970
// get out if we reached the end
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];
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;
1988
if (aLastWordDimensions.descent < fontXlib->mMaxDescent) {
1989
aLastWordDimensions.descent = fontXlib->mMaxDescent;
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;
1998
if (aDimensions.descent < fontXlib->mMaxDescent) {
1999
aDimensions.descent = fontXlib->mMaxDescent;
2003
// advance to where the next font starts
2011
nsRenderingContextXlib::GetTextDimensions(const char* aString, PRUint32 aLength,
2012
nsTextDimensions& aDimensions)
2014
mFontMetrics->GetMaxAscent(aDimensions.ascent);
2015
mFontMetrics->GetMaxDescent(aDimensions.descent);
2016
return GetWidth(aString, aLength, aDimensions.width);
2020
nsRenderingContextXlib::GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
2021
nsTextDimensions& aDimensions, PRInt32* aFontID)
2023
aDimensions.Clear();
2025
NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
2027
nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
2029
NS_ENSURE_TRUE(metrics != nsnull, NS_ERROR_FAILURE);
2031
nsFontXlib* prevFont = nsnull;
2032
int rawWidth = 0, rawAscent = 0, rawDescent = 0;
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)) {
2043
goto FoundFont; // for speed -- avoid "if" statement
2047
currFont = metrics->FindFont(c);
2049
// XXX avoid this test by duplicating code -- erik
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;
2062
prevFont = currFont;
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;
2075
aDimensions.width = NSToCoordRound(rawWidth * mP2T);
2076
aDimensions.ascent = NSToCoordRound(rawAscent * mP2T);
2077
aDimensions.descent = NSToCoordRound(rawDescent * mP2T);
2079
if (nsnull != aFontID)
2086
nsRenderingContextXlib::DrawString(const char *aString, PRUint32 aLength,
2087
nscoord aX, nscoord aY,
2088
const nscoord* aSpacing)
2090
nsresult res = NS_OK;
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);
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++;
2111
mTranMatrix->TransformCoord(&xx, &yy);
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]);
2122
res = mCurrentFont->DrawString(this, mSurface, xx, yy,
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);
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,
2142
mTranMatrix->TransformCoord(&x, &y);
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]);
2153
res = mCurrentFont->DrawString(this, mSurface, x, y,
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);
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);
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
2178
mFontMetrics->GetFont(font);
2179
PRUint8 deco = font->decorations;
2181
if (deco & NS_FONT_DECORATION_OVERLINE)
2182
DrawLine(aX, aY, aX + aWidth, aY);
2184
if (deco & NS_FONT_DECORATION_UNDERLINE)
2186
nscoord ascent,descent;
2188
mFontMetrics->GetMaxAscent(ascent);
2189
mFontMetrics->GetMaxDescent(descent);
2191
DrawLine(aX, aY + ascent + (descent >> 1),
2192
aX + aWidth, aY + ascent + (descent >> 1));
2195
if (deco & NS_FONT_DECORATION_LINE_THROUGH)
2199
mFontMetrics->GetHeight(height);
2201
DrawLine(aX, aY + (height >> 1), aX + aWidth, aY + (height >> 1));
2204
#endif /* DISABLED_FOR_NOW */
2210
nsRenderingContextXlib::DrawString(const PRUnichar* aString, PRUint32 aLength,
2211
nscoord aX, nscoord aY,
2213
const nscoord* aSpacing)
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);
2223
mTranMatrix->TransformCoord(&x, &y);
2225
nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
2226
nsFontXlib *prevFont = nsnull;
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)) {
2237
goto FoundFont; // for speed -- avoid "if" statement
2241
currFont = metrics->FindFont(c);
2243
// XXX avoid this test by duplicating code -- erik
2245
if (currFont != prevFont) {
2247
const PRUnichar* str = &aString[start];
2248
const PRUnichar* end = &aString[i];
2250
// save off mCurrentFont and set it so that we cache the GC's font correctly
2251
nsFontXlib *oldFont = mCurrentFont;
2252
mCurrentFont = prevFont;
2258
mTranMatrix->TransformCoord(&x, &y);
2259
prevFont->DrawString(this, mSurface, x, y, str, 1);
2263
mCurrentFont = oldFont;
2266
nsFontXlib *oldFont = mCurrentFont;
2267
mCurrentFont = prevFont;
2269
x += prevFont->DrawString(this, mSurface, x, y, &aString[start],
2271
mCurrentFont = oldFont;
2273
prevFont = currFont;
2278
prevFont = currFont;
2284
nsFontXlib *oldFont = mCurrentFont;
2285
mCurrentFont = prevFont;
2289
const PRUnichar* str = &aString[start];
2290
const PRUnichar* end = &aString[i];
2294
mTranMatrix->TransformCoord(&x, &y);
2295
prevFont->DrawString(this, mSurface, x, y, str, 1);
2301
prevFont->DrawString(this, mSurface, x, y, &aString[start], i - start);
2304
mCurrentFont = oldFont;
2312
nsRenderingContextXlib::DrawString(const nsString& aString,
2313
nscoord aX, nscoord aY,
2315
const nscoord* aSpacing)
2317
return DrawString(aString.get(), aString.Length(),
2318
aX, aY, aFontID, aSpacing);
2322
nsRenderingContextXlib::CopyOffScreenBits(nsDrawingSurface aSrcSurf, PRInt32 aSrcX, PRInt32 aSrcY,
2323
const nsRect &aDestBounds, PRUint32 aCopyFlags)
2325
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::CopyOffScreenBits()\n"));
2327
PRInt32 srcX = aSrcX;
2328
PRInt32 srcY = aSrcY;
2329
nsRect drect = aDestBounds;
2330
nsIDrawingSurfaceXlib *destsurf;
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);
2336
if (aCopyFlags & NS_COPYBITS_TO_BACK_BUFFER) {
2337
destsurf = mSurface;
2341
NS_ENSURE_TRUE(mOffscreenSurface != nsnull, NS_ERROR_FAILURE);
2342
destsurf = mOffscreenSurface;
2345
if (aCopyFlags & NS_COPYBITS_XFORM_SOURCE_VALUES)
2346
mTranMatrix->TransformCoord(&srcX, &srcY);
2348
if (aCopyFlags & NS_COPYBITS_XFORM_DEST_VALUES)
2349
mTranMatrix->TransformCoord(&drect.x, &drect.y, &drect.width, &drect.height);
2351
//XXX flags are unused. that would seem to mean that there is
2352
//inefficiency somewhere... MMP
2355
Drawable destdrawable; destsurf->GetDrawable(destdrawable);
2356
Drawable srcdrawable; ((nsIDrawingSurfaceXlib *)aSrcSurf)->GetDrawable(srcdrawable);
2358
::XCopyArea(mDisplay,
2363
drect.width, drect.height,
2370
nsRenderingContextXlib::RetrieveCurrentNativeGraphicData(PRUint32 * ngd)
2372
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::RetrieveCurrentNativeGraphicData()\n"));
2378
void Widen8To16AndGetTextExtents(nsXFont *xFont,
2387
NS_ASSERTION(!xFont->IsSingleByte(),"wrong string/font size");
2388
XChar2b buf[WIDEN_8_TO_16_BUF_SIZE];
2392
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
2393
p = (XChar2b*)malloc(text_length*sizeof(XChar2b));
2394
if (!p) { // handle malloc failure
2404
uchar_size = Widen8To16AndMove(text, text_length, p);
2405
xFont->TextExtents16(p, uchar_size/2,
2412
if (text_length > WIDEN_8_TO_16_BUF_SIZE) {
2418
nsRenderingContextXlib::GetBoundingMetrics(const char* aString,
2420
nsBoundingMetrics& aBoundingMetrics)
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();
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]);
2437
res = mCurrentFont->GetBoundingMetrics(unichars, len,
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);
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);
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);
2474
nsRenderingContextXlib::GetBoundingMetrics(const PRUnichar* aString,
2476
nsBoundingMetrics& aBoundingMetrics,
2479
aBoundingMetrics.Clear();
2481
NS_ENSURE_TRUE(aString != nsnull, NS_ERROR_FAILURE);
2483
nsFontMetricsXlib *metrics = NS_REINTERPRET_CAST(nsFontMetricsXlib *, mFontMetrics.get());
2484
nsFontXlib *prevFont = nsnull;
2486
nsBoundingMetrics rawbm;
2487
PRBool firstTime = PR_TRUE;
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)) {
2498
goto FoundFont; // for speed -- avoid "if" statement
2502
currFont = metrics->FindFont(c);
2504
// XXX avoid this test by duplicating code -- erik
2506
if (currFont != prevFont) {
2507
prevFont->GetBoundingMetrics((const PRUnichar*) &aString[start],
2510
firstTime = PR_FALSE;
2511
aBoundingMetrics = rawbm;
2514
aBoundingMetrics += rawbm;
2516
prevFont = currFont;
2521
prevFont = currFont;
2527
prevFont->GetBoundingMetrics((const PRUnichar*) &aString[start],
2530
aBoundingMetrics = rawbm;
2533
aBoundingMetrics += rawbm;
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);
2543
if (nsnull != aFontID)
2548
#endif /* MOZ_MATHML */
2551
nsRenderingContextXlib::DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint)
2553
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawImage()\n"));
2555
return nsRenderingContextImpl::DrawImage(aImage, aSrcRect, aDestPoint);
2559
nsRenderingContextXlib::DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect)
2561
PR_LOG(RenderingContextXlibLM, PR_LOG_DEBUG, ("nsRenderingContextXlib::DrawScaledImage()\n"));
2563
return nsRenderingContextImpl::DrawScaledImage(aImage, aSrcRect, aDestRect);
2567
nsRenderingContextXlib::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsDrawingSurface &aBackbuffer)
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);
2576
nsRenderingContextXlib::ReleaseBackbuffer(void)
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();