Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  nodelist  faq  login

Almost nothing in Perl serves a single purpose. -- Larry Wall in <199712040054.QAA13811@wall.org>


programming / comp.lang.smalltalk.dolphin / Re: Implementing Graphics::MeasureCharacterRanges

SubjectAuthor
* Implementing Graphics::MeasureCharacterRangesJoe Betz
`* Re: Implementing Graphics::MeasureCharacterRangesJoe Betz
 `* Re: Implementing Graphics::MeasureCharacterRangesJoe Betz
  `- Re: Implementing Graphics::MeasureCharacterRangesJoe Betz

1
Subject: Implementing Graphics::MeasureCharacterRanges
From: Joe Betz
Newsgroups: comp.lang.smalltalk.dolphin
Date: Mon, 23 May 2022 04:18 UTC
X-Received: by 2002:a37:e205:0:b0:6a3:39d1:6292 with SMTP id g5-20020a37e205000000b006a339d16292mr10544246qki.525.1653279498786;
Sun, 22 May 2022 21:18:18 -0700 (PDT)
X-Received: by 2002:aca:abc1:0:b0:32b:21d5:f21a with SMTP id
u184-20020acaabc1000000b0032b21d5f21amr2735210oie.298.1653279498512; Sun, 22
May 2022 21:18:18 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.smalltalk.dolphin
Date: Sun, 22 May 2022 21:18:18 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=2001:861:51c3:bae0:8842:ea09:98ad:5b74;
posting-account=P1X3VgoAAADgSty0b3mKYJl_KPjmW842
NNTP-Posting-Host: 2001:861:51c3:bae0:8842:ea09:98ad:5b74
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <f5bc8ce7-6195-4d56-97fe-40b7acbd8e20n@googlegroups.com>
Subject: Implementing Graphics::MeasureCharacterRanges
From: joebet...@gmail.com (Joe Betz)
Injection-Date: Mon, 23 May 2022 04:18:18 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 2731
View all headers
I'm trying to use the GDI+ method Graphics::MeasureCharacterRanges but am getting errors from Windows that are no help in debugging the problem.

I think my issue is with the last argument to the method, which according to https://docs.microsoft.com/en-us/windows/win32/api/gdiplusgraphics/nf-gdiplusgraphics-graphics-measurecharacterranges needs to be a "pointer to an array of Region objects".

What does that mean in Dolphin?

A few possibilities I've tried, plus the errors returned:
- an ExternalHandle -> "Invalid access to memory location"
- array of ExternalHandle objects -> "Invalid access to memory location"
- array of GdiplusRegion objects -> "Cannot coerce an Array to lpvoid"

I also tried creating a subclass of ExternalStructure called GpRegion, but that didn't seem correct since Region it isn't a nice simple C struct but rather a full blown C++ monstrosity. Or whatever it is they call classes.





GdiplusGraphics>>measureCharacterRanges: aString font: aFont layoutRect: aRectangle format: aStringFormat
| text regionCount regions status |
text := aString asUtf16String.
regionCount := aStringFormat getMeasurableCharacterRangeCount value.
regions := (1 to: regionCount) collect: [ :index | GdiplusRegion new ].
(status := GdiplusLibrary default
gdipMeasureCharacterRanges: self asParameter
str: text
length: text size
font: aFont asParameter
layoutRect: (RECTF fromRectangle: aRectangle)
stringFormat: aStringFormat asParameter
regionCount: regionCount
regions: regions asParameter) == Ok
ifFalse: [GdiplusError signal: 'GdipMeasureCharacterRanges failed' with: status].
^regions


Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: Joe Betz
Newsgroups: comp.lang.smalltalk.dolphin
Date: Mon, 23 May 2022 05:06 UTC
References: 1
X-Received: by 2002:a05:6214:27ed:b0:462:1ee4:f029 with SMTP id jt13-20020a05621427ed00b004621ee4f029mr7318001qvb.47.1653282393066;
Sun, 22 May 2022 22:06:33 -0700 (PDT)
X-Received: by 2002:aca:7c1:0:b0:324:fe9a:9856 with SMTP id
184-20020aca07c1000000b00324fe9a9856mr10290424oih.293.1653282392824; Sun, 22
May 2022 22:06:32 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.smalltalk.dolphin
Date: Sun, 22 May 2022 22:06:32 -0700 (PDT)
In-Reply-To: <f5bc8ce7-6195-4d56-97fe-40b7acbd8e20n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2001:861:51c3:bae0:8842:ea09:98ad:5b74;
posting-account=P1X3VgoAAADgSty0b3mKYJl_KPjmW842
NNTP-Posting-Host: 2001:861:51c3:bae0:8842:ea09:98ad:5b74
References: <f5bc8ce7-6195-4d56-97fe-40b7acbd8e20n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <175b8d86-2354-4eb8-98bd-4131b482585bn@googlegroups.com>
Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: joebet...@gmail.com (Joe Betz)
Injection-Date: Mon, 23 May 2022 05:06:33 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1606
View all headers
Additionally,
- a HandlerArray of ExternalHandle objects (`HandleArray withAll: ((1 to: regionCount) collect: [:i | GdiplusRegion new asParameter])`) -> "Invalid parameter"
- a PointerArray of GdiplusRegion objects  (`PointerArray withAll: ((1 to: regionCount) collect: [:i | GdiplusRegion new])`) -> "Object busy"

Both of these seem more promising than my previous attempts, but still don't work.


Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: Joe Betz
Newsgroups: comp.lang.smalltalk.dolphin
Date: Mon, 23 May 2022 17:18 UTC
References: 1 2
X-Received: by 2002:ad4:5bc1:0:b0:42c:3700:a6df with SMTP id t1-20020ad45bc1000000b0042c3700a6dfmr17914466qvt.94.1653326297512;
Mon, 23 May 2022 10:18:17 -0700 (PDT)
X-Received: by 2002:a05:6808:1206:b0:2d7:65a8:65e with SMTP id
a6-20020a056808120600b002d765a8065emr21994oil.107.1653326297145; Mon, 23 May
2022 10:18:17 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.smalltalk.dolphin
Date: Mon, 23 May 2022 10:18:16 -0700 (PDT)
In-Reply-To: <175b8d86-2354-4eb8-98bd-4131b482585bn@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2001:861:51c3:bae0:8842:ea09:98ad:5b74;
posting-account=P1X3VgoAAADgSty0b3mKYJl_KPjmW842
NNTP-Posting-Host: 2001:861:51c3:bae0:8842:ea09:98ad:5b74
References: <f5bc8ce7-6195-4d56-97fe-40b7acbd8e20n@googlegroups.com> <175b8d86-2354-4eb8-98bd-4131b482585bn@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <5cc2afa1-0afa-4b07-8eae-4ab12d328aacn@googlegroups.com>
Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: joebet...@gmail.com (Joe Betz)
Injection-Date: Mon, 23 May 2022 17:18:17 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 2267
View all headers
Okay, some progress after a full night's sleep.

I found one off-by-one error in a separate method, then after fixing that, HandleArray seems to be working correctly if used like so:

        regionCount := aStringFormat getMeasurableCharacterRangeCount value.
        regions := (1 to: regionCount) collect:  [ :i | GdiplusRegion fromRectangle: aRectangle ].
        regionHandles := HandleArray withAll: (regions collect: [:each| each asParameter])

Now the problem is with the regions being returned. The first one seems to be correct, but the rest all have negative extents.

E.g. for the string 'Hello world!', the regions for each character are:

H -> 3@0 corner: 11@22
e -> 14@0 corner: 8@22
l -> 22@0 corner: 4@22
l -> 26@0 corner: 4@22
o -> 30@0 corner: 9@22
 -> 39@0 corner: 4@22
w -> 43@0 corner: 12@22
o -> 55@0 corner: 9@22
r -> 64@0 corner: 6@22
l -> 70@0 corner: 4@22
d -> 74@0 corner: 9@22
! -> 83@0 corner: 5@22

Origins look correct, but corners are obviously wrong.


Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: Joe Betz
Newsgroups: comp.lang.smalltalk.dolphin
Date: Thu, 26 May 2022 01:07 UTC
References: 1 2 3
X-Received: by 2002:a05:620a:22c1:b0:6a3:9974:fd12 with SMTP id o1-20020a05620a22c100b006a39974fd12mr11918074qki.93.1653527240908;
Wed, 25 May 2022 18:07:20 -0700 (PDT)
X-Received: by 2002:a05:6871:8a5:b0:f1:8d80:b5d4 with SMTP id
r37-20020a05687108a500b000f18d80b5d4mr7412048oaq.133.1653527240593; Wed, 25
May 2022 18:07:20 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!feed1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.smalltalk.dolphin
Date: Wed, 25 May 2022 18:07:20 -0700 (PDT)
In-Reply-To: <5cc2afa1-0afa-4b07-8eae-4ab12d328aacn@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=2001:861:51c3:bae0:8842:ea09:98ad:5b74;
posting-account=P1X3VgoAAADgSty0b3mKYJl_KPjmW842
NNTP-Posting-Host: 2001:861:51c3:bae0:8842:ea09:98ad:5b74
References: <f5bc8ce7-6195-4d56-97fe-40b7acbd8e20n@googlegroups.com>
<175b8d86-2354-4eb8-98bd-4131b482585bn@googlegroups.com> <5cc2afa1-0afa-4b07-8eae-4ab12d328aacn@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <36001d64-20e2-4e50-9584-ab934530718an@googlegroups.com>
Subject: Re: Implementing Graphics::MeasureCharacterRanges
From: joebet...@gmail.com (Joe Betz)
Injection-Date: Thu, 26 May 2022 01:07:20 +0000
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
X-Received-Bytes: 2633
View all headers
Oddly, treating the corners as extents gives a mostly correct region rectangle (i.e., `Rectangle origin: rect origin extent: rect corner`).But mostly correct isn't good enough since I need it to be pixel perfect. Also, it failed completely on strings longer than a dozen characters, so I've given up on MeasureCharacterRanges completely.

Backing up a bit, the whole reason I'm doing this is to implement a custom text editor. Which requires a caret, which requires knowing the position of each and every character in the text editor in order to know exactly where to position it.

MeasureCharacterRanges is supposed to let me get the region for each character in a string, and seemed like the best way to delegate kerning and other subtle formatting responsibilities to GDI+. But it obviously isn't, so now I've regressed to positioning and drawing each individual character inside the text editor, using Graphics::GetKerningPairs to get kerning information, and using `GdiplusStringFormat genericTypographic` to ensure that GDI+ doesn't add any additionally padding.

So far it's working well enough. And proved yet again that in the world of Win32 programming, if I want something done it's better to do it myself.


1
rocksolid light 0.7.2
clearneti2ptor