I would like to change the font size options that come with the Nook Reader.
The reader.apk comes with seven different font sizes : from 7.0 to 27.0
The smaller at 7.0 is too small to be useful
and the largest at 27.0 is too large
and the jump from the fifth size (13.0) to the sixth size (20) is too big a jump.
I have used apktool to take apart the apk as in this post http://forum.xda-developers.com/showthread.php?t=1735858
The font size options appear to be set in /com/bn/nook/reader/commonui/ReaderCommonUIConstants.smali
lines 117 to 129
I changed the font sizes to 11.0, 12.0, 14.0, 16.0, 18.0, 20.0 and 22.0.
Saved the .smali file.
I then used apktool to put it all back into a newreader.apk
signed newreader.apk
deleted the existing reader.apk from my nook
adb pushed this apk to /system/app/reader.apk
But when I open a book, the font size options are just the same as before my changes. It is as if no changes were made at all
Any suggestions?
ladykayaker said:
I would like to change the font size options that come with the Nook Reader.
The font size options appear to be set in /com/bn/nook/reader/commonui/ReaderCommonUIConstants.smali
lines 117 to 129
Click to expand...
Click to collapse
For those who don't feel like taking apart the apk, the lines referenced are:
Code:
.field public static final FONT_SIZE_1:D = 7.0
.field public static final FONT_SIZE_2:D = 8.5
.field public static final FONT_SIZE_3:D = 9.75
.field public static final FONT_SIZE_4:D = 11.0
.field public static final FONT_SIZE_5:D = 13.0
.field public static final FONT_SIZE_6:D = 20.0
.field public static final FONT_SIZE_7:D = 27.0
Which looks like a pretty reasonable place to make the changes, right?
To understand why this doesn't work, you need to know a little bit more about the Java compiler, specifically what it means to declare a value as static final.
Consider the following Java code:
Code:
private static final double TEST = 9.75;
private static void test() {
double myVal;
myVal = 1.23;
if (myVal != TEST)
myVal = TEST;
}
Since you've flagged the TEST value as static final, you're making a promise to the compiler. And that promise is: "I promise to never, ever change the value of TEST. It's 9.75 now and it's going to be 9.75 every time you run this program no matter what."
When the compiler hears you make that promise, it's just going to go ahead and substitute the value 9.75 every single time it comes across a reference to TEST.
So, to the compiler, the above code "pre-compiles" to:
Code:
private static final double TEST = 9.75;
private static void test() {
double myVal;
myVal = 1.23;
if (myVal != 9.75)
myVal = 9.75;
}
which we can verify against the resulting smali code:
Code:
# static fields
.field private static final TEST:D = 9.75
.method private static test()V
.registers 4
.prologue
.line 6
const-wide v0, 0x3ff3ae147ae147aeL
.line 8
.local v0, myVal:D
const-wide v2, 0x4023800000000000L
cmpl-double v2, v0, v2
if-eqz v2, :cond_13
.line 9
const-wide v0, 0x4023800000000000L
.line 10
:cond_13
return-void
.end method
(0x4023800000000000L is the hexadecimal representation of the double value 9.75)
Notice that there is still a static definition of TEST as 9.75. But in the code, there are no more references to TEST, just references to the value of TEST at the time the code was compiled.
In this example, if you were trying to replace 9.75 with 12.0, you would need to find the value 0x4023800000000000L and replace it with 0x4023800000000000L each place in the code. Of course, you need to be careful: since the constant labels have been stripped, you have no way of knowing if the original code referenced TEST, or 9.75 or OTHER_DEFINITION that also happened to be 9.75 and you don't want to change it in places where it may be referring to 9.75 as the price of a book instead of 9.75 as the size of a font.
Fortunately, 9.75 is a pretty unique value so a quick search through the Reader code results in only one result:
Code:
D:\nook\Reader>grep -ir 0x4023800000000000 *
smali/com/bn/nook/reader/commonui/ReaderCommonUIConstants$5.smali: const-wide v1, 0x4023800000000000L
Looking at the file, we can see in the Init() function is basically preparing a hashmap with the following values
Code:
1 => 0x401c (7.0)
2 => 0x4021 (9.0)
3 => 0x4023800000000000L (9.75)
4 => 0x4026 (11.0)
5 => 0x402a (13.0)
6 => 0x4034 (20.0)
7 => 0x403b (27.0)
Which is funny, because it's actually using 9.0 instead of 8.5 as the second font size despite the defined value and all of the values except 9.75 are defined as integers rather than Doubles. It looks like some B&N programmer ignored the FONT_SIZE_X definitions and just hard coded the values herself. Anyhow, this creates that mapping that is (most likely) used internally by the reader to find the proper sizing to use for each of the 7 font size options.
I don't have Reader.apk installed on my Nook so I can't actually test this out. But I'm pretty sure if you change the values in ReaderCommonUIConstants$5.smali you'll end up with the results you want.
If that doesn't work, let me make a plug for Cool Reader, which among many other advantages versus the stock Reader has a much larger range of font sizes to choose from.
Yes, that did it. I didn't consider that the values would actually be hard-coded!
Related
Hi,
I am trying to simulate a PictureBox.Click event. I have searched these forums and the ones on MSDN with many different combinations of search terms.
However I cannot find anything!
Basically what I am trying to achieve is to fire the picturebox's click event from within my code. What I have read so far seems to indicate that I need to make a call to SendMessage (COM interop?) to actually make windows perform the click.
This is for the compact framework version 1.0.
Any help you can give would be great because this is all very new to me, I'm a web application developer by trade so i'm a fish out of water on this one!
OK, the other method that I am investigating is the use of the mouse_event as demonstrated in this article by Daniel Moth.
However I am struggling to find the namespace Win32Api anywhere in the framework so I'm struggling with that also.
*Update*
I have been able to simulate a click using mouse_event in a call to the coredll using the following code:
Code:
[DllImport("coredll")]
static extern bool SetCursorPos(int X, int Y);
[DllImport("coredll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, int dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
bool tempVal = SetCursorPos(x, y);
mouse_event((uint)MouseEventFlags.LEFTDOWN, 0, 0, 0, 0);
mouse_event((uint)MouseEventFlags.LEFTUP, 0, 0, 0, 0);
however I have one outstanding problem (that I know of!).
I am struggling to capture the corrext X and Y co-ordinates of the control. I have tried many different methods and they all return values of 0 for both axis.
How do you guys do it?
Many Thanks
I haven't answered till now since I don't know .NET
But since you found your way to using native APIs I think I can help you.
This is how I would do it in C/C++:
Code:
RECT wndRect; //this is a structure that contains window top, left, bottom and right coordinates.
GetWindowRect(FindWind(L"[I]window class[/I]", L"[I]window name[/I]"), &wndRect);
x = wndRect.left + 1; //add 1 to window position to make sure the click is inside
y = wndRect.top + 1;
GetWindowRect returns the window position in screen coordinates for top left and bottom right corners.
For FindWindow to work you need to know the class and name of the window you want to find. You can find them using a utility called SPY++ which comes with any Microsoft C++ compiler.
The class is window type (so it will probably be something like 'PictureBox' or 'Image') and window name is most likely blank.
Hope this helps.
Thanks fo your help
I don't know if your code would have done the trick or not but I managed to work my way through the different class definitions to find what i needed.
Code:
int x = selectedButton.PointToScreen(selectedButton.Bounds.Location).X + 2;
int y = selectedButton.PointToScreen(selectedButton.Bounds.Location).Y + 2;
This still doesn't work but I really don't have time to work out why, all I know is that the call to SetCursorPos() returns false. I know the mouse_event code works because if I position the cursor over the Start button it opens the menu.
Time is of an essence so for now I'm just going to have to drop this and pray that I have time to finish this when towards the end of my project.
/me thinks writing my first Mobile 5.0 application in 4 days (I'm a web application developer by trade) was bad planning on the management's fault anyway
Thanks for your input though
use this method signature:
[DllImport("coredll")]
public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
int instead of uint or long.
For me it worked.
I am pasting this from my post on the MS .NETCF Dev Forums:
========================8< snip ======================
Hello.
I cannot seem to find a complete example for this, and as I am new to using unmanaged code, I need a COMPLETE one. If there is a MANAGED way to do this - great, but I certainly can't find one. Even the SHCMBM_OVERRIDEKEY constant was buried so far into the docs I needed spelunking equipment to find it.
I am writing a Dialer App, mostly as proof of concept. I cannot figure out how to capture the Talk key in order to actually place the call.
I pulled some constants from winuser.h and aygshell.h:
Code:
public const int WM_USER = 0x0400;
public const int SHCMBM_OVERRIDEKEY = (WM_USER + 403);
public const int VK_F3 = 0x72;
public const int VK_TTALK = VK_F3;
public const int SHMBOF_NODEFAULT = 0x00000001; // do not do default handling of this key
public const int SHMBOF_NOTIFY = 0x00000002; // send us the WM_* messages for this key
and imported some funcs from coredll and aygshell:
Code:
[DllImport("coredll.dll", SetLastError=true)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
[DllImport("aygshell", SetLastError=true)]
public static extern IntPtr SHFindMenuBar(IntPtr hwnd);
And then I have this call in InitializeComponent():
Code:
SendMessage((IntPtr)SHFindMenuBar(this.Handle), SHCMBM_OVERRIDEKEY, VK_TTALK, SHMBOF_NODEFAULT | SHMBOF_NOTIFY);
Now I have a couple of questions.
A - is there anything wrong with all of that?
and B - in other examples, I see people somehow getting ahold of a .Message property of the Form, but I don't seem to have System.Windows.Forms.Message anywhere... Not in the namespace or off the window object itself. I assume it's being passed back in some sort of event related to the form, but what?
I hope these aren't total n00b questions, but as I asid I am really unfamiliar with how unmanaged code really works, and have never done any Win32 C++ only vanilla C++ under unix.
Thanks in advance.
====================>8 unsnip =================
In case that's not clear: I want to make the green talk button NOT launch the phone's default dialer, but instead initiate the call from within MY dialer. The actual hardware button, not a softkey and not an on-screen button.
I am using an HTC Mogul.
.NETCF 2.0
VS2005
C#
and a partridge in a pear tree!
Any help would be MUCH appreciated. I am a little surprised that there doesn't seem to be an obvious way of doing it. Seems like a rather glaring omission to the managed SDK. Perhaps there is a way and I have just missed it.
Thanks!
Bump for the daytime crew.
Hi,
Does anybody know how to pull the time from a server and use that time to update the devices clock?
I want to lock the Clock down on the device so the best way to ensure the time is correct is to sync it with a server.
I'm using VB.net.
Give this a spin.
It sets the get the UTC time, from http://www.timeapi.org/ , but have a look at the site to see what else it can do.
Your device should deal with your timezone offset from UTC automatically.
I used .NET Reflector to translate into VB from C#, hence the odd definition of some variables.
Code:
Public Structure SYSTEMTIME
Public wYear As UInt16
Public wMonth As UInt16
Public wDayOfWeek As UInt16
Public wDay As UInt16
Public wHour As UInt16
Public wMinute As UInt16
Public wSecond As UInt16
Public wMilliseconds As UInt16
End Structure
Declare Function GetSystemTime Lib "CoreDll.dll" _
(ByRef lpSystemTime As SYSTEMTIME) As UInt32
Declare Function SetSystemTime Lib "CoreDll.dll" _
(ByRef lpSystemTime As SYSTEMTIME) As UInt32
Private Shared Sub Main(ByVal args As String())
Dim Buffer As Byte() = New Byte(&H19 - 1) {}
Dim DateItems As String() = New String(8 - 1) {}
Dim Separators As Char() = New Char() { "-"c, "-"c, "T"c, ":"c, ":"c, "+"c, ":"c }
Dim Now As New SYSTEMTIME
Program.GetSystemTime((Now))
Dim ResponseStream As Stream = WebRequest.Create("http://www.timeapi.org/utc/now").GetResponse.GetResponseStream
ResponseStream.Read(Buffer, 0, &H19)
ResponseStream.Close
DateItems = Encoding.UTF8.GetString(Buffer, 0, &H19).Split(Separators)
Now.wYear = Convert.ToUInt16(DateItems(0))
Now.wMonth = Convert.ToUInt16(DateItems(1))
Now.wDay = Convert.ToUInt16(DateItems(2))
Now.wHour = Convert.ToUInt16(DateItems(3))
Now.wMinute = Convert.ToUInt16(DateItems(4))
Now.wSecond = Convert.ToUInt16(DateItems(5))
Now.wMilliseconds = 0
Program.SetSystemTime((Now))
End Sub
The original C# code is here. You will have to convert the C# 'using' statements to VB 'Imports'
Code:
using System;
using System.Net;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace GetTime
{
class Program
{
[DllImport("coredll.dll")]
private extern static void GetSystemTime(ref SYSTEMTIME lpSystemTime);
[DllImport("coredll.dll")]
private extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime);
private struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
static void Main(string[] args)
{
byte[] Buffer = new byte[25];
string DateString;
string[] DateItems = new string[8];
char[] Separators = new char[7] { '-', '-', 'T', ':', ':', '+', ':' };
SYSTEMTIME Now = new SYSTEMTIME();
GetSystemTime(ref Now);
Stream ResponseStream = WebRequest.Create("http://www.timeapi.org/utc/now").GetResponse().GetResponseStream();
ResponseStream.Read(Buffer, 0, 25);
ResponseStream.Close();
DateString = Encoding.UTF8.GetString(Buffer, 0, 25);
DateItems = DateString.Split(Separators);
Now.wYear = Convert.ToUInt16(DateItems[0]);
Now.wMonth = Convert.ToUInt16(DateItems[1]);
Now.wDay = Convert.ToUInt16(DateItems[2]);
Now.wHour = Convert.ToUInt16(DateItems[3]);
Now.wMinute = Convert.ToUInt16(DateItems[4]);
Now.wSecond = Convert.ToUInt16(DateItems[5]);
Now.wMilliseconds = 0;
SetSystemTime(ref Now);
}
}
}
Here's how it works: The call to the URL returns the date/time as a char buffer.
"2011-12-02T14:56:38+00:00" as an example.
After converting this to a string we convert it into an array of strings in DateItems[] as
2011
12
02
14
56
38
00
00
using Separators[] to split the fields apart.
These are then converted to ushort values in the time structure, before setting the time on the device with it.
Nice code stephj .
Cheers!!!
Thanks for that stephj, will give it a go.
i've tried this and i'm getting a :
The remote server returned an error: (407) Proxy Authentication Required.
any ideas?
I tried the above program on an emulated device connected to the net via its host PC's connection and it worked a treat.
To get through a proxy, you will need to add the following code.
Code:
Program.GetSystemTime((Now))
**************INSERT THIS ****************
Dim Proxy as new WebProxy("http://ProxyServer:80/",true)
proxy.Credentials = CredentialCache.DefaultCredentials
WebRequest.DefaultWebProxy = proxy
**************INSERT ENDS ****************
Dim ResponseStream As Stream = WebRequest.Create("http://www.timeapi.org/utc/now").GetResponse.GetResponseStream
Where the first parameter of the WebProxy constructor is the name of your proxy server, and the port it uses. Here at work, we can get away with just using our proxy server's internal network DNS name of "Internet:8080", to access the outside web through a Microsoft ISA Proxy/Firewall. Note in this case the proxy uses a different port number of 8080 as opposed to the default http port of 80. If yours is not 80 you will have to provide it. You may have to do some groundwork to track down the name of your proxy server, and the port it uses. I would start by looking at the proxy setup in Settings->Connections->'Set up my proxy server' for starters.
CredentialCache.DefaultCredentials, picks up your default login/credentials and passes them to the proxy server. If it works properly, you should go through it, seamlessly.
Good luck!
Hi steph,
i tweaked this slightly and set up a webreference in my program, i then pull the time down from that in the format of "2011-12-12T09:43:14", it then splits it.
The problem i am having is that sometimes it seems to add an hour to the time.
Any ideas?
What time zone is your device operating under?
Start->Settings->[System]->Clock & Alarms->[Time]
What's the zone, and is it Home or Visiting? - I'll see if I can duplicate it.
GMT London and is set as Home.
As a test I set the time on the device to: 01/06/1999 and time 01:00:00. When i run the program the first time i press my 'Update Time' button and it returns 12/12/11 and 12:53:04, so 1 hour ahead. If i press the button again I get the correct time.
I notice on your original post that the time returned had +00:00 on the end but you dont seem to use it when you break the string down, is this not required?
Thanks for the help, much appreciated
At least I can duplicate it, so that is a start. It only seems to throw the hour forward if the date has changed, which explains why the second call to it corrects the time.
If you just knock the time back a couple of hours, a single call of the program sets the correct time.
Interesting. I'll try and get to the bottom of it, might take a day or so, on and off.
Edit: Got it!
The 1st of June 1999 is in BST one hour in front of GMT/UTC. The first call changes the date and time using BST, leaving the time pushed forward one hour. The date is then set to today's date which is in GMT/UTC. The second call sets the time against the GMT Timezone which corrects the time.
Set the date time to 04:00 yesterday and it works fine.
I'll see if we can fix it a bit better. More later.........
Here's the cure: It's C#, I'll leave you to convert it to VB.
The secret is to set the time twice, but stall the thread for ten seconds inbetween. The device will sort itself out in the gap, as various time and date housekeeping tasks are triggered. The second SetTime(), will carry out the final fix of the time before the program finally ends.
This should also work in BST when changing from a GMT/UTC date, and should also work with all global time zones.
Add this:
Code:
using System.Threading;
SetSystemTime(ref Now);
Thread.Sleep(10000);
SetSystemTime(ref Now);
that's great steph, thanks again.
There is a minor problem with the previous code:- If the minute happens to roll over in the 10 seconds while the process is asleep, then the change of minute will be lost.
Here's a better solution. Create a DateTime object in which to store the returned date and time from the WebRequest().
Use it to set the system date/time, and then advance it forward ten seconds.
Set the date/time with it again, after the ten second sleep() has elapsed.
Seems to work O.K. Post bug reports to this thread, if you find it doesn't.
Code:
using System;
using System.Net;
using System.Text;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;
namespace GetTime
{
class Program
{
[DllImport("coredll.dll")]
private extern static uint SetSystemTime(ref SYSTEMTIME lpSystemTime);
private struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
static void Main(string[] args)
{
byte[] Buffer = new byte[25];
string DateString;
string[] DateItems = new string[8];
char[] Separators = new char[7] { '-', '-', 'T', ':', ':', '+', ':' };
SYSTEMTIME Now = new SYSTEMTIME();
Stream ResponseStream = WebRequest.Create("http://www.timeapi.org/utc/now").GetResponse().GetResponseStream();
ResponseStream.Read(Buffer, 0, 25);
ResponseStream.Close();
DateString = Encoding.UTF8.GetString(Buffer, 0, 25);
DateItems = DateString.Split(Separators);
DateTime SaveTime = new DateTime(Convert.ToInt32(DateItems[0]),Convert.ToInt32(DateItems[1]),Convert.ToInt32(DateItems[2]),Convert.ToInt32(DateItems[3]),Convert.ToInt32(DateItems[4]),Convert.ToInt32(DateItems[5]));
Now.wYear = Convert.ToUInt16(SaveTime.Year);
Now.wMonth = Convert.ToUInt16(SaveTime.Month);
Now.wDay = Convert.ToUInt16(SaveTime.Day);
Now.wHour = Convert.ToUInt16(SaveTime.Hour);
Now.wMinute = Convert.ToUInt16(SaveTime.Minute);
Now.wSecond = Convert.ToUInt16(SaveTime.Second);
Now.wMilliseconds = 0;
SetSystemTime(ref Now);
SaveTime.AddSeconds(10);
Thread.Sleep(10000);
Now.wYear = Convert.ToUInt16(SaveTime.Year);
Now.wMonth = Convert.ToUInt16(SaveTime.Month);
Now.wDay = Convert.ToUInt16(SaveTime.Day);
Now.wHour = Convert.ToUInt16(SaveTime.Hour);
Now.wMinute = Convert.ToUInt16(SaveTime.Minute);
Now.wSecond = Convert.ToUInt16(SaveTime.Second);
SetSystemTime(ref Now);
}
}
}
C# .NET CF 2.0 WinMo 5.0 onwards executable is included in the zip file.
It is a console application, so don't expect anything much to happen until the 'hourglass' disappears.
If the first SetSystemTime() ends up changing the date across a Daylight Saving Boundary date, then, during the sleep() period, the device's housekeeping date/time/alarm services will probably retrigger any outstanding task and event reminders for 'today'.
P.S. GetSystemTime() can be dropped it is not required.
works like a charm steph, nice one. thanks.
@stephj, Thanks for the updated code .
Cheers!!!
Seem to be having a problem with this since UK has put the clocks forward an hour, every time I update using this code my device is adding an hour to the time.
The device is an M3 Mobile.
What are the settings on the Start-> Settings->Clock and Alarms->Time[Tab]
It should still have the Home radio button active and the time zone set to GMT London, Dublin. The mobile device should take care of daylight saving itself.
Is your M3 running WinMo 6.1 or 6.5? But I can't see it making much difference.
Works OK on a stock 6.1 Kaiser (Vodafone v1615)
Update: Also seems to work OK on the WM 6.5.3 Professional emulator.
wubbledoos said:
Hi,
Does anybody know how to pull the time from a server and use that time to update the devices clock?
I want to lock the Clock down on the device so the best way to ensure the time is correct is to sync it with a server.
I'm using VB.net.
Click to expand...
Click to collapse
Well on my Kaisers (running either wm 6.1 or 6.5) I use SKTsync to sync my device clock to one of the NIST or SNTP servers. It's freeware and it does it all for you, all you do is run the app. It's soooo simple. I also run an app called CT Scheduler lite. I use it to automatically run SKTsync every night.
Some people have expressed a need to read foreign language media on their nook, with the stock reader.
I am trying to work out how to make the necessary changes to the stock reader so that the user can select their own font family, such as thai, hebrew, korean, etc.
Using apktool to extract the smali files - I have changed the following lines
(changing from Amasis30.ttf to Hebrew.ttf)
com\bn\nook\reader\activities\ReaderActivity$34.smali
.field public static final FONT_FAMILY_AMASIS:Ljava/lang/String; = "Amasis30"
.field public static final FONT_FAMILY_AMASIS_PATH:Ljava/lang/String; = "/system/fonts/Amasis30.ttf"
com\bn\nook\reader\commonui\ReaderCommonUIConstants$6.smali
const-string v1, "Amasis30"
com\bn\nook\reader\commonui\ReaderCommonUIConstants.smali
.field public static final FONT_FAMILY_AMASIS:Ljava/lang/String; = "Amasis30"
.field public static final FONT_FAMILY_AMASIS_PATH:Ljava/lang/String; = "/system/fonts/Amasis30.ttf"
com\bn\nook\reader\commonui\TextSettingsView.smali
const-string v1, "/system/fonts/Amasis30.ttf"
But, this doesn't seem to be enough.
The font name in the list of six options still says Amasis, but it is in the new font type.
The font in the book has defaulted to Malabar font.
The preferences.xml gives the new font type.
Where else is should I look to find the references to the font file?
Quick answer: replace the two in-code references below with /system/fonts/Hebrew.ttf (assuming this is the correct path and capitalizaton for the font file)
Code:
smali/com/bn/nook/reader/activities/ReaderActivity$34.smali: const-string v3, "/system/fonts/Amasis30.ttf"
smali/com/bn/nook/reader/commonui/TextSettingsView.smali: const-string v1, "/system/fonts/Amasis30.ttf"
Leave everything else untouched. Don't worry about the "static final" definitions.
This line
smali/com/bn/nook/reader/commonui/TextSettingsView.smali: const-string v1, const-string v1, "/system/fonts/Amasis30.ttf"
sets the font for font name in the popup window where the user selects the font.
This line at first doesn't appear to make a change,
smali/com/bn/nook/reader/activities/ReaderActivity$34.smali: const-string v3, "/system/fonts/Amasis30.ttf"
the book hasn't changed to hebrew font, but on closer look the book is now in Malabar font(the one in the list above Amasis)
after digging around it appears the font may be stored in FONTFAMILY_MAP
but then again, I go round in circles following this, and it might only be used to write the ReaderPrefences.xml file.
It seems the font file names are being stored somewhere, perhaps not in Reader.apk
but I can't find where.
You might find the info in this blog:
http://phanquochuy.me/?p=114
and this thread
http://bookclubs.barnesandnoble.com...n-t-display-Vietnamese-characters/td-p/494819
helpful re: some other approaches to adding alternative fonts.
My idea is to make it easier for a user to change font in the stock reader.
I think this is done in com\bn\nook\reader\activities\ReaderActivity$34.smali
If I change the lines referring to Amasis font, to the new font name (spelling, uppercase, etc checked to be correct)
then it doesn't use the new font, it also doesn't use Amasis, but uses the previous in the list, that is Malabar.
I'm a very accomplished coder when using interpreted languages, but this low-level memory management stuff is proving hard for me to get my head around.
I'm trying to work through the OpenGL ES sample code on the official developer site and I cannot understand why they create a ByteBuffer for the vertex list and then immediately turn around and create a FloatBuffer from the ByteBuffer. Why not just allocate and reference the FloatBuffer directly? Aren't there now two sets of data that basically refer to the same set of numbers? Here's the snippet to which I am directly referring (perhaps the reason lies elsewhere in the code, though?):
public class Triangle {
private FloatBuffer vertexBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float triangleCoords[] = { // in counterclockwise order:
0.0f, 0.622008459f, 0.0f, // top
-0.5f, -0.311004243f, 0.0f, // bottom left
0.5f, -0.311004243f, 0.0f // bottom right
};
....
public Triangle() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(triangleCoords);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
}
}
It is basicallly due to the way Java uses data types. In the language of gods (C) we can just cast types and all is good.
What is happening there is a workaround basically.. machines have a word order (not sure if you have ever heard of the term back-words or byte ordering before) the ByteBuffer has a method which shuffles data to put it into the CPU byte order (ByteOrder.nativeOrder()) which can then be sent to the GPU.
Imagine the value 0xFFEE on an Intel CPU that would be stored as the 2 bytes 0xEE 0xFF or "backwards" if you will, it is called a Little endian CPU. An ARM CPU may store it is 0xFF 0xEE in memory as it is Big Endian
Since Java has it's own convention that it always uses, the ByteBuffer is there to provide a method to re-order it to whatever the CPU needs.
Hope my explanation is not more confusing! I am half-asleep and was just heading to bed :-S