Code Monkey home page Code Monkey logo

android-pagecurl's Introduction

NOTE

As of this commit all "pages" will be 2-sided. There's a new class CurlPage, using which you can assign a separate texture on both sides, one for front side only, or same texture can be shared on both sides. CurlPage contains also color values for blending which allows you to e.g share texture on both sides but do alpha blending only on back side of the page, leaving you with exactly same effect what earlier version of this example application did. This time with the difference there's some more freedom included.

Here's an example video from cags12 showing 2-sided page support in landscape mode;

[http://www.youtube.com/watch?v=iwu7P5PCpsw]

Introduction

Project for implementing 'page curl' effect on Android + OpenGL ES 1.0 (possibly 1.1/2.0 too if there's clear advantage in using them).

The source code is released under Apache 2.0 and can be used in commercial or personal projects. See LICENSE for more information. See NOTICE for any exceptions, these include namely the application icon and images used in the demo. Besides these exceptions, let it be as-is implementation or - maybe more preferably - as an example for implementing your own effect.

For the ones without Android development environment, and/or people willing to take only a brief look on what's happening here, there are a few video captures. While person responsible for capturing them is not a happy owner of Android device yet It's truly hoped performance is not that poor on actual device compared to what you see here;

So what you saw there;

  • There are approximately 26 + 26 + 4 + 4 = 60 vertices at most.
  • 8 vertices for underlying pages, 4 for each.
  • ~26 vertices for curled page + ~26 vertices for fake soft shadow. These numbers are maximum values and vary depending on curl position and angle.
  • Rendering them as triangle strips end up producing approximately 50 polygons at most. To give some perspective rendering a cube without back face culling requires 8 vertices and 12 polygons.

What you didn't see;

  • There is an experimental flag unable to show on emulator. With the kind help of Andrew Winter it was possible to do some experimenting on using touch pressure information. If you go and call CurlView.setEnableTouchPressure(true), curl radius will be adjusted based on the touch pressure. The more you press, the smaller it gets. Currently it's a vast one line 'hack', simply to show off it's there, mostly for experimenting, but who knows. If someone takes the work and calibrates it properly it might turn out to something.
  • Z-buffering, really, we don't need to do depth check giving us a minor performance boost.
  • Lightning, it's a more of a trick we use here, leaving us with something very close to flat shading actually.
  • Perspective projection. Since it's very much easier to map render target to screen size using orthogonal projection it's used by default. For quick prototyping you can enable it though, check USE_PERSPECTIVE_PROJECTION flag in CurlRenderer.

ToDo

  • Adjust fake soft shadow calculation. Current 'drop shadow', cast behind curl, implementation is not exactly what one wants necessarily. It might be better strategy to leave some 'softness' for situations in which radius is close to zero. Currently it means shadow is decreased to non-existent. Well, that's how shadows work, but considering from usability side..
  • Add some details to make it a bit more book alike.

Some details

Implementation can be divided roughly in two parts.

  • CurlMesh - which handles actual curl calculations and everything related to its rendering.
  • CurlView - which is responsible for providing rendering environment - but more importantly - handles curl manipulation. Meaning it receives touch events and repositions curl based on them. While this sounds something utterly trivial, it really isn't, and becomes more complex if curl didn't happen around a cylinder. Depending on what you're trying to achieve of course. For me it was most important from the beginning that 'paper edge' follows pointer at all times.

Anyway, here are a few links describing this page curl implementation somewhat well. Only difference is that instead of using a static grid an algorithm which 'splits' rectangle dynamically regarding curl position and direction was implemented. This is done in order to get better render quality and to reduce polygon count. It's an absolute win-win situation if these things can be combined with limited amount of extra calculation to ease the work of renderer. In this particular case, we really do not want to draw polygons separately if they lie next to each other on same plane. It's more appropriate to have more vertices used for drawing rotating part instead. On negative side lots of code complexity comes from the need for creating a triangle strip for rendering. Using a solid grid such problems do not occur at all.

It isn't very difficult to see what happens here once you take a paper and simply curl it to some direction. If you fold paper completely, cylinder, curl happens around, radius becomes zero, making it more of a 2D effect. And likewise folding the paper so that curl radius is constant most of the characteristics remain - most importantly there is a line - at the center of this 'cylinder' - which has constant slope not dependent on radius. Its distance from the point you're holding the paper varies only. Keeping this in mind makes curl position handling based on touch events a lot easier compared to using a cone as solid curling is done around. For information on using a cone, it's highly recommended to take a look on W. Dana Nuon's blog post on the topic. Chris Luke's article is a good read too, even though he came to pretty much the same conclusion as me, better to go with cylinder instead.

Curl/cylinder is defined with three parameters, position, which is any point on a line collinear to curl. Direction vector which tells direction curl 'opens to'. And curl/cylinder radius. 'Paper' is first translated and rotated; curl position translates to origin and then rotated so that curl opens to right (1, 0). This transformation makes it a bit easier to calculate rotating vertices as all vertices which have x -coordinate at least 0 are not affected. Vertices which have x -coordinate between (-PIradius, 0) are within 'curl', and if x -coordinate is less than equal to -PIradius they are completely rotated. And scan line algorithm for splitting lines within rotating area is more simple as scan lines are always vertical. Not to forget rotating happens around y -axis as cylinder center is positioned at x = 0. And after we translate these vertices back to original position we have a curl which direction heads to direction vector and it's center is located at given curl position.

  1. At first there is a piece of paper represented by 4 vertices at its corners.
    Paper 1
  2. And let's say we want to curl it approximately like this.
    Paper 2
  3. Which could results in something like these vertices. Adding more scan lines within the rotating area increases its quality. But the idea remains, bounding lines of original rectangle are split on more/less dense basis.
    Paper 3

But, once again, using a piece of paper and doing some experiments by yourself works much more as a proper explanation than words, mine at least, can tell. And maybe gives some idea how to make better/more realistic implementation. Happy page flipping :)

Sources of inspiration

Some YouTube links to page curl/flip implementations which were found interesting for a reason or another.

Not to forget many of the true real-time rendering heros. One day We're about to beat them all. One day. Right?

android-pagecurl's People

Contributors

cags12 avatar harism avatar rukiman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-pagecurl's Issues

Setting the Page Size

i'm currently using your page curl source code and i want to know where could i set the page size?

i want to set the bitmap on the whole page.

or where could i set the scale to make the bitmap cover the whole page.

Adding video on page

Dear harism,
Thanks for this great source code, I want to add video on page either left/right. Can you please guid me?
Thanks

Please help about creating auto-animate

Hi, Harism.

I am really appreciate your project and effort.

I have read the post before and you said the TouchEvent is the key to make auto-animate function, I would like to ask how can I make use of it as I have no ideas about how to pass a TouchEvent to the view.

Crash when orientation changes

Sometimes when orientation changes I'm having a crash. Don't know why it is happening because only occurs sometimes when doing fast movements of rotation.

I can't to find wax to fix it now. How can I fix it?

Here is the crash log:

01-25 12:16:30.429: W/SurfaceView(2816): mSurface is not valid! creating=true formatChanged=true sizeChanged=true visible=true visibleChanged=true surfaceChanged=false realSizeChanged=true redrawNeeded=true left=false top=false
01-25 12:16:30.429: W/SurfaceView(2816): java.lang.RuntimeException
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.SurfaceView.updateWindow(SurfaceView.java:532)
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.SurfaceView.access$000(SurfaceView.java:81)
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:169)
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:590)
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1710)
01-25 12:16:30.429: W/SurfaceView(2816): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2539)
01-25 12:16:30.429: W/SurfaceView(2816): at android.os.Handler.dispatchMessage(Handler.java:99)
01-25 12:16:30.429: W/SurfaceView(2816): at android.os.Looper.loop(Looper.java:137)
01-25 12:16:30.429: W/SurfaceView(2816): at android.app.ActivityThread.main(ActivityThread.java:4514)
01-25 12:16:30.429: W/SurfaceView(2816): at java.lang.reflect.Method.invokeNative(Native Method)
01-25 12:16:30.429: W/SurfaceView(2816): at java.lang.reflect.Method.invoke(Method.java:511)
01-25 12:16:30.429: W/SurfaceView(2816): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
01-25 12:16:30.429: W/SurfaceView(2816): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
01-25 12:16:30.429: W/SurfaceView(2816): at dalvik.system.NativeStart.main(Native Method)

