text:
Have you ever had the experience of trying to write a document in MS Word (or Open/LibreOffice) and it keeps "correcting" your formatting to something you don't want? The last time I experienced that was about a year ago, and that was when I decided "screw it, I'll just write this in HTML instead". That was a good decision.
Pretty much anything you might want to use a word processor for, you can do in HTML - and oftentimes it's simpler. Sure, there's a bit of a learning curve if you don't know HTML, but that's true for anything. Now anytime I need to create "a document" (a letter, random notes or signs to print, etc.) I always do it in HTML rather than LibreOffice, and I'm the happier for it. I keep all my data in git repositories, and so it's a bonus that these documents are now in a plaintext format rather than a binary blob.
I realized that this is probably part of a trend - a lot of people I know nowadays to "powerpoint" presentations using web technologies such as reveal.js. I haven't seen many people comment on using web tech to do word processing, but I know I do it. The only big "office suite" thing left is the spreadsheet. It would be awesome if somebody wrote a drop-in JS spreadsheet library that you could include into a HTML page and instantly turn a table element into a spreadsheet.
I'm reminded of this old blog post by Joel Spolsky: How Trello is different. He talks about most of the people who use Excel really just use it because it provides a table format for entering things, rather than it's computational ability. HTML already provides that, but whenever I've tried doing that I find the markup/content ratio too high, so it always seemed like a pain. It would be nice to have a WSYIWYG tool that let you build a table (or spreadsheet) and import/export it as raw HTML that you can publish, print, share, etc.
As an addendum, that blog post by Joel also introduced me to the concept of unshipped code as "inventory", which is one of the reasons I really hate finding old bugs sitting around in Bugzilla with perfectly good patches that never landed!
November 15, 2014
Kartikaya Gupta
Killing the office suite
Have you ever had the experience of trying to write a document in MS Word (or Open/LibreOffice) and it keeps "correcting" your formatting to something you don't want? The last time I experienced that was about a year ago, and that was when I decided "screw it, I'll just write this in HTML instead". That was a good decision.
November 05, 2014
Matt Brubeck
Let's build a browser engine! Part 7: Painting 101
I'm returning at last to my series on building a simple HTML rendering engine:
- Part 1: Getting started
- Part 2: HTML
- Part 3: CSS
- Part 4: Style
- Part 5: Boxes
- Part 6: Block layout
- Part 7: Painting 101
In this article, I will add very basic painting code. This code takes the tree of boxes from the layout module and turns them into an array of pixels. This process is also known as "rasterization."
Browsers usually implement rasterization with the help of graphics APIs and libraries like Skia, Cairo, Direct2D, and so on. These APIs provide functions for painting polygons, lines, curves, gradients, and text. For now, I'm going to write my own rasterizer that can only paint one thing: rectangles.
Eventually I want to implement text rendering. At that point, I may throw away this toy painting code and switch to a "real" 2D graphics library. But for now, rectangles are sufficient to turn the output of my block layout algorithm into pictures.
Catching Up
Since my last post, I've made some small changes to the code from previous articles. These includes some minor refactoring, and some updates to keep the code compatible with the latest Rust nightly builds. None of these changes are vital to understanding the code, but if you're curious, check the commit history.
Building the Display List
Before painting, we will walk through the layout tree and build a display list. This is a list of graphics operations like "draw a circle" or "draw a string of text." Or in our case, just "draw a rectangle."
Why put commands into a display list, rather than execute them immediately? The display list is useful for a several reasons. You can search it for items that will be completely covered up by later operations, and remove them to eliminate wasted painting. You can modify and re-use the display list in cases where you know only certain items have changed. And you can use the same display list to generate different types of output: for example, pixels for displaying on a screen, or vector graphics for sending to a printer.
Robinson's display list is a vector of DisplayCommands. For now there is only one type of DisplayCommand, a solid-color rectangle:
type DisplayList = Vec<DisplayCommand>;
enum DisplayCommand {
SolidColor(Color, Rect),
// insert more commands here
To build the display list, we walk through the layout tree and generate a series of commands for each box. First we draw the box's background, then we draw its borders and content on top of the background.
fn build_display_list(layout_root: &LayoutBox) -> DisplayList {
let mut list = Vec::new();
render_layout_box(&mut list, layout_root);
return list;
fn render_layout_box(list: &mut DisplayList, layout_box: &LayoutBox) {
render_background(list, layout_box);
render_borders(list, layout_box);
// TODO: render text
for child in layout_box.children.iter() {
render_layout_box(list, child);
By default, HTML elements are stacked in the order they appear: If two elements overlap, the later one is drawn on top of the earlier one. This is reflected in our display list, which will draw the elements in the same order they appear in the DOM tree. If this code supported the z-index property, then individual elements would be able to override this stacking order, and we'd need to sort the display list accordingly.
The background is easy. It's just a solid rectangle. If no background color is specified, then the background is transparent and we don't need to generate a display command.
fn render_background(list: &mut DisplayList, layout_box: &LayoutBox) {
get_color(layout_box, "background").map(|color|
list.push(DisplayCommand::SolidColor(color, layout_box.dimensions.border_box())));
/// Return the specified color for CSS property `name`, or None if no color was specified.
fn get_color(layout_box: &LayoutBox, name: &str) -> Option<Color> {
match layout_box.box_type {
BlockNode(style) | InlineNode(style) => match style.value(name) {
Some(Value::ColorValue(color)) => Some(color),
_ => None
AnonymousBlock => None
The borders are similar, but instead of a single rectangle we draw four—one for each edge of the box.
fn render_borders(list: &mut DisplayList, layout_box: &LayoutBox) {
let color = match get_color(layout_box, "border-color") {
Some(color) => color,
_ => return // bail out if no border-color is specified
let d = &layout_box.dimensions;
let border_box = d.border_box();
// Left border
list.push(DisplayCommand::SolidColor(color, Rect {
x: border_box.x,
y: border_box.y,
width: d.border.left,
height: border_box.height,
// Right border
list.push(DisplayCommand::SolidColor(color, Rect {
x: border_box.x + border_box.width - d.border.right,
y: border_box.y,
width: d.border.right,
height: border_box.height,
// Top border
list.push(DisplayCommand::SolidColor(color, Rect {
x: border_box.x,
y: border_box.y,
width: border_box.width,
height: d.border.top,
// Bottom border
list.push(DisplayCommand::SolidColor(color, Rect {
x: border_box.x,
y: border_box.y + border_box.height - d.border.bottom,
width: border_box.width,
height: d.border.bottom,
Next the rendering function will draw each of the box's children, until the entire layout tree has been translated into display commands.
Now that we've built the display list, we need to turn it into pixels by executing each DisplayCommand. We'll store the pixels in a Canvas:
struct Canvas {
pixels: Vec<Color>,
width: uint,
height: uint,
impl Canvas {
/// Create a blank canvas
fn new(width: uint, height: uint) -> Canvas {
let white = Color { r: 255, g: 255, b: 255, a: 255 };
return Canvas {
pixels: Vec::from_elem(width * height, white),
width: width,
height: height,
// ...
To paint a rectangle on the canvas, we just loop through its rows and columns, using a helper method to make sure we don't go outside the bounds of our canvas.
fn paint_item(&mut self, item: &DisplayCommand) {
match item {
&DisplayCommand::SolidColor(color, rect) => {
// Clip the rectangle to the canvas boundaries.
let x0 = rect.x.clamp(0.0, self.width as f32) as uint;
let y0 = rect.y.clamp(0.0, self.height as f32) as uint;
let x1 = (rect.x + rect.width).clamp(0.0, self.width as f32) as uint;
let y1 = (rect.y + rect.height).clamp(0.0, self.height as f32) as uint;
for y in range(y0, y1) {
for x in range(x0, x1) {
// TODO: alpha compositing with existing pixel
self.pixels[x + y * self.width] = color;
Note that this code only works with opaque colors. If we added transparency
(by reading the
opacity property, or adding support for
rgba() values
in the CSS parser) then it would need to blend each new pixel with
whatever it's drawn on top of.
Now we can put everything together in the
paint function, which builds a
display list and then rasterizes it to a canvas:
/// Paint a tree of LayoutBoxes to an array of pixels.
fn paint(layout_root: &LayoutBox, bounds: Rect) -> Canvas {
let display_list = build_display_list(layout_root);
let mut canvas = Canvas::new(bounds.width as uint, bounds.height as uint);
for item in display_list.iter() {
return canvas;
Lastly, we can write a few lines of code using the Rust Image library to save the array of pixels as a PNG file.
Pretty Pictures
At last, we've reached the end of our rendering pipeline. In under 1000 lines of code, robinson can now parse this HTML file:

…and this CSS file:
* { display: block; padding: 12px; }
.a { background: #ff0000; }
.b { background: #ffa500; }
.c { background: #ffff00; }
.d { background: #008000; }
.e { background: #0000ff; }
.f { background: #4b0082; }
.g { background: #800080; }
…to produce this:
If you're playing along at home, here are some things you might want to try:
Write an alternate painting function that takes a display list and produces vector output (for example, an SVG file) instead of a raster image.
Add support for opacity and alpha blending.
Write a function to optimize the display list by culling items that are completely outside of the canvas bounds.
If you're familiar with OpenGL, write a hardware-accelerated painting function that uses GL shaders to draw the rectangles.
To Be Continued…
Now that we've got basic functionality for each stage in our rendering pipeline, it's time to go back and fill in some of the missing features—in particular, inline layout and text rendering. Future articles may also add additional stages, like networking and scripting.
I'm going to give a short "Let's build a browser engine!" talk at this month's Bay Area Rust Meetup. The meetup is at 7pm tomorrow (Thursday, November 6) at Mozilla's San Francisco office, and it will also feature talks on Servo by my fellow Servo developers. Video of the talks will be streamed live on Air Mozilla, and recordings will be published there later.
October 31, 2014
Geoff Brown
Firefox for Android Performance Measures – September/October check-up
I skipped my monthly review for September, so here is a review of Firefox for Android performance measurements for September and October. Highlights:
- significant regression in tcheck2
- minor regressions in tp4m, tspaint
- improvements in trobopan, tsvgx
- checkerboard regressions in eideticker
This section tracks Perfomatic graphs from graphs.mozilla.org for mozilla-central builds of Firefox for Android, for Talos tests run on Android 4.0 Opt. The test names shown are those used on tbpl. See https://wiki.mozilla.org/Buildbot/Talos for background on Talos.
Measure of "checkerboarding" during simulation of real user interaction with page. Lower values are better.
12 (start of period) – 17.8 (end of period)
Significant regression Oct 7 – bug 1086642.
Panning performance test. Value is square of frame delays (ms greater than 25 ms) encountered while panning. Lower values are better.
50000 (start of period) – 30000 (end of period)
Distinct improvement around Oct 8.
Performance of history and bookmarks' provider. Reports time (ms) to perform a group of database operations. Lower values are better.
520 (start of period) – 520 (end of period).
An svg-only number that measures SVG rendering performance. About half of the tests are animations or iterations of rendering. This ASAP test (tsvgx) iterates in unlimited frame-rate mode thus reflecting the maximum rendering throughput of each test. The reported value is the page load time, or, for animations/iterations – overall duration the sequence/animation took to complete. Lower values are better.
6300 (start of period) – 6100 (end of period).
Distinct improvement October 4.
Generic page load test. Lower values are better.
850 (start of period) – 880 (end of period).
Regression on October 22 – bug 1088669.
Startup performance test. Lower values are better.
3850 (start of period) – 3850 (end of period).
Regression on Oct 28 – bug 1091664.
Throbber Start / Throbber Stop
These graphs are taken from http://phonedash.mozilla.org. Browser startup performance is measured on real phones (a variety of popular devices).
Note the changes in throbber start (and corresponding improvements in throbber stop, below) around Oct 1 — bug 888482. Changes around Oct 28 are being investigated in bug 1091664.
These graphs are taken from http://eideticker.mozilla.org. Eideticker is a performance harness that measures user perceived performance of web browsers by video capturing them in action and subsequently running image analysis on the raw result.
More info at: https://wiki.mozilla.org/Project_Eideticker
October 29, 2014
Kartikaya Gupta
Building a NAS
I've been wanting to build a NAS (network-attached storage) box for a while now, and the ominous creaking noises from the laptop I was previously using as a file server prompted me to finally take action. I wanted to build rather than buy because (a) I wanted more control over the machine and OS, (b) I figured I'd learn something along the way and (c) thought it might be cheaper. This blog posts documents the decisions and mistakes I made and problems I ran into.
First step was figuring out the level of data redundancy and storage space I wanted. After reading up on the different RAID levels I figured 4 drives with 3 TB each in a RAID5 configuration would suit my needs for the next few years. I don't have a huge amount of data so the ~9TB of usable space sounded fine, and being able to survive single-drive failures sounded sufficient to me. For all critical data I keep a copy on a separate machine as well.
I chose to go with software RAID rather than hardware because I've read horror stories of hardware RAID controllers going obsolete and being unable to find a replacement, rendering the data unreadable. That didn't sound good. With an open-source software RAID controller at least you can get the source code and have a shot at recovering your data if things go bad.
With this in mind I started looking at software options - a bit of searching took me to FreeNAS which sounded exactly like what I wanted. However after reading through random threads in the user forums it seemed like the FreeNAS people are very focused on using ZFS and hardware setups with ECC RAM. From what I gleaned, using ZFS without ECC RAM is a bad idea, because errors in the RAM can cause ZFS to corrupt your data silently and unrecoverably (and worse, it causes propagation of the corruption). A system that makes bad situations worse didn't sound so good to me.
I could have still gone with ZFS with ECC RAM but from some rudimentary searching it sounded like it would increase the cost significantly, and frankly I didn't see the point. So instead I decided to go with NAS4Free (which actually was the original FreeNAS before iXsystems bought the trademark and forked the code) which allows using a UFS file system in a software RAID5 configuration.
So with the software decisions made, it was time to pick hardware. I used this guide by Sam Kear as a starting point and modified a few things here and there. I ended up with this parts list that I mostly ordered from canadadirect.com. (Aside: I wish I had discovered pcpartpicker.com earlier in the process as it would have saved me a lot of time). They shipped things to me in 5 different packages which arrived on 4 different days using 3 different shipping services. Woo! The parts I didn't get from canadadirect.com I picked up at a local Canada Computers store. Then, last weekend, I put it all together.
It's been a while since I've built a box so I screwed up a few things and had to rewind (twice) to fix them. Took about 3 hours in total for assembly; somebody who knew what they were doing could have done it in less than one. I mostly blame lack of documentation with the chassis since there were a bunch of different screws and it wasn't obvious which ones I had to use for what. They all worked for mounting the motherboard but only one of them was actually correct and using the wrong one meant trouble later.
In terms of the hardware compatibility I think my choices were mostly sound, but there were a few hitches. The case and motherboard both support up to 6 SATA drives (I'm using 4, giving me some room to grow). However, the PSU only came with 4 SATA power connectors which means I'll need to get some adaptors or maybe a different PSU if I need to add drives. The other problem was that the chassis comes with three fans (two small ones at the front, one big one at the back) but there was only one chassis power connector on the motherboard. I plugged the big fan in and so far the machine seems to be staying pretty cool so I'm not too worried. Does seem like a waste to have those extra unused fans though.
Finally, I booted it up using a monitor/keyboard borrowed from another machine, and ran memtest86 to make sure the RAM was good. It was, so I flashed the NAS4Free LiveUSB onto a USB drive and booted it up. Unfortunately after booting into NAS4Free my keyboard stopped working. I had to disable the USB 3.0 stuff in the BIOS to get around that. I don't really care about having USB 3.0 support on this machine so not a big deal. It took me some time to figure out what installation mode I wanted to use NAS4Free in. I decided to do a full install onto a second USB drive and not have a swap partition (figured hosting swap over USB would be slow and probably unnecessary).
So installing that was easy enough, and I was able to boot into the full NAS4Free install and configure it to have a software RAID5 on the four disks. Things generally seemed OK and I started copying stuff over.. and then the box rebooted. It also managed to corrupt my installation somehow, so I had to start over from the LiveUSB stick and re-install. I had saved the config from the first time so it was easy to get it back up again, and once again I started putting data on there. Again it rebooted, although this time it didn't corrupt my installation. This was getting worrying, particularly since the system log files provided no indication as to what went wrong.
My first suspicion was that the RAID wasn't fully initialized and so copying data onto it resulted in badness. The array was "rebuilding" and I'm supposed to be able to use it then, but I figured I might as well wait until it was done. Turns out it's going to be rebuilding for the next ~20 days because RAID5 has to read/write the entire disk to initialize fully and in the days of multi-terabyte disk this takes forever. So in retrospect perhaps RAID5 was a poor choice for such large disks.
Anyway in order to debug the rebooting, I looked up the FreeBSD kernel debugging documentation, and that requires having a swap partition that the kernel can dump a crash report to. So I reinstalled and set up a swap partition this time. This seemed to magically fix the rebooting problem entirely, so I suspect the RAID drivers just don't deal well when there's no swap, or something. Not an easy situation to debug if it only happens with no swap partition but you need a swap partition to get a kernel dump.
So, things were good, and I started copying more data over and configuring more stuff and so on. The next problem I ran into was the USB drive to which I had installed NAS4Free started crapping out with read/write errors. This wasn't so great but by this point I'd already reinstalled it about 6 or 7 times, so I reinstalled again onto a different USB stick. The one that was crapping out seems to still work fine in other machines, so I'm not sure what the problem was there. The new one that I used, however, was extremely slow. Things that took seconds on the previous drive took minutes on this one. So I switched again to yet another drive, this time an old 2.5" internal drive that I have mounted in an enclosure through USB.
And finally, after installing the OS at least I've-lost-count-how-many times, I have a NAS that seems stable and appears to work well. To be fair, reinstalling the OS is a pretty painless process and by the end I could do it in less than 10 minutes from sticking in the LiveUSB to a fully-configured working system. Being able to download the config file (which includes not just the NAS config but also user accounts and so on) makes it pretty painless to restore your system to exactly the way it was. The only additional things I had to do were install a few FreeBSD packages and unpack a tarball into my home directory to get some stuff I wanted. At no point was any of the data on the RAID array itself lost or corrupted, so I'm pretty happy about that.
In conclusion, setup was a bit of a pain, mostly due to unclear documentation and flaky USB drives (or drivers) but now that I have it set up it seems to be working well. If I ever have to do it over I might go for something other than RAID5 just because of the long rebuild time but so far it hasn't been an actual problem.
October 24, 2014
Nick Alexander
Building Fennec with Gradle and IntelliJ: first steps
Developing Fennec with Eclipse has been working well for quite some time now, but Eclipse is officially no longer supported by Google and the new standard is to build with Gradle and to edit in Android Studio or IntelliJ. I recently landed Bug 1041395 and friends, which makes it easy to build Fennec with Gradle. Here is a companion demonstration screencast.
You need the Android Support Repository and Google Repository installed. These install local Maven repositories of SDK libraries that the Gradle build depends on. To install the repositories:
android update sdk --no-ui --filter "extra-google-m2repository,extra-android-m2repository"
You can also install the repositories manually: use the android tool and select them from the Extras section.
Test a build with Gradle
./mach build && ./mach package
cd $OBJDIR/mobile/android/gradle
./gradlew build
The debug APK will be at $OBJDIR/mobile/android/base/app/build/outputs/apk/app-debug.apk.
Test a build with IntelliJ
The $OBJDIR/mobile/android/gradle directory can be imported into IntelliJ as follows:
- File > Import Project
- [select $OBJDIR/mobile/android/gradle]
- Import project from external model > Gradle
- [select Use default Gradle wrapper]
When prompted, do not add any files to git. You may need to re-open the project, or restart IntelliJ, to pick up a compiler language-level change.
Technical overview
- The Gradle build will "succeed" but crash on start up if the object directory has not been properly packaged.
- Changes to preprocessed source code and resources (namely, strings.xml.in and the accompanying DTD files) are not recognized.
- There's no support for editing JavaScript.
How the Gradle project is laid out
To the greatest extent possible, the Gradle configuration lives in the source directory. The only Gradle configuration that lives in the object directory is installed when building the mobile/android/gradle directory.
At the time of writing, their are three sub-modules: app, base, and thirdparty.
app is the Fennec wrapper; it generates the org.mozilla.fennec.R resource package. base is the Gecko code; it generates the org.mozilla.gecko.R resource package. Together, app and base address the "two package namespaces" that has plagued Fennec from day one.
Due to limitations in the Android Gradle plugin, all test code is shoved into the app module. (The issue is that, at the time of writing, there is no support for test-only APKs.) For no particular reason, the compiled C/C++ libraries are included in the app module; they could be included in the base module. I expect base to rebuilt slightly more frequently than app, so I'm hoping this choice will allow for faster incremental builds.
thirdparty is the external code we use in Fennec; it's built as an Android library but uses no resources. It's separate simply to allow the build system to cache the compiled and pre-dexed artifacts, hopefully allowing for faster incremental builds.
Recursive make backend details
The mobile/android/gradle directory writes the following into $OBJDIR/mobile/android/gradle:
- the Gradle wrapper;
- gradle.properties;
- symlinks to certain source and resource directories.
The Gradle wrapper is written to make it easy to build with Gradle from the object directory. The wrapper is intended to be checked into version control.
gradle.properties is the single source of per-object directory Gradle configuration, and provides the Gradle configuration access to configure/moz.build variables.
The symlinks are not necessary for the Gradle build itself, but they prevent nested directory errors and incorrect Java package scoping when the Gradle project is imported into IntelliJ. Because IntelliJ treats the Gradle project as authoritative, it's not sufficient to fix these manually in IntelliJ after the initial import — IntelliJ reverts to the Gradle configuration after every build. Since there aren't many symlinks, I've done them in the Makefile rather than at a higher level of abstraction (like a moz.build definition, or a custom build backend). In future, I expect to be able to remove all such symlinks by making our in-tree directory structures agree with what Gradle and IntelliJ expect.
Many thanks to ckitching for doing the first work on developing Fennec with IntelliJ. Thanks also to mhaigh for championing IntelliJ as the tool of choice for the Fennec front-end team, and to wesj for circulating updated IntelliJ usage notes.
- Fri 14 Nov 2014: Included Maven repository prerequisites. Thanks to mcomella for reporting the underlying issue and to IRC user rogeliodh for the command line one-liner.
October 23, 2014
James Willcox
MP4 improvements in Firefox for Android
One of the things that has always been a bit of a struggle in Firefox for Android is getting reliable video decoding for H264. For a couple of years, we've been shipping an implementation that went through great heroics in order to use libstagefright directly. While it does work fine in many cases, we consistently get reports of videos not playing, not displayed correctly, or just crashing.
In Android 4.1, Google added the
MediaCodec class to the SDK. This provides a blessed interface to the underlying libstagefright API, so presumably it will be far more reliable. This summer, my intern Martin McDonough worked on adding a decoding backend in Firefox for Android that uses this class. I expected him to be able to get something that sort of worked by the end of the internship, but he totally shocked me by having video on the screen inside of two weeks. This included some time spent modifying our JNI bindings generator to work against the Android SDK. You can view Martin's intern presentation on Air Mozilla.
While the API for MediaCodec seems relatively straightforward, there are several details you need to get right or the whole thing falls apart. Martin constantly ran into problems where it would throw IllegalStateException for seemingly no valid reason. There was no error message or other explanation in the exception. This made development pretty frustrating, but he fought through it. It looks like Google has improved both the documentation and the error handling in the API as of Lollipop, so that's good to see.
As Martin wrapped up his internship he was working on handling the video frames as output by the decoder. Ideally you would get some kind of sane YUV variation, but this often is not the case. Qualcomm devices frequently output in their own proprietary format,
OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka. You'll notice this doesn't even appear in the list of possibilities according to
MediaCodecInfo.CodecCapabilities. It does, however, appear in the OMX headers, along with a handful of other proprietary formats. Great, so Android has this mostly-nice class to decode video, but you can't do anything with the output? Yeah. Kinda. It turns out we actually have code to handle this format for B2G, because we run on QC hardware there, so this specific case had a possible solution. But maybe there is a better way?
I know from my work on supporting Flash on Android that we use a
SurfaceTexture there to render video layers from the plugin. It worked really well most of the time. We can use that with
MediaCodec too. With this output path we don't ever see the raw data; it goes straight into the
Surface attached to the
SurfaceTexture. You can then composite it with OpenGL and the crazy format conversions are done by the GPU. Pretty nice! I think handling all the different YUV conversions would've been a huge source of pain, so I was happy to eliminate that entire class of bugs. I imagine the GPU conversions are probably faster, too.
There is one problem with this. Sometimes we need to do something with the video other than composite it onto the screen with OpenGL. One common usage is to draw the video into a canvas (either 2D or WebGL). Now we have a problem, because the only way to get stuff out of the
SurfaceTexture (and the attached
Surface) is to draw it with OpenGL. Initially, my plan to handle this was to ask the compositor to draw this single
SurfaceTexture separately into a temporary FBO, read it back, and give me those bits. It worked, but boy was it ugly. There has to be a better way, right? There is, but it's still not great.
SurfaceTexture, as of Jelly Bean, allows you to attach and detach a GL context. Once attached, the
updateTexImage() call updates whatever texture you attached. Detaching frees that texture, and makes the
SurfaceTexture able to be attached to another texture (or GL context). My idea was to only attach the compositor to the
SurfaceTexture while it was drawing it, and detach after. This would leave the
SurfaceTexture able to be consumed by another GL context/texture. For doing the readback, we just attach to a context created specifically for this purpose on the main thread, blit the texture to a FBO, read the pixels, detach. Performance is not great, as
glReadPixels() always seems to be slow on mobile GPUs, but it works. And it doesn't involve IPC to the compositor. I had to resort to a little hack to make some of this work well, though. Right now there is no way to create a
SurfaceTexture in an initially detached state. You must always pass a texture in the constructor, so I pass
0 and then immediately call
detachFromGLContext(). Pretty crappy, but it should be relatively safe. I filed an Android bug to request a no-arg constructor for SurfaceTexture more than two years ago, but nothing has happened. I'm not sure why Google even allows people to file stuff, honestly.
tl;dr: Video decoding should be much better in Firefox for Android as of today's Nightly if you are on Jelly Bean or higher. Please give it a try, especially if you've had problems in the past. Also, file bugs if you have issues!
October 22, 2014
Matt Brubeck
A little randomness for Hacker News
In systems that rely heavily on "most popular" lists, like Reddit or Hacker News, the rich get richer while the poor stay poor. Since most people only look at the top of the charts, anything that's not already listed has a much harder time being seen. You need visibility to get ratings, and you need ratings to get visibility.
Aggregators try to address this problem by promoting new items as well as popular ones. But this is hard to do effectively. For example, the "new" page at Hacker News gets only a fraction of the front page's traffic. Most users want to see the best content, not wade through an unfiltered stream of links. Thus, very little input is available to decide which links get promoted to the front page.
As an experiment, I wrote a userscript that uses the Hacker News API to search for new or low-ranked links and randomly insert just one or two of them into the front page. It's also available as a bookmarklet for those who can't or don't want to install the user script.
Install user script (may require a browser extension)
Randomize HN (drag to bookmark bar, or right-click to bookmark)
This gives readers a chance to see and vote on links that they otherwise wouldn't, without altering their habits or wading through a ton of unfiltered content. Each user will see just one or two links per visit, but thanks to randomness a much larger number of links will be seen by the overall user population. My belief, though I can't prove it, is that widespread use of this feature would improve the quality of the selection process.
The script isn't perfect (search for FIXME in the source code for some known issues), but it works well enough to try out the idea. Unfortunately, the HN API doesn't give access to all the data I'd like, and sometimes the script won't find any suitable links to insert. (You can look at your browser's console to see which which items were randomly inserted.) Ideally, this feature would be built in to Hacker News—and any other service that recommends "popular" items.
October 19, 2014
Kartikaya Gupta
Google-free android usage
When I switched from using a BlackBerry to an Android phone a few years ago it really irked me that the only way to keep my contacts info on the phone was to also let Google sync them into their cloud. This may not be true universally (I think some samsung phones will let you store contacts to the SD card) but it was true for phone I was using then and is true on the Nexus 4 I'm using now. It took a lot of painful digging through Android source and googling, but I successfully ended up writing a bunch of code to get around this.
I've been meaning to put up the code and post this for a while, but kept procrastinating because the code wasn't generic/pretty enough to publish. It still isn't but it's better to post it anyway in case somebody finds it useful, so that's what I'm doing.
In a nutshell, what I wrote is an Android app that includes (a) an account authenticator, (b) a contacts sync adapter and (c) a calendar sync adapter. On a stock Android phone this will allow you to create an "account" on the device and add contacts/calendar entries to it.
Note that I wrote this to interface with the way I already have my data stored, so the account creation process actually tries to validate the entered credentials against a webhost, and the the contacts sync adapter is actually a working one-way sync adapter that will download contact info from a remote server in vcard format and update the local database. The calendar sync adapter, though, is just a dummy. You're encouraged to rip out the parts that you don't want and use the rest as you see fit. It's mostly meant to be a working example of how this can be accomplished.
The net effect is that you can store contacts and calendar entries on the device so they don't get synced to Google, but you can still use the built-in contacts and calendar apps to manipulate them. This benefits from much better integration with the rest of the OS than if you were to use a third-party contacts or calendar app.
Source code is on Github: staktrace/pimple-android.
October 07, 2014
Lucas Rocha
Probing with Gradle
Up until now, Probe relied on dynamic view proxies generated at runtime to intercept View calls. Although very convenient, this approach greatly affects the time to inflate your layouts—which limits the number of use cases for the library, especially in more complex apps.
This is all changing now with Probe's brand new Gradle plugin which seamlessly generates build-time proxies for your app. This means virtually no overhead at runtime!
Using Probe's Gradle plugin is very simple. First, add the Gradle plugin as a dependency in your build script.
buildscript { ... dependencies { ... classpath 'org.lucasr.probe:gradle-plugin:0.1.3' } }
Then apply the plugin to your app's build.gradle.
apply plugin: 'org.lucasr.probe'
Probe's proxy generation is disabled by default and needs to be explicitly enabled on specific build variants (build type + product flavour). For example, this is how you enable Probe proxies in debug builds.
probe { buildVariants { debug { enabled = true } } }
And that's all! You should now be able to deploy interceptors on any part of your UI. Here's how you could deploy an OvermeasureInterceptor in an activity.
public final class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { Probe.deploy(this, new OvermeasureInterceptor()); super.onCreate(savedInstanceState); setContentView(R.id.main_activity); } }
While working on this feature, I have changed DexMaker to be an optional dependency i.e. you have to explicitly add DexMaker as a build dependency in your app in order to use it.
This is my first Gradle plugin. There's definitely a lot of room for improvement here. These features are available in the 0.1.3 release in Maven Central.
As usual, feedback, bug reports, and fixes are very welcome. Enjoy!
September 29, 2014
William Lachance
Using Flexbox in web applications
Over last few months, I discovered the joy that is CSS Flexbox, which solves the "how do I lay out this set of div's in horizontally or vertically". I've used it in three projects so far:
- Centering the timer interface in my meditation app, so that it scales nicely from a 320×480 FirefoxOS device all the way up to a high definition monitor
- Laying out the chart / sidebar elements in the Eideticker dashboard so that maximum horizontal space is used
- Fixing various problems in the Treeherder UI on smaller screens (see bug 1043474 and its dependent bugs)
When I talk to people about their troubles with CSS, layout comes up really high on the list. Historically, basic layout problems like a panel of vertical buttons have been ridiculously difficult, involving hacks involving floating divs and absolute positioning or JavaScript layout libraries. This is why people write articles entitled "Give up and use tables".
Flexbox has pretty much put an end to these problems for me. There's no longer any need to "give up and use tables" because using flexbox is pretty much just *like* using tables for layout, just with more uniform and predictable behaviour. They're so great. I think we're pretty close to Flexbox being supported across all the major browsers, so it's fair to start using them for custom web applications where compatibility with (e.g.) IE8 is not an issue.
To try and spread the word, I wrote up a howto article on using flexbox for web applications on MDN, covering some of the common use cases I mention above. If you've been curious about flexbox but unsure how to use it, please have a look.
September 23, 2014
Lucas Rocha
New Features in Picasso
I've always been a big fan of Picasso, the Android image loading library by the Square folks. It provides some powerful features with a rather simple API.
Recently, I started working on a set of new features for Picasso that will make it even more awesome: request handlers, request management, and request priorities. These features have all been merged to the main repo now. Let me give you a quick overview of what they enable you to do.
Request Handlers
Picasso supports a wide variety of image sources, from simple resources to content providers, network, and more. Sometimes though, you need to load images in unconventional ways that are not supported by default in Picasso.
Wouldn't it be nice if you could easily integrate your custom image loading logic with Picasso? That's what the new request handlers are about. All you need to do is subclass RequestHandler and implement a couple of methods. For example:
public class PonyRequestHandler extends RequestHandler { private static final String PONY_SCHEME = "pony"; @Override public boolean canHandleRequest(Request data) { return PONY_SCHEME.equals(data.uri.getScheme()); } @Override public Result load(Request data) { return new Result(somePonyBitmap, MEMORY); } }
Then you register your request handler when instantiating Picasso:
Picasso picasso = new Picasso.Builder(context) .addRequestHandler(new PonyHandler()) .build();
Voilà! Now Picasso can handle pony URIs:
picasso.load("pony://somePonyName") .into(someImageView)
This pull request also involved rewriting all built-in bitmap loaders on top of the new API. This means you can also override the built-in request handlers if you need to.
Request Management
Even though Picasso handles view recycling, it does so in an inefficient way. For instance, if you do a fling gesture on a ListView, Picasso will keep triggering and canceling requests blindly because there was no way to make it pause/resume requests according to the user interaction. Not anymore!
The new request management APIs allow you to tag associated requests that should be managed together. You can then pause, resume, or cancel requests associated with specific tags. The first thing you have to do is tag your requests as follows:
Picasso.with(context) .load("http://example.com/image.jpg") .tag(someTag) .into(someImageView)
Then you can pause and resume requests with this tag based on, say, the scroll state of a ListView. For example, Picasso's sample app now has the following scroll listener:
public class SampleScrollListener implements AbsListView.OnScrollListener { ... @Override public void onScrollStateChanged(AbsListView view, int scrollState) { Picasso picasso = Picasso.with(context); if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_TOUCH_SCROLL) { picasso.resumeTag(someTag); } else { picasso.pauseTag(someTag); } } ... }
These APIs give you a much finer control over your image requests. The scroll listener is just the canonical use case.
Request Priorities
It's very common for images in your Android UI to have different priorities. For instance, you may want to give higher priority to the big hero image in your activity in relation to other secondary images in the same screen.
Up until now, there was no way to hint Picasso about the relative priorities between images. The new priority API allows you to tell Picasso about the intended order of your image requests. You can just do:
Picasso.with(context) .load("http://example.com/image.jpg") .priority(HIGH) .into(someImageView);
These priorities don't guarantee a specific order, they just tilt the balance in favour of higher-priority requests.
That's all for now. Big thanks to Jake Wharton and Dimitris Koutsogiorgas for the prompt code and API reviews!
You can try these new APIs now by fetching the latest Picasso code on Github. These features will probably be available in the 2.4 release. Enjoy!
September 18, 2014
Kartikaya Gupta
Maker Party shout-out
I've blogged before about the power of web scale; about how important it is to ensure that everybody can use the web and to keep it as level of a playing field as possible. That's why I love hearing about announcements like this one: 127K Makers, 2513 Events, 86 Countries, and One Party That Just Won't Quit. Getting more people all around the world to learn about how the web works and keeping that playing field level is one of the reasons I love working at Mozilla. Even though I'm not directly involved in Maker Party, it's great to see projects like this having such a huge impact!
Matt Brubeck
Let's build a browser engine! Part 6: Block layout
Welcome back to my series on building a toy HTML rendering engine:
- Part 1: Getting started
- Part 2: HTML
- Part 3: CSS
- Part 4: Style
- Part 5: Boxes
- Part 6: Block layout
- Part 7: Painting 101
This article will continue the layout module that we started in Part 5. This time, we'll add the ability to lay out block boxes. These are boxes that are stack vertically, such as headings and paragraphs.
To keep things simple, this code implements only normal flow: no floats, no absolute positioning, and no fixed positioning.
Traversing the Layout Tree
The entry point to this code is the
layout function, which takes a takes a
LayoutBox and calculates its dimensions. We'll break this function into three
cases, and implement only one of them for now:
impl LayoutBox {
/// Lay out a box and its descendants.
fn layout(&mut self, containing_block: Dimensions) {
match self.box_type {
BlockNode(_) => self.layout_block(containing_block),
InlineNode(_) => {} // TODO
AnonymousBlock => {} // TODO
// ...
A block's layout depends on the dimensions of its containing block. For block boxes in normal flow, this is just the box's parent. For the root element, it's the size of the browser window (or "viewport").
You may remember from the previous article that a block's width depends on its parent, while its height depends on its children. This means that our code needs to traverse the tree top-down while calculating widths, so it can lay out the children after their parent's width is known, and traverse bottom-up to calculate heights, so that a parent's height is calculated after its children's.
fn layout_block(&mut self, containing_block: Dimensions) {
// Child width can depend on parent width, so we need to calculate
// this box's width before laying out its children.
// Determine where the box is located within its container.
// Recursively lay out the children of this box.
// Parent height can depend on child height, so `calculate_height`
// must be called *after* the children are laid out.
This function performs a single traversal of the layout tree, doing width calculations on the way down and height calculations on the way back up. A real layout engine might perform several tree traversals, some top-down and some bottom-up.
Calculating the Width
The width calculation is the first step in the block layout function, and also
the most complicated. I'll walk through it step by step. To start, we need
the values of the CSS
width property and all the left and right edge sizes:
fn calculate_block_width(&mut self, containing_block: Dimensions) {
let style = self.get_style_node();
// `width` has initial value `auto`.
let auto = Keyword("auto".to_string());
let mut width = style.value("width").unwrap_or(auto.clone());
// margin, border, and padding have initial value 0.
let zero = Length(0.0, Px);
let mut margin_left = style.lookup("margin-left", "margin", &zero);
let mut margin_right = style.lookup("margin-right", "margin", &zero);
let border_left = style.lookup("border-left-width", "border-width", &zero);
let border_right = style.lookup("border-right-width", "border-width", &zero);
let padding_left = style.lookup("padding-left", "padding", &zero);
let padding_right = style.lookup("padding-right", "padding", &zero);
// ...
This uses a helper function called
lookup, which just tries a
series of values in sequence. If the first property isn't set, it tries the
second one. If that's not set either, it returns the given default value.
This provides an incomplete (but simple) implementation of shorthand
properties and initial values.
Note: This is similar to the following code in, say, JavaScript or Ruby:
margin_left = style["margin-left"] || style["margin"] || zero;
Since a child can't change its parent's width, it needs to make sure its own width fits the parent's. The CSS spec expresses this as a set of constraints and an algorithm for solving them. The following code implements that algorithm.
First we add up the margin, padding, border, and content widths. The
to_px helper method converts lengths to their numerical values. If
a property is set to
'auto', it returns 0 so it doesn't affect the sum.
let total = [&margin_left, &margin_right, &border_left, &border_right,
&padding_left, &padding_right, &width].iter().map(|v| v.to_px()).sum();
This is the minimum horizontal space needed for the box. If this isn't equal to the container width, we'll need to adjust something to make it equal.
If the width or margins are set to
'auto', they can expand or contract to
fit the available space. Following the spec, we first check if the box is too
big. If so, we set any expandable margins to zero.
// If width is not auto and the total is wider than the container, treat auto margins as 0.
if width != auto && total > containing_block.content.width {
if margin_left == auto {
margin_left = Length(0.0, Px);
if margin_right == auto {
margin_right = Length(0.0, Px);
If the box is too large for its container, it overflows the container. If it's too small, it will underflow, leaving extra space. We'll calculate the underflow—the amount of extra space left in the container. (If this number is negative, it is actually an overflow.)
let underflow = containing_block.content.width - total;
We now follow the spec's algorithm for eliminating any
overflow or underflow by adjusting the expandable dimensions. If there are no
'auto' dimensions, we adjust the right margin. (Yes, this means the
margin may be negative in the case of an overflow!)
match (width == auto, margin_left == auto, margin_right == auto) {
// If the values are overconstrained, calculate margin_right.
(false, false, false) => {
margin_right = Length(margin_right.to_px() + underflow, Px);
// If exactly one size is auto, its used value follows from the equality.
(false, false, true) => { margin_right = Length(underflow, Px); }
(false, true, false) => { margin_left = Length(underflow, Px); }
// If width is set to auto, any other auto values become 0.
(true, _, _) => {
if margin_left == auto { margin_left = Length(0.0, Px); }
if margin_right == auto { margin_right = Length(0.0, Px); }
if underflow >= 0.0 {
// Expand width to fill the underflow.
width = Length(underflow, Px);
} else {
// Width can't be negative. Adjust the right margin instead.
width = Length(0.0, Px);
margin_right = Length(margin_right.to_px() + underflow, Px);
// If margin-left and margin-right are both auto, their used values are equal.
(false, true, true) => {
margin_left = Length(underflow / 2.0, Px);
margin_right = Length(underflow / 2.0, Px);
At this point, the constraints are met and any
'auto' values have been
converted to lengths. The results are the the used values for
the horizontal box dimensions, which we will store in the layout tree. You
can see the final code in layout.rs.
The next step is simpler. This function looks up the remanining margin/padding/border styles, and uses these along with the containing block dimensions to determine this block's position on the page.
fn calculate_block_position(&mut self, containing_block: Dimensions) {
let style = self.get_style_node();
let d = &mut self.dimensions;
// margin, border, and padding have initial value 0.
let zero = Length(0.0, Px);
// If margin-top or margin-bottom is `auto`, the used value is zero.
d.margin.top = style.lookup("margin-top", "margin", &zero).to_px();
d.margin.bottom = style.lookup("margin-bottom", "margin", &zero).to_px();
d.border.top = style.lookup("border-top-width", "border-width", &zero).to_px();
d.border.bottom = style.lookup("border-bottom-width", "border-width", &zero).to_px();
d.padding.top = style.lookup("padding-top", "padding", &zero).to_px();
d.padding.bottom = style.lookup("padding-bottom", "padding", &zero).to_px();
// Position the box below all the previous boxes in the container.
d.content.x = containing_block.content.x +
d.margin.left + d.border.left + d.padding.left;
d.content.y = containing_block.content.y + containing_block.content.height +
d.margin.top + d.border.top + d.padding.top;
Take a close look at that last statement, which sets the
y position. This
is what gives block layout its distinctive vertical stacking behavior. For
this to work, we'll need to make sure the parent's
height is updated after
laying out each child.
Here's the code that recursively lays out the box's contents. As it loops through the child boxes, it keeps track of the total content height. This is used by the positioning code (above) to find the vertical position of the next child.
fn layout_block_children(&mut self) {
let d = &mut self.dimensions;
for child in self.children.iter_mut() {
// Track the height so each child is laid out below the previous content.
d.content.height = d.content.height + child.dimensions.margin_box().height;
The total vertical space taken up by each child is the height of its margin box, which we calculate like so:
impl Rect {
fn expanded_by(self, edge: EdgeSizes) -> Rect {
Rect {
x: self.x - edge.left,
y: self.y - edge.top,
width: self.width + edge.left + edge.right,
height: self.height + edge.top + edge.bottom,
impl Dimensions {
/// The area covered by the content area plus its padding.
fn padding_box(self) -> Rect {
/// The area covered by the content area plus padding and borders.
fn border_box(self) -> Rect {
/// The area covered by the content area plus padding, borders, and margin.
fn margin_box(self) -> Rect {
For simplicity, this does not implement margin collapsing. A real layout engine would allow the bottom margin of one box to overlap the top margin of the next box, rather than placing each margin box completely below the previous one.
The 'height' Property
By default, the box's height is equal to the height of its contents. But if
'height' property is set to an explicit length, we'll use that instead:
fn calculate_block_height(&mut self) {
// If the height is set to an explicit length, use that exact length.
match self.get_style_node().value("height") {
Some(Length(h, Px)) => { self.dimensions.content.height = h; }
_ => {}
And that concludes the block layout algorithm. You can now call
layout() on
a styled HTML document, and it will spit out a bunch of rectangles with
widths, heights, margins, etc. Cool, right?
Some extra ideas for the ambitious implementer:
Collapsing vertical margins.
Parallelize the layout process, and measure the effect on performance.
If you try the parallelization project, you may want to separate the width
calculation and the height calculation into two distinct passes. The top-down
traversal for width is easy to parallelize just by spawning a separate task
for each child. The height calculation is a little trickier, since you need
to go back and adjust the
y position of each child after its siblings are
laid out.
To Be Continued…
Thank you to everyone who's followed along this far!
These articles are taking longer and longer to write, as I journey further into unfamiliar areas of layout and rendering. There will be a longer hiatus before the next part as I experiment with font and graphics code, but I'll resume the series as soon as I can.
Update: Part 7 is now ready.
September 16, 2014
Lucas Rocha
Introducing Probe
We've all heard of the best practices regarding layouts on Android: keep your view tree as simple as possible, avoid multi-pass layouts high up in the hierarchy, etc. But the truth is, it's pretty hard to see what's actually going on in your view tree in each UI traversal (measure → layout → draw).
We're well served with developer options for tracking graphics performance—debug GPU overdraw, show hardware layers updates, profile GPU rendering, and others. However, there is a big gap in terms of development tools for tracking layout traversals and figuring out how your layouts actually behave. This is why I created Probe.
Probe is a small library that allows you to intercept view method calls during Android's layout traversals e.g. onMeasure(), onLayout(), onDraw(), etc. Once a method call is intercepted, you can either do extra things on top of the view's original implementation or completely override the method on-the-fly.
Using Probe is super simple. All you have to do is implement an Interceptor. Here's an interceptor that completely overrides a view's onDraw(). Calling super.onDraw() would call the view's original implementation.
public class DrawGreen extends Interceptor { private final Paint mPaint; public DrawGreen() { mPaint = new Paint(); mPaint.setColor(Color.GREEN); } @Override public void onDraw(View view, Canvas canvas) { canvas.drawPaint(mPaint); } }
Then deploy your Interceptor by inflating your layout with a Probe:
Probe probe = new Probe(this, new DrawGreen(), new Filter.ViewId(R.id.view2)); View root = probe.inflate(R.layout.main_activity, null);
Just to give you an idea of the kind of things you can do with Probe, I've already implemented a couple of built-in interceptors. OvermeasureInterceptor tints views according to the number of times they got measured in a single traversal i.e. equivalent to overdraw but for measurement.
LayoutBoundsInterceptor is equivalent to Android's "Show layout bounds" developer option. The main difference is that you can show bounds only for specific views.
Under the hood, Probe uses Google's DexMaker to generate dynamic View proxies during layout inflation. The stock ProxyBuilder implementation was not good enough for Probe because I wanted to avoid using reflection entirely after the proxy classes were generated. So I created a specialized View proxy builder that generates proxy classes tailored for Probe's use case.
This means Probe takes longer than your usual LayoutInflater to inflate layout resources. There's no use of reflection after layout inflation though. Your views should perform the same. For now, Probe is meant to be a developer tool only and I don't recommend using it in production.
The code is available on Github. As usual, contributions are very welcome.
September 15, 2014
William Lachance
mozregression 0.24
I just released mozregression 0.24. This would be a good time to note some of the user-visible fixes / additions that have gone in recently:
- Thanks to Sam Garrett, you can now specify a different branch other than inbound to get finer grained regression ranges from. E.g. if you're pretty sure a regression occurred on fx-team, you can do something like:
mozregression --inbound-branch fx-team -g 2014-09-13 -b 2014-09-14
- Fixed a bug where we could get an incorrect regression range (bug 1059856). Unfortunately the root cause of the bug is still open (it's a bit tricky to match mozilla-central commits to that of other branches) but I think this most recent fix should make things work in 99.9% of cases. Let me know if I'm wrong.
- Thanks to Julien Pagès, we now download the inbound build metadata in parallel, which speeds up inbound bisection quite significantly
If you know a bit of python, contributing to mozregression is a great way to have a high impact on Mozilla. Many platform developers use this project in their day-to-day work, but there's still lots of room for improvement.
September 12, 2014
Geoff Brown
Running my own AutoPhone
AutoPhone is a brilliant platform for running automated tests on physical mobile devices.
:bc maintains an AutoPhone instance running startup performance tests (aka "S1/S2 tests" or "throbber start/stop tests") on a small farm of test phones; those tests run against all of our Firefox for Android builds and results are reported to PhoneDash, available for viewing at http://phonedash.mozilla.org/.
I have used phonedash.mozilla.org for a long time now, and reported regressions in bugs and in my monthly "Performance Check-up" posts, but I have never looked under the covers or tried to use AutoPhone myself — until this week.
All things considered, it is surprisingly easy to set up your own AutoPhone instance and run your own tests. You might want to do this to reproduce phonedash.mozilla.org results on your own computer, or to check for regressions on a feature before check-in.
Here's what I did to run my own AutoPhone instance running S1/S2 tests against mozilla-inbound builds:
Install AutoPhone:
git clone https://github.com/mozilla/autophone
cd autophone
pip install -r requirements.txt
Install PhoneDash, to store and view results:
git clone https://github.com/markrcote/phonedash
Create a phonedash settings file, phonedash/server/settings.cfg with content:
Start phonedash:
python server.py <ip address of your computer>
It will log status messages to the console. Watch that for any errors, and to get a better understanding of what's happening.
Prepare your device:
Connect your Android phone or tablet to your computer by USB. Multiple devices may be connected. Each device must be rooted. Check that you can see your devices with adb devices — and note the serial number(s) (see devices.ini below).
Configure your device:
cp devices.ini.example devices.ini
Edit devices.ini, changing the serial numbers to your device serial numbers and the device names to something meaningful to you. Here's my simple devices.ini for one device I called "gbrown":
Configure autophone:
cp autophone.ini.example autophone.ini
Edit autophone.ini to make it your own. Most of the defaults are fine; here is mine:
#clear_cache = False
#ipaddr = …
#port = 28001
#cachefile = autophone_cache.json
#logfile = autophone.log
loglevel = DEBUG
test_path = tests/manifest.ini
#emailcfg = email.ini
enable_pulse = True
enable_unittests = False
#cache_dir = builds
#override_build_dir = None
repos = mozilla-inbound
#buildtypes = opt
#build_cache_port = 28008
verbose = True
#build_cache_size = 20
#build_cache_expires = 7
#device_ready_retry_wait = 20
#device_ready_retry_attempts = 3
#device_battery_min = 90
#device_battery_max = 95
#phone_retry_limit = 2
#phone_retry_wait = 15
#phone_max_reboots = 3
#phone_ping_interval = 15
#phone_command_queue_timeout = 10
#phone_command_queue_timeout = 1
#phone_crash_window = 30
#phone_crash_limit = 5
python autophone.py -h provides help on options, which are analogues of the autophone.ini settings.
Configure your tests:
Notice that autophone.ini has a test path of tests/manifest.ini. By default, tests/manifest.ini is configured for S1/S2 tests — it points to configs/s1s2_settings.ini. We need to set up that file:
cd configs
cp s1s2_settings.ini.example s1s2_settings.ini
Edit s1s2_settings.ini to make it your own. Here's mine:
#source = files/
#dest = /mnt/sdcard/tests/autophone/s1test/
#profile = /data/local/tmp/profile
# test locations can be empty to specify a local
# path on the device or can be a url to specify
# a web server.
local =
remote = http://192.168.0.82:8080/
blank = blank.html
twitter = twitter.html
iterations = 2
resulturl = http://192.168.0.82:8080/api/s1s2/
id =
key =
Be sure to set the resulturl to match your PhoneDash instance.
If running local tests, copy your test files (like blank.html above) to the files directory. If runnng remote tests, be sure that your test files are served from the resulturl (if using PhoneDash, copy to the html directory).
Start autophone:
python autophone.py –config autophone.ini
With these settings, autophone will listen for new builds on mozilla-inbound, and start tests on your device(s) for each one. You should start to see your device reboot, then Firefox will be installed and startup tests will run. As more builds complete on mozilla-inbound, more tests will run.
autophone.py will print some diagnostics to the console, but much more detail is available in autophone.log — watch that to see what's happening.
Check your phonedash instance for results — visit http://<ip address of your computer>:8080. At first this won't have any data, but as autophone runs tests, you'll start to see results. Here's my instance after a few hours:
September 11, 2014
William Lachance
Hacking on the Treeherder front end: refreshingly easy
Over the past two weeks, I've been working a bit on the Treeherder front end (our interface to managing build and test jobs from mercurial changesets), trying to help get things in shape so that the sheriffs can feel comfortable transitioning to it from tbpl by the end of the quarter.
One thing that has pleasantly surprised me is just how easy it's been to get going and be productive. The process looks like this on Linux or Mac:
git clone https://github.com/mozilla/treeherder-ui.git
cd treeherder-ui/webapp
We have a fair backlog of issues to get through, many of them related to the front end. If you're interested in helping out, please have a look:
If nothing jumps out at you, please drop by irc.mozilla.org #treeherder and we can probably find something for you to work on. We're most active during Pacific Time working hours.
September 08, 2014
Matt Brubeck
Let's build a browser engine! Part 5: Boxes
This is the latest in a series of articles about writing a simple HTML rendering engine:
This article will begin the layout module, which takes the style tree and translates it into a bunch of rectangles in a two-dimensional space. This is a big module, so I'm going to split it into several articles. Also, some of the code I share in this article may need to change as I write the code for the later parts.
The layout module's input is the style tree from Part 4, and its output is yet another tree, the layout tree. This takes us one step further in our mini rendering pipeline:
I'll start by talking about the basic HTML/CSS layout model. If you've ever learned to develop web pages you might be familiar with this already—but it may look a bit different from the implementer's point of view.
The Box Model
Layout is all about boxes. A box is a rectangular section of a web page. It has a width, a height, and a position on the page. This rectangle is called the content area because it's where the box's content is drawn. The content may be text, image, video, or other boxes.
A box may also have padding, borders, and margins surrounding its content area. The CSS spec has a diagram showing how all these layers fit together.
Robinson stores a box's content area and surrounding areas in the following
structure. [Rust note:
f32 is a 32-bit floating point type.]
// CSS box model. All sizes are in px.
struct Dimensions {
/// Position of the content area relative to the document origin:
content: Rect,
// Surrounding edges:
padding: EdgeSizes,
border: EdgeSizes,
margin: EdgeSizes,
struct Rect {
x: f32,
y: f32,
width: f32,
height: f32,
struct EdgeSizes {
left: f32,
right: f32,
top: f32,
bottom: f32,
Block and Inline Layout
Note: This section contains diagrams that won't make sense if you are reading them without the associated visual styles. If you are reading this in a feed reader, try opening the original page in a regular browser tab. I also included text descriptions for those of you using screen readers or other assistive technologies.
The CSS
display property determines which type of box an
element generates. CSS defines several box types, each with its own layout
rules. I'm only going to talk about two of them: block and inline.
I'll use this bit of pseudo-HTML to illustrate the difference:
Block boxes are placed vertically within their container, from top to bottom.
a, b, c, d { display: block; }
Description: The diagram below shows four rectangles in a vertical stack.
Inline boxes are placed horizontally within their container, from left to right. If they reach the right edge of the container, they will wrap around and continue on a new line below.
a, b, c, d { display: inline; }
Description: The diagram below shows boxes `a`, `b`, and `c` in a horizontal line from left to right, and box `d` in the next line.
Each box must contain only block children, or only inline children. When an DOM element contains a mix of block and inline children, the layout engine inserts anonymous boxes to separate the two types. (These boxes are "anonymous" because they aren't associated with nodes in the DOM tree.)
In this example, the inline boxes
b and
c are surrounded by an anonymous
block box, shown in pink:
a { display: block; }
b, c { display: inline; }
d { display: block; }
Description: The diagram below shows three boxes in a vertical stack. The first is labeled `a`; the second contains two boxes in a horizonal row labeled `b` and `c`; the third box in the stack is labeled `d`.
Note that content grows vertically by default. That is, adding children to a container generally makes it taller, not wider. Another way to say this is that, by default, the width of a block or line depends on its container's width, while the height of a container depends on its children's heights.
This gets more complicated if you override the default values for properties
width and
height, and way more complicated if you want to support
features like vertical writing.
The Layout Tree
The layout tree is a collection of boxes. A box has dimensions, and it may contain child boxes.
struct LayoutBox<'a> {
dimensions: Dimensions,
box_type: BoxType<'a>,
children: Vec<LayoutBox<'a>>,
A box can be a block node, an inline node, or an anonymous block box. (This will need to change when I implement text layout, because line wrapping can cause a single inline node to split into multiple boxes. But it will do for now.)
enum BoxType<'a> {
BlockNode(&'a StyledNode<'a>),
InlineNode(&'a StyledNode<'a>),
To build the layout tree, we need to look at the
display property for each
DOM node. I added some code to the
style module to get the
display value
for a node. If there's no specified value it returns the initial value,
enum Display {
impl StyledNode {
/// Return the specified value of a property if it exists, otherwise `None`.
fn value(&self, name: &str) -> Option<Value> {
self.specified_values.get(name).map(|v| v.clone())
/// The value of the `display` property (defaults to inline).
fn display(&self) -> Display {
match self.value("display") {
Some(Keyword(s)) => match s.as_slice() {
"block" => Display::Block,
"none" => Display::None,
_ => Display::Inline
_ => Display::Inline
Now we can walk through the style tree, build a
LayoutBox for each node, and
then insert boxes for the node's children. If a node's
display property is
set to
'none' then it is not included in the layout tree.
/// Build the tree of LayoutBoxes, but don't perform any layout calculations yet.
fn build_layout_tree<'a>(style_node: &'a StyledNode<'a>) -> LayoutBox<'a> {
// Create the root box.
let mut root = LayoutBox::new(match style_node.display() {
Block => BlockNode(style_node),
Inline => InlineNode(style_node),
DisplayNone => panic!("Root node has display: none.")
// Create the descendant boxes.
for child in style_node.children.iter() {
match child.display() {
Block => root.children.push(build_layout_tree(child)),
Inline => root.get_inline_container().children.push(build_layout_tree(child)),
DisplayNone => {} // Skip nodes with `display: none;`
return root;
impl LayoutBox {
/// Constructor function
fn new(box_type: BoxType) -> LayoutBox {
LayoutBox {
box_type: box_type,
dimensions: Default::default(), // initially set all fields to 0.0
children: Vec::new(),
If a block node contains an inline child, create an anonymous block box to contain it. If there are several inline children in a row, put them all in the same anonymous container.
impl LayoutBox {
/// Where a new inline child should go.
fn get_inline_container(&mut self) -> &mut LayoutBox {
match self.box_type {
InlineNode(_) | AnonymousBlock => self,
BlockNode(_) => {
// If we've just generated an anonymous block box, keep using it.
// Otherwise, create a new one.
match self.children.last() {
Some(&LayoutBox { box_type: AnonymousBlock,..}) => {}
_ => self.children.push(LayoutBox::new(AnonymousBlock))
This is intentionally simplified in a number of ways from the standard CSS box generation algorithm. For example, it doesn't handle the case where an inline box contains a block-level child. Also, it generates an unnecessary anonymous box if a block-level node has only inline children.
To Be Continued…
Whew, that took longer than I expected. I think I'll stop here for now, but don't worry: Part 6 is coming soon, and will cover block-level layout.
Once block layout is finished, we could jump ahead to the next stage of the pipeline: painting! I think I might do that, because then we can finally see the rendering engine's output as pretty pictures instead of just numbers.
However, the pictures will just be a bunch of colored rectangles, unless we finish the layout module by implementing inline layout and text layout. If I don't implement those before moving on to painting, I hope to come back to them afterward.
Lucas Rocha
Introducing dspec
With all the recent focus on baseline grids, keylines, and spacing markers from Android's material design, I found myself wondering how I could make it easier to check the correctness of my Android UI implementation against the intended spec.
Wouldn't it be nice if you could easily provide the spec values as input and get it rendered on top of your UI for comparison? Enter dspec, a super simple way to define UI specs that can be rendered on top of Android UIs.
Design specs can be defined either programmatically through a simple API or via JSON files. Specs can define various aspects of the baseline grid, keylines, and spacing markers such as visibility, offset, size, color, etc.
Given the responsive nature of Android UIs, the keylines and spacing markers are positioned in relation to predefined reference points (e.g. left, right, vertical center, etc) instead of absolute offsets.
The JSON files are Android resources which means you can easily adapt the spec according to different form factors e.g. different specs for phones and tablets. The JSON specs provide a simple way for designers to communicate their intent in a computer-readable way.
You can integrate a DesignSpec with your custom views by drawing it in your View's onDraw(Canvas) method. But the simplest way to draw a spec on top of a view is to enclose it in a DesignSpecFrameLayout—which can take an designSpec XML attribute pointing to the spec resource. For example:
<DesignSpecFrameLayout android:layout_width="match_parent" android:layout_height="match_parent" app:designSpec="@raw/my_spec"> ... </DesignSpecFrameLayout>
I can't wait to start using dspec in some of the new UI work we're doing Firefox for Android now. I hope you find it useful too. The code is available on Github. As usual, testing and fixes are very welcome. Enjoy!
September 02, 2014
Geoff Brown
Firefox for Android Performance Measures – August check-up
My monthly review of Firefox for Android performance measurements. This month's highlights:
– Eideticker for Android is back!
– small regression in ts_paint
– small improvement in tp4m
– small regression in time to throbber start / stop
This section tracks Perfomatic graphs from graphs.mozilla.org for mozilla-central builds of Firefox for Android, for Talos tests run on Android 4.0 Opt. The test names shown are those used on tbpl. See https://wiki.mozilla.org/Buildbot/Talos for background on Talos.
This test is not currently run on Android 4.0.
Measure of "checkerboarding" during simulation of real user interaction with page. Lower values are better.
12 (start of period) – 12 (end of period)
There was a temporary regression in this test for much of the month, but it seems to be resolved now.
Panning performance test. Value is square of frame delays (ms greater than 25 ms) encountered while panning. Lower values are better.
50000 (start of period) – 50000 (end of period)
Performance of history and bookmarks' provider. Reports time (ms) to perform a group of database operations. Lower values are better.
520 (start of period) – 520 (end of period).
An svg-only number that measures SVG rendering performance. About half of the tests are animations or iterations of rendering. This ASAP test (tsvgx) iterates in unlimited frame-rate mode thus reflecting the maximum rendering throughput of each test. The reported value is the page load time, or, for animations/iterations – overall duration the sequence/animation took to complete. Lower values are better.
6300 (start of period) – 6300 (end of period).
Generic page load test. Lower values are better.
940 (start of period) – 850 (end of period).
Improvement noted around August 21.
Startup performance test. Lower values are better.
3650 (start of period) – 3850 (end of period).
Note the slight regression around August 12, and perhaps another around August 27 – bug 1061878.
Throbber Start / Throbber Stop
These graphs are taken from http://phonedash.mozilla.org. Browser startup performance is measured on real phones (a variety of popular devices).
Note the regression in time to throbber start around August 14 — bug 1056176.
The same regression, less pronounced, is seen in time to throbber stop.
Eideticker for Android is back after a long rest – yahoo!!
These graphs are taken from http://eideticker.mozilla.org. Eideticker is a performance harness that measures user perceived performance of web browsers by video capturing them in action and subsequently running image analysis on the raw result.
More info at: https://wiki.mozilla.org/Project_Eideticker
August 25, 2014
Matt Brubeck
Let's build a browser engine! Part 4: Style
Welcome back to my series on building your own toy browser engine. If you're just tuning in, you can find the previous episodes here:
- Part 1: Getting started
- Part 2: HTML
- Part 3: CSS
- Part 4: Style
This article will cover what the CSS standard calls assigning property values, or what I call the style module. This module takes DOM nodes and CSS rules as input, and matches them up to determine the value of each CSS property for any given node.
This part doesn't contain a lot of code, since I've left out all the really complicated parts. However, I think what's left is still quite interesting, and I'll also explain how some of the missing pieces can be implemented.
The Style Tree
The output of robinson's style module is something I call the style tree. Each node in this tree includes a pointer to a DOM node, plus its CSS property values:
/// Map from CSS property names to values.
type PropertyMap = HashMap<String, Value>;
/// A node with associated style data.
struct StyledNode<'a> {
node: &'a Node, // pointer to a DOM node
specified_values: PropertyMap,
children: Vec


text:
The Disc Jockey from Lego Minifig Series 2 takes to the mic.
Taken with a Lumix Panasonic DMC-FS42.
Based on Tom Jones maybe : ))
It's not unusual to base LEGO minifigures on real people, but I don't think this particular one is :P
– Matt Roberts
This is one pretty cool looking Lego dude. :-D I would add some really hip in the house DJ lingo here, but I don't know any….nice pic Matt.
Ha! Me neither, so we'll just leave it at that :P Thanks :)
– Matt Roberts
He's even got a hairy chest, I second the Tom Jones suggestion! lol. Nice shot.
Thanks. As far as the Tom Jones thing goes – ask LEGO :P
– Matt Roberts
Great shot matt x
YAY!!! Thanks Helen. Am I getting better? =P
– Matt Roberts
a cordless mic even… (yo? … bro?)
perfect lighting Matt
Really? Whoa! Thanks :P
– Matt Roberts
Defiantly just needs plain background… just had an idea and as i typed it i thought ' no i want to do it lol' you have inspired me!
Aww, but share! o.o
– Matt Roberts
I reckon if you stuck a bit of actual glitter to his "teeth" where the suggested spark is, and shot it with the lighting just so, then… POW!
that would be the ultimate capture of the inanimate dude… perhaps some staged spotlights, particularly in the background, and dust motes swirling in the air also… could fake it with an incense stick and an LED torch…
Hmm. Might just give that a go at some point :)
– Matt Roberts
I shall when i have done it hehe
Great fun shot Matt
Great fun shot Matt
Thanks :)
– Matt Roberts

subset: commoncrawl


text:
We're sorry, we need more information to run your search. Please enter a last name (adding more details will improve your results).
Getting your hands on the right information about E Bennett is easy and simple if you turn to PeopleFinders.com. We enable you to access a plethora of facts about E Bennett that include age, possible relatives, age, and so on. E Bennett was born in [YOB] and is 65 years old. E's recent address is located in Fort Smith, AR. Based on our findings, E's include [RELATIVES], among others.
To make your search for E Bennett simple, we have provided all the data that we have with us. This database of info will enable you to hit upon the correct E and includes facts such as relatives, previous addresses, and age. If the E on this page is not the E you seek, you can explore the list of people with the Bennett above.
Refine your search process by keying in all the extra facts into the search fields. If you enter further details—first name, middle name, last name, city, state and/or age—we will be able to return the right results for your search of E Bennett. Once you have determined the exact E Bennett that you require, you can take your time exploring all of the public records for E Bennett that we have on hand.


text:
Ottawa watching Quebec right-to-die bill: Rona Ambrose
Federal Health Minister Rona Ambrose says she "can't predict the future" on where the debate on legalizing physician-assisted suicide will go.
|Report an Error
Share via Email
Federal Health Minister Rona Ambrose says she "can't predict the future" on where the debate on legalizing physician-assisted suicide in Canada will go, but "at this point" her government's position is clearly against the idea.
Talking to reporters following a meeting with her provincial and territorial counterparts on Friday, Ambrose indicated that her government is closely watching what happens to a bill on end-of-life care in Quebec.
"Quebec is going through the motions of discussion or debate in their legislature. Should that pass then obviously we will look to see what we do with that and if it does end up in court, then the courts will decide the jurisdiction," she said.
The debate over assisted suicide was reignited last month following the death of respected Toronto microbiologist Dr. Don Low from a brain tumour. A central figure in Canada's 2003 SARS crisis, Low made an impassioned deathbed video appeal to legalize dying with dignity.
While the issue was not on the official agenda of the nation's health ministers, it was hard for them to ignore.
"We did talk about it. It's not about opening a door, it's about recognizing a reality that this is an issue that people talk about in their families, but it is also a very emotional issue, it is a very divisive issue," Ambrose said.
The House of Commons defeated legislation to amend the Criminal Code to allow for assisted suicide in 2010 in a vote of 226 to 59.
But since that time, there appears to have been a sea change in attitude toward assisted suicide with polls showing the majority of Canadians support the idea.
Legislation was introduced in the Quebec national assembly in June that, if passed, would legalize medically assisted death.
"Provincial health ministers have every right to discuss this (but) because we did take a vote on this in parliament in 2010, that is our position at this point," Ambrose said.
"I can't predict the future, but if another vote was taken you would have to see that outcome," she added.
Another controversial issue addressed by the ministers was last year's cuts by Ottawa to refugee health benefits. Provinces argue that they have been forced to pick up the slack for Ottawa and absorb millions in health-care costs for refugees.
In a conciliatory gesture, Ambrose said she has already taken up their concerns with Employment and Social Develop Minister Jason Kenney.
"I listened to my colleagues and in fact after I saw their communiqué yesterday (Thursday), the first person who I contacted was minister Kenney," she said.
Ontario Health Minister Deb Matthews said that her government has been forced to absorb $20 million in refugee health expenditures.
"Hope spring eternal," she said when asked about the possibility of Ottawa reimbursing the province.
Top News
- Updated Wrongfully convicted Mississauga man free after 12 years in jail
- College finds MD guilty of sexual impropriety with teen patient
- NEW Huge mudslide shuts eastbound 403 in Hamilton
- Hospital fires staff who accessed patient files after suicide
- Video Duo charged in Vaughan wedding head butt
- Toronto gas prices to plunge over weekend
- NEW #PutOutYourBat pays moving tribute to Australian batsman Phil Hughes
- Star Wars VII: here's the teaser
commercial promo
commercial promo
commercial promo
Popular Photo Galleries
News | Toronto Star
News | Toronto Star
News | Toronto Star


text:
Holdays.net Home
Kachina Dolls: Authentic Native American Navajo
Authentic Native American Kachina Dolls: Navajo dolls are used to represent our spiritual connection. These are not manufactured in China but are
the genuine article made by Navajo Native Americans,using real feather,
fur, etc.
Go to view dolls & choose.
State doll name and color in your Pay Pal order.
Badger (south)—healers, aggressiveness, perseverance
Bear (west)—healer, strength, introspection
Buffalo—strength, endurance to rise above one's weaknesses
Butterfly--Butterfly directs the medicine man to ingredients that can be used in medicine. The Butterfly Kachina brings together unmarried men and women. During the butterfly social dance they appear as a pair, one female and one male.
Deer—abundance in the natural world
Eagle (zenith or sky)—spirit, a connection to the Divine
Hawk—see things differenlty, Change
Owl—wise, smart, patient, the unseen
Snake—a force in life, death and rebirth
Wolf (east)—teacher, pathfinder on the journey of survival, familly
Choose the Color:
Blues & Greens
Golds & Tans
Eagle: Spirit Connection, Strength & Protection
Star:Control Planet & star influence
Butterfly: Soul Mate
Bear: Healing
Buffalo:Strength & Endurance
Deer: Abundance
Badger: Healing & Perseverance
Owl: Wisdom
Rainbow: Peace & Harmony
Snake: Re-birth
Crow Mother
Medicine Man: Healing
Kokopelli: Fertility
Red Tail Hawk: Change (RED ONLY)
This item has been shown 2624 times.
Navajo Native American Comanche Dancer By Largo Sku#222073
Trailblazers Amn Indian Pioneers
Navajo Native American White Cloud Kachina Dancer Sku#222057
Navajo Eagle Kachina Doll Item-a Handmadejacida Loley
Navajo Eagle Kachina Doll Item-c Handmadejacida Loley
Navajo Eagle Kachina Doll Item-b Handmadejacida Loley
Stunning Native American Hopi Kachina Doll Sculpture Flute Player 1st Mesa Signe
4 Beautiful Little Vintage Native American Clay? Storybook Dolls? Signed .
Vintage Inuit Eskimo Alaskan Yupik ~6" Doll Figure: Wood Face, Fur, Suede
Koshare Clown Football Player Kachina By Bertha Wood - Navajo Native American


text:
813 W. Douglas
Wichita, Kansas 67213
GreenLeaf Chiropractic
Main Navigation
Types of Care
Infant Care
Toddler Care
Children & Teenagers
Nutritional Therapy
First Visit
About Us
Welcome to Greenleaf Chiropractic in Wichita, Kansas...
Your Health.
Your Life.
Your Well-Being
Welcome to
Chiropractic located in Wichita, Kansas. We are excited that you have found our website. To schedule an appointment call our Wichita, Kansas office at 316-440-4052.
Stop hurting and get in to see your Wichita Chiropractors Today!
Chiropractic care can improve your quality of life. If you are currently experiencing pain come in and visit Wichita, Kansas Chiropractors Dr. Robin Henderson and
Dr. Kaileigh McLaughlin. It is important to remember that you achieve the best Chiropractic results by visiting on a routine basis. Visiting the Chiropractor will make you feel so much better!
Our Wichita, Kansas Office Hours
Mondays: 9-1 & 3-6
Tuesdays: 9-1 & 3-6
Wednesdays: 9-1 & 3-6
Thursdays: 9-1 & 3-6
Fridays: Closed
Come and visit our
Wichita, Kansas Chiropractic
office today!


text:
Book review: 'Its Head Came Off by Accident' a lumbering ranch-life memoir
"ITS HEAD CAME OFF BY ACCIDENT," by Muffy Mead-Ferro, TwoDot, $14.95, 170 pages (nf)
Despite its intriguing title, "Its Head Came off by Accident" is only a mildly entertaining read.
Author Muffy Mead-Ferro was raised in the wilds of Wyoming. Her daily life included face to face amblings with Hereford cattle that were raised on the family ranch. But while immersed in the day-to-day workings of animals and land, she always felt a little bit out of place, especially when she compared herself to her mother, Mary, a proficient but stony feature of the ranch.
As an adult, Mead-Ferro traded the saddle and tractor for big city dreams. She kept her toe in the family business by purchasing an old pig farm on the border of Wyoming and Idaho but only spent time there during the summer months.
Planted with her husband and two children in Salt Lake City, Mead-Ferro unexpectedly receives a package in the mail that changes her life. Startled to find the clothes her mother was wearing when killed during a cattle drive inside the box, Mead-Ferro is suddenly compelled not to give up on ranching but stretch into her roots and continue that legacy.
The book sketches moments pulled from Mead-Ferro's youth on the ranch as well as tidbits from her adult attempts at continuing that way of life. Revealing childhood adventures in forgotten junk sheds, encounters with heroic cowboys and the life and death of precious livestock during her learning experiences and occasional blunders fill the pages with unique flashes of farm living.
This inside look at ranch life in rural Wyoming had potential, but sadly, the project fell flat. Although some of the anecdotal glimpses into life on a cattle ranch are amusing, Mead-Ferro fails to connect readers with her story in any tangible way.
The book feels like a yawning evening sitting around swapping farm stories with acquaintances. While the tales are occasionally intriguing, there is a depth missing that leaves the account feeling tepid.
There are quirky characters and comical moments, but overall the book is tedious and lackluster. There is a lot of dry information to sift through in order to find the entertaining fragments.
If you go ...
What: Muffy Mead-Ferro book signing
When: Tuesday, Oct. 30, 7 p.m.
Where: The King's English, 1511 S. 1500 East, Salt Lake City
Web: kingsenglish.com
Melissa DeMoux is a stay-at-home mother of six young children who lives in West Valley City. Her email is email@example.com and she blogs about her adventures in motherhood at demouxfamily.blogspot.com.
- Capturing 'Mormon Faces': LDS mother,...
- Mormon creator of 'Battlestar Galactica'...
- Consumer group lists '10 worst toys' for kids
- A community of theater: Utah theater...
- 'Fire is catching,' so catch up with Katniss
- 'Mockingjay, Part 1' opens with $123 million
- Local theaters bringing stars,magic and...
- What's new: 'Walk Beside Me' adds vibrancy to...
- Mormon creator of 'Battlestar... 17
- Jennifer Lawrence: Privacy loss that... 4
- FanX returns in January with 'Star... 4
- Consumer group lists '10 worst toys'... 3
- Gift Guide: 3 ways to watch streaming... 3
- Model-TV host Dickinson accuses Cosby... 2
- Cookbooks see growth, but slow to move... 1
- 'Fire is catching,' so catch up with... 1


text:
Browser does not support script.
"Crime and policing has always been at the forefront of public debate. Yet academic researchers and practitioners have not collaborated as fruitfully as they might have to understand 'what works' by way of interventions and the costs and benefits of alternate interventions. There is however reason to hope that there will be a push towards more evidence-based policing."
Read full opinion
Policing is perhaps one of the most complex areas of government, invariably relying upon expert advice from a number of departments ranging from justice to welfare and health to education. I therefore welcome this collobarative 'joined-up' thinking approach between academics and practitioners. It will go someway towards achieving a sound and evidence-based policing policy.
Print this page
Download as PDF
Powered by Contensis


text:
Video Chat Separates Google Plus From Facebook And TwitterPosted by Sian Phillips under Social Media
From http://tweakyourbiz.com 715 days ago
Made Hot by: ObjectOriented on December 13, 2012 1:29 pm
Okay, name the last time you had a video chat using your social networking account on Facebook and Twitter. No, no, fancy add-ons don't count. Just straight video chat without having to put in the extra effort. Anyone? Anyone?
Well, so long Facebook and Twitter, GooglePlus just took the lead.
Well, so long Facebook and Twitter, GooglePlus just took the lead.
Sponsored Content
Who Voted for this Story
Top BizSugar Users
This week's most active BizSugar users. Join Them!
Written by adukes81
711 days ago
711 days ago
With video becoming more and more popular I think the Hangout feature could really separate G+ form Facebook/Twitter. I have yet see the Hangout feature, but am planning on doing a weekly show on social media in 2013.
Written by elainerogers
714 days ago
714 days ago
Fair play to leading people (such as Alicia) to take on social networking and make good and productive use of it. I have seen a lot of passive aggressive bullying also, so it's nice to see positivity.
Google+ and hangouts have been "hanging" for a while, but you are right Ann, they seem to be taking off slowly slowly, but surely :)
Google+ and hangouts have been "hanging" for a while, but you are right Ann, they seem to be taking off slowly slowly, but surely :)
Written by lyceum
714 days ago
714 days ago
I participated in a Hangout at a media fair some time ago. We were invited to "hang out" in Google+'s booth and demonstrating how to use video chats and at the same time promote our upcoming unconference (potluck conference), WebCoast. Google was one of our sponsors of WebCoast. I am waiting to see that hangouts will be used more in future, e.g., as an alternative to Twitter chats.
Log in to comment or register here.
Three Key Voluntary Policies for WomenOctober 8, 2014
Today 4 in 10 women are the sole or primary breadwinners for their families,¹ and they do more than twice the amount …Sponsored By Aflac
Michele Welch: BizSugar "Contributor of the Week"
Woo-hoo! It's that time again. So, please put your hands together (or better yet, give us a nice tweet, Facebook … MoreMore Contributors
Editor's Picks
- 5 Reasons To Put It In Writing
- Benefits of Digitising Your Company\'s Physical Records
- What keeps a coach like you up at night?
- Technical Entrepreneurs Often Fail By Early Adopters
Niall Devitt
Niall Devitt advises organizations how to plan, design and implement social strategies that generate real business returns. In 2009, Niall co-founded TweakYourBiz.com …