01-25 12:16:30.445: E/GLSurfaceView(2816): eglCreateWindowSurface
01-25 12:16:30.445: E/GLSurfaceView(2816): java.lang.IllegalArgumentException: Make sure the SurfaceView or associated SurfaceHolder has a valid Surface
01-25 12:16:30.445: E/GLSurfaceView(2816): at com.google.android.gles_jni.EGLImpl._eglCreateWindowSurface(Native Method)
01-25 12:16:30.445: E/GLSurfaceView(2816): at com.google.android.gles_jni.EGLImpl.eglCreateWindowSurface(EGLImpl.java:90)
01-25 12:16:30.445: E/GLSurfaceView(2816): at android.opengl.GLSurfaceView$DefaultWindowSurfaceFactory.createWindowSurface(GLSurfaceView.java:798)
01-25 12:16:30.445: E/GLSurfaceView(2816): at android.opengl.GLSurfaceView$EglHelper.createSurface(GLSurfaceView.java:1065)
01-25 12:16:30.445: E/GLSurfaceView(2816): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1433)
01-25 12:16:30.445: E/GLSurfaceView(2816): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)

android_page_curl-How add more than 5 image in curlview

hi.. this is ashish saini. i get more help with this tutorial.realy its very helpful.But i could not add more than 5 image in CurlView class.i wana to add 57 images on first activity and on clik of images i wana to start ne activity with the description of images.And May i apply it for text view to read next and previous story using this animation?
pls help me.

Add Text on each page?

Hello,
I'm using curlview to create a book.
Do you know if you can add text on each page?
Can you create an independent effect of curlview to show and hide the text?
Maybe we could add two images on a page, the first would be the background and the second text, but could each have a different visual effect?

Thank you!

CurlView with no margins isn't working correctly

I've made some changes in the SizeChangedObserver at the CurlActivity.java. Basically I wanted the CurlView with no margins, so I set them to 0 (zero).

private class SizeChangedObserver implements CurlView.SizeChangedObserver {
        @Override
        public void onSizeChanged(int w, int h) {
            if (w > h) {
                mCurlView.setViewMode(CurlView.SHOW_TWO_PAGES);
                mCurlView.setMargins(0, 0, 0, 0);
            } else {
                mCurlView.setViewMode(CurlView.SHOW_ONE_PAGE);
                mCurlView.setMargins(.1f, .1f, .1f, .1f);
            }
        }
    }

When I'm trying to do the curl effect something wrong happens with the curl. The edge, shadow and corner of the page are slowlly desapearing while curling.
Am I making something wrong? What's causing this?

Background color is reset to black after screen is recreated

I have changed the default background color in the CurlActivity to white (mCurlView.setBackgroundColor(0xFFFFFF);).
The background will reset to black after turning the smartphone screen on/off (onSurfaceCreated and onSurfaceChanged are called after this).
The problem is caused by the mBackgroundColorChanged variable. Setting it to true in onSurfaceChanged seemed to work...

Animation very slow with large images

First of all thank you for this awesome component, Harri.

I've been trying to make a comic reader using this page-curl implementation however when using big images the curlview takes a long time between the ACTION_DOWN event and the actual start of the animation. (Around 2 secs, tested on many real devices)

The delay seems to occur in CurlMesh.onDrawFrame, but I wasn't able to figure out what's happening.

Full screen problem

I'm using the page curl effect with a ViewPager. The bitmaps are taken to the fragments contained in the ViewPager using the "grabIt" method (http://kcy.me/cm7m). All was working fine until I changed the application theme to use fullscreen (by removing the status bar), so now, when the page curl effect is ongoing, the image is blurry and hurts my eyes trying to focus. ¿Is it a bug? ¿Any recommendation?

How do i add background.

when i add back groud to the it then it only show me the back ground and nothing else pls tell me how to fix this .

Left-to-right curl

Hello :)

Thank you very much for this great project :)

I noticed that this project supports right-to-left curl in order to bring up a new page, and left-to-right one when you want to navigate to the previous page.

I just wondered: can you please provide us with one of the opposite matter? I mean, to curl from left-to-right when navigating to a new page and from right-to-left when navigating to the previous page (exactly mirroring the current code).

Thank you :)

integrate with listview

am try to open listview instead of image drawable in CurlView

please help how integrate with listview

Invoke redraw/repaint

I´m trying to force redraw the image at navigation time, change page on touch, but invalidade() and requestRender() doesn´t not force redraw, anyone has some tip to do this? I try to invoke startcurl and image is redrawed, but I need to back to previous page and go ahead again to view page redrawed.

Flickering in Opengl2.0 version

Hi,

I'm experiencing some flickering when turning the page slowly in the OpenGL 2 version (the next SIDE_FRONT page flashes for a split second and then disappears).
No flickering in the master branch.
Devices tested so far:
Galaxy Nexus, 4.2.2
Asus Transformer tf101, 4.2.2

Any idea how to fix that?
Thanks.

Downwards through the top of the touch event

We appreciate your business.

Page through the touch events will move left to right.
Downwards through the top of the touch event (or in the opposite direction) would like you to move.
With these functions, an option to all?

How To apply Onclick listener

Hi ,
Please solve my issue or give any suggestion?
I have already post on stack overflow link is bellow:-

 http://stackoverflow.com/questions/13859425/how-to-apply-click-listener

OnResume() not work after Home button pressed and back to app

Hi, I have found a issue.
In the app when I pressed Home button , and the again click on the app. It show me only back pages for curl, no images found.
The same issue is when screen is screen. Then I just unlock the screen and it again show only black pages.

Same is when I try to put this in the "Tabed Activity". 1 tab is for curl. But when I switch to other tab , and then back to the curl page tab. It show only the black pages. No images to curl.

Please check this out.

Thanks

CurlView flickers black on first draw

Hi, I'm trying to integrate this library in my app. My CurlView is set to 'invisible' in my layout file, and I set it to visible after the activity has started, when a certain event occurs. The problem I'm experiencing is that the CurlView turns black for about a second when it is first drawn after it has been set to visible, and then loads the provided bitmaps.
I managed to replicate this issue in the following derivation of your CurlActivity:
https://gist.github.com/8c0156895e0661821882
The layout is:
https://gist.github.com/3b4aba27fd2526180ede

Can you please help me?
Thanks ;)

Non flipped image on "left" side. - 2 page view

While in landscape (2 pages at a time) I can't figure out how to display the left (back ) image non flipped.

There must be a flag that I am missing but any help would be great. Awesome work.

top to bottom

make it be able to flip vertically................
Can you change the Page Curl code so that it can not only flip left to right but top to bottom?

CurlView displaying the reverse side of image

Hi, I found an issue,

Pre-requisite:

  • CurlView is in Single display mode. Using the right to left curl

Steps to Reproduce:

  • Turn the last page so that no page is displayed in CurlView.
  • Jump to a certain page using setCurrentIndex

Problem:
-Page is displayed in reverse side (But updates the correct image side after any touch event)
-This only happens if selecting image occurred after the last page is turned

Can you please tell how to fix this? Thanks in advance,

opengl es 2.0 migration

Is it big deal to migrate this project to open gl es 2.0 ? I need this because I want to remove the non power of two size limitation for textures. If you don't have time for this I'll deal with it next week.

Pinch to zoom?

I need the pinch to zoom and pan features over pages and I would like to contribute to the project in order to achieve it.

Do you have any suggestion on where and how to start ?

I'm thinking of an extension of the CurlView that inherits its features and add the zoom code and the listeners for the touches.

How to use RGB_565?

I am using the OpenGL ES 2.0 version and loading rather big bitmaps. What are the possible ways to reduce the memory footprint? I switched off the rendering of the left page (only portrait is allowed).

Switching from ARGB_888 to RGB_565 results in a deformed (skewed) texture.
I tried switching the color config in the loadBitmap method, in the following line:
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

BTW. If I am returning to previous pages (turning the pages backwards) then the current page flickers for a brief moment. This happens only in the ES 2.0 version.

Thanks for the help.

Appending Audio files for each page-curl

Hi Harism,

     Thank u very much........!!

My issue is.....

  1. I appended the audio files for each page curl, I fallowed only in portrait mode, While I am curling the page from right to left the audio files are palying according to page index but while I am curling page from left to right the audio files are not playing respectively. The audio file is playing before's to the present page.....!!

That means page-1, audio-1

  from  left to right ----->   page-1, audio-1....page-2,audio-2.......  respectively  but

  from right to left------->   page-2, audio-1

so i changed the code at......

curlview.java.........line no:579 private void startCurl(int page) method

if (mCurrentIndex > 1) {
Bitmap bitmap = mBitmapProvider.getBitmap(mPageBitmapWidth,mPageBitmapHeight, mCurrentIndex - 1); ( instead of -2 i kept -1)

so now audio is playing in according to the index for both left to right and vise versa

but here I am not able to see th 1 st page curl when i went back after 3 page curls

plz help me in logic where i am lagging......!!

HTML (WebView)

Hello! I have tried to use WebView, but unsuccessfully. Empty black screen :( How to make a webview instead of pictures? Thanks!

Wrong Index number of images being returned

If we move from start till end the index number that is returned is write but for example if we are at index 3 and flip 1 page back then instead of 2 the index returned is 1.
I am reading the index in log in getBitmap(int width, int height, int index) in CurlActivity.java file.

            public Bitmap getBitmap(int width, int height, int index) {
        Bitmap b = Bitmap.createBitmap(width, height,
                Bitmap.Config.ARGB_8888);
        b.eraseColor(0xFFFFFFFF);
        Canvas c = new Canvas(b);
                    Log.i("index",index+"");                                  // using to print the index

Or please tell me at which place in source code I can get the correct index number.Actually I need the correct index number of images while flipping on both sides.

Page curled little at bottom right

Hi,

I am using android 3D page curl to develop a ebook reader kind of application. I am not much familiar with OpenGl and also I am new to android.Can anyone help in where to set the values for the initial page offset for x and y movement. I want the page to be curled slightly at the bottom right to indicate that there are more pages. Can anyone please give me direction on how to achieve this.

Thanks in advance.

RTL Support

How can i support RTL paging curl
i've tried to modify the "startCurl" method
but things seems more complicated to me, and didnt work
can you suggest anything to help me?

software license

Hi Harri, can you please add a suitable software license to your library project. I sent you an email with more details to your gmail account. Look forward to hearing from you soon.

Get Drawing Rect

Hi,

I can change margins in SizeChangedObserver, but how to get a relative position to screen size? How Can get Rect from drawed book when my screen size is 1280x720?

Understand (Read/PageCurl) State

how can i decide/understand page curl has been finished and application at read page state?
i do pdf reader and it takes sometimes. So that on read state other pages creating and adding a vector with threads.
but in that time i need to force user wait for reading and adding other pages to vector. (in read page state.)

read page state is: curling page is done and user ready to read this or these page(s).

A right to left page curl lead touch event

I think it would look a bit more natural if a right to left page curl were to lead the touch event in SHOW_ONE_PAGE mode.

Start by changing the onSizeChanged funtion in CurlActivity to this

public void onSizeChanged(int w, int h) {
mCurlView.setViewMode(CurlView.SHOW_ONE_PAGE);
mCurlView.setMargins(.1f, .5f, .1f, .5f);
}

If view the application in landscape mode and do a right to left page curl the the curl will never reach the left side of the screen; But if you do a left to right curl the animation will look very nice when moving your finger left and right.

image not showing properly in android 2.3.5

i just put the source code and execute it .it dosnt execute right.after Obama pic it shows two blank pages..and soo on the problem is not solving i didn't change any thing in code.

only images or also views?

Hey, how can I use this lib with LinearLayout instead of images (BitmapProvider)?
Any code examples. Thx!

shadow center of pages(left and right)

Dear Hairson,
First of all I would like to thank you and really appreciate your work. One needed one help from your side. My boss wants to see the shown between the pages(left and right), as it looks like real book.
can you help me?
Thanks

How to move specific index page

I'd like to move specific index page.

eg,
After you add the bookmark at specific index page,
you can restart to read it from there.

I'm trying like below.
updatepage(mCurlpage, width, height, index);
or
mCurlView.startCurl(index);

Do I have to set up new classes?

If you know simple method,
Please let me know that.

Best,

is it posible?

I'm trying to change images dinamically at any time.
Why? well, i want to download images asynchronous from web and display them like a book . I do that with other views but look cool with your.

To be honest, i don't know nothing about graphic programming and i'm lost.
By now, i get something by calling updateBitmaps() and requestRender(), but look bad if i'm paging, animmation stop and more errors.

Any tip or key methods?

Thanks you very much

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